How do I Add C++ Files to Embedded Swift Project

How do I add C or C++ files to the project that can be used in Embedded Swift (ESP32)?

I'm exploring the Embedded Swift Sample Projects (ESP32 LED Strip) esp32-led-strip-sdk

I have existing code that I want to add, but I haven't been able to get Embedded Swift to compile with non-Swift C/C++ code.

In the CMakeLists.txt it looks like I need to modify two areas:

# 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"
)

and

# List of Swift source files to build.
target_sources(${COMPONENT_LIB}
    PRIVATE
    Main.swift
    LedStrip.swift
)

I attempted to expose it, but I don't really understand how it needs to be formatted with CMake and ESP IDF.

BridgingHeader.h

#include "print_float.h"

CMakeLists.txt

# List of Swift source files to build.
target_sources(${COMPONENT_LIB}
    PRIVATE
    src/print_float.cpp
    Main.swift
    LedStrip.swift
    Format.swift
)

I get errors as it is not seeing the C++ function: undefined reference to printFloat

[1/6] Performing build step for 'bootloader'
[1/1] cd /Users/paulsolt/dev/embedded/LED/build/bootloader/esp-idf/esptool_py && /Users/paulsolt/.espressif/python_env/idf5.2_py3.12_env/bin/python /Users/paulsolt/esp/esp-idf/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 /Users/paulsolt/dev/embedded/LED/build/bootloader/bootloader.bin
Bootloader binary size 0x54b0 bytes. 0x2b50 bytes (34%) free.
[4/6] Linking CXX executable main.elf
FAILED: main.elf 

...

/Users/paulsolt/.espressif/tools/riscv32-esp-elf/esp-13.2.0_20230928/riscv32-esp-elf/bin/../lib/gcc/riscv32-esp-elf/13.2.0/../../../../riscv32-esp-elf/bin/ld: esp-idf/main/libmain.a(Main.swift.obj): in function `.Lpcrel_hi1':
Main.swift.obj:(.text.$s10__idf_main04app_B0yyF+0x3c): undefined reference to `printFloat'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

Ok I figured out how to add C files to my project, but it looks like I need to add a separate step to compile C++ files into an object file before they can be linked with Swift.

I haven't figured out C++ code yet ...

I added two folders under my main folder:

main/
    include/
         print_float.h
    src/
         print_float.c

Then I updated the CMakeLists.txt to grab all the source files in the folder, so that I don't need to keep updating the CmakeLists.txt if I add files.

print_float.h

void printFloat(float value);

print_float.c

#ifndef PRINT_FLOAT_H
#define PRINT_FLOAT_H

#include "print_float.h"
#include <stdio.h>

void printFloat(float value) {
    printf("%f\n", value);
}

#endif

main/CMakeLists.txt

file(GLOB_RECURSE SOURCES "src/*.c")
message(SOURCES="${SOURCES}") # Prints out the source files added

idf_component_register(
    # SRCS /dev/null # We don't have any C++ sources
    SRCS ${SOURCES} 
    INCLUDE_DIRS "include"
    PRIV_INCLUDE_DIRS "."
    LDFRAGMENTS "linker.lf"
)

I dont have any pointers on how to do this, but whatever you do figure out would be good to push back to embedded examples so others can follow your lead!

1 Like

@rauhul I attempted to use these guides for Swift and C++, but I don't understand how the ESP32 IDF components and Swift/C++ build settings mix together.

I attempted to merge the CMakeLists.txt settings, but I couldn't get anything to build.

  1. Creating a Module to contain your C++ source code (Building with CMake)
  2. Setting Up Mixed-Language Swift and C++ Projects

That second link makes it sound like I just need the -cxx-interoperability-mode=default build setting to make it build with swiftc, but the module map and layout of the C++ code may still be important from the previous link.

Hmm yeah this is tricky because you're running into the combination of:

  • C++ Interop
  • CMake Swift
  • ESP Specific CMake

I dont actually think Embedded Swift play a large role in this mix ironically.

Maybe @kubamracek might know how to setup the CMake for this, or perhaps @etcwilde

1 Like