I used the embedded-swift example blink as a starting point that builds nicely and runs on an ESP32C6, using VSC on macOS. I would like to connect to wifi.
I have checked that esp_wifi, etc. components are loaded. However, just adding the header files to BridgingHeader.h results in a mass of errors:
#include <WiFi.h>
The first error is:
- error: unknown type name 'class'
This is the error you get when you invoke the C compiler rather than the C++ compiler. If I remove this header and use some of the subsidiary ones, such as:
Then these do not error and I can make successful calls to:
var ret = nvs_flash_init()
I am not experienced in CMake, but I guess the error is caused by stripping out the normal CMakeLists.txt to make it work with embedded swift. And lack of CMake knowledge means I have no idea where to start to try to fix it!
# Register the app as an IDF component
idf_component_register(
SRCS /dev/null # We don't have any C++ sources
PRIV_INCLUDE_DIRS "."
LDFRAGMENTS "linker.lf"
)
idf_build_get_property(target IDF_TARGET)
idf_build_get_property(arch IDF_TARGET_ARCH)
if("${arch}" STREQUAL "xtensa")
message(FATAL_ERROR "Not supported target: ${target}")
endif()
if(${target} STREQUAL "esp32c2" OR ${target} STREQUAL "esp32c3")
set(march_flag "rv32imc_zicsr_zifencei")
set(mabi_flag "ilp32")
elseif(${target} STREQUAL "esp32p4")
set(march_flag "rv32imafc_zicsr_zifencei")
set(mabi_flag "ilp32f")
else()
set(march_flag "rv32imac_zicsr_zifencei")
set(mabi_flag "ilp32")
endif()
# Clear the default COMPILE_OPTIONS which include a lot of C/C++ specific compiler flags that the Swift compiler will not accept
get_target_property(var ${COMPONENT_LIB} COMPILE_OPTIONS)
set_target_properties(${COMPONENT_LIB} PROPERTIES COMPILE_OPTIONS "")
# Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header).
set(SWIFT_INCLUDES)
foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ")
string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ")
endforeach()
foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-Xcc ")
string(CONCAT SWIFT_INCLUDES ${SWIFT_INCLUDES} "-I${dir} ")
endforeach()
# Swift compiler flags to build in Embedded Swift mode, optimize for size, choose the right ISA, ABI, etc.
target_compile_options(${COMPONENT_LIB} PUBLIC "$<$<COMPILE_LANGUAGE:Swift>:SHELL:
-target riscv32-none-none-eabi
-Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library -Osize
-Xcc -march=${march_flag} -Xcc -mabi=${mabi_flag}
-pch-output-dir /tmp
-Xfrontend -enable-single-module-llvm-emission
${SWIFT_INCLUDES}
-import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
>")
# Enable Swift support in CMake, force Whole Module builds (required by Embedded Swift), and use "CMAKE_Swift_COMPILER_WORKS" to
# skip the trial compilations which don't (yet) correctly work when cross-compiling.
set(CMAKE_Swift_COMPILER_WORKS YES)
set(CMAKE_Swift_COMPILATION_MODE_DEFAULT wholemodule)
set(CMAKE_Swift_COMPILATION_MODE wholemodule)
enable_language(Swift)
# List of Swift source files to build.
target_sources(${COMPONENT_LIB}
PRIVATE
Main.swift
Led.swift
)
Thank you very much for your reply. Including the one line
-cxx-interoperability-mode=default
Gets me further, but it then errors with:
esp-idf/components/esp_wifi/include/esp_wifi.h:251:9: note: macro 'WIFI_INIT_CONFIG_DEFAULT' unavailable: function like macros not supported
I have encountered this before when wrapping libraries for swift on a raspberry pi, it was only one and easy to re-write the macro as a swift function in that context. I get the feeling that this approach might not work here. Is there a better way? Thank you again for your help.
I tried creating a stub function for WIFI_INIT_CONFIG_DEFAULT and it then gives a final error in linking:
undefined reference to `_swift_exceptionPersonality'
There is an outstanding ticket on GitHub for this same error, which I see you are aware of:
I have done some digging in the source. It looks like the symbol is missing because the function isn't included in the build. Is it as simple as changing the #if directive to enable its inclusion?
I tried building my own toolchain having removed the #if, but after about 40 minutes it reports an error about a missing target that I can't resolve. I've misplaced the name of the target but I will find it later and update this post.
undefined reference to `_swift_exceptionPersonality'
you need to tell Clang to disable exceptions support for the C++ code (which is likely what you want anyway, most embedded platforms don't want the relatively heavyweight unwinding runtime that is needed for C++ exceptions to work...):
At link-time.
It's a bit odd, because WiFi.begin(said,pwd) fails at compile-time saying it doesn't exist. I thought it was implicitly included in the build, but I have tried adding it explicitly but with no difference. I can lots of esp_wifi/lib/esp32c6/lib... in the log.
However, I can successfully build an image with the lower-level calls, such as:
esp_wifi_scan_get_ap_num(&ap_count)
I thought it might be that I hadn't successfully downloaded the dependencies, but I can grep wifiscanclass in a number of places in the build folder.