Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to build Swift library by adding custom target and dependency #1401

Open
oleksandr-kosylov opened this issue Jun 15, 2024 · 1 comment

Comments

@oleksandr-kosylov
Copy link

oleksandr-kosylov commented Jun 15, 2024

In order to support ability to use Swift programming language with Embedded platform support, I've adjusted CMakeLists according to Example at https://github.com/apple/swift-embedded-examples/tree/main/esp32-led-strip-sdk
and installed dev snapshot of swift toolchain that supports embedded platforms.

Project structure:
src/
Main.swift
Dummy.c
BridgingHeader.h
CMakeLists.txt

platform.ini
[env:esp32-c6-devkitc-1]
platform = espressif32 @ 6.7.0
board = esp32-c6-devkitc-1
framework = espidf

Main idea of approach is to build Swift sources and link to main target.
It's being achieved by next steps:

  1. creating of custom command (add_custom_command) that produces library.o object.
  2. creating of custom target that depends on library.o (add_custom_target)
  3. linking of _idf_main with library.o
  4. setting dependency of _idf_main on custom target (add_dependencies)

This works fine from terminal by idf.py build BUT looks like custom command and target are not being built in VS Code with PlatformIO, I've tried to replace swift build command with test one and it's net being executed.

Build fails because of missing implementation for app_main function that is declared in Main.swift, so because of library wasn't built.

Please advice what can cause an ignoring of custom target and command by build system.
I see that build.ninja contains build commands for custom target and command based on CMakeLists.txt but looks they are not executed.

CMakeLists.txt

@oleksandr-kosylov oleksandr-kosylov changed the title Unable to build Swift library add custom target and dependency Unable to build Swift library by adding custom target and dependency Jun 15, 2024
@valeros
Copy link
Member

valeros commented Jun 17, 2024

Hi @oleksandr-kosylov, thanks for reaching out. The current ESP-IDF integration is meant to be used only with generic ASM/C/C++ based projects. Anyway, the problem you're experiencing is caused by limited CMake's API which currently doesn't export any information about custom build targets. It means that all extra build steps need to be implemented using PlatformIO build API manually. In case with your example, I believe it's possible implement a small workaround using an extra script that will compile Swift sources and inject the resulting binary into the linker command. Please beware, I haven't tested the code below, but it should look something like this:

[platformio]
; Use the common IDF build folder to make CMake happy
src_dir = main

[env:esp32-c6-devkitc-1]
platform = espressif32
framework = espidf
monitor_speed = 115200
board = esp32-c6-devkitc-1

; Compile and inject the Swift library
extra_scripts = 
    compile_swift.py

compile_swift.py:

import os

from platformio.builder.tools.piomaxlen import _file_long_data

Import("env")

# Swift files are located in the `main` build folder
SWIFT_SOURCE_FILES = ("Main.swift", "LedStrip.swift")

def compile_swift_sources(swift_sources):
    assert len(swift_sources) > 0, "Missing Swift source files"
    swift_obj = env.Command(
        os.path.join("$BUILD_DIR", "_swiftcode.o"),
        swift_sources,
        env.VerboseAction(
            " ".join(
                [
                    "swiftc",
                    "-target",
                    "riscv32-none-none-eabi",
                    "-Xfrontend",
                    "-function-sections",
                    "-enable-experimental-feature",
                    "Embedded",
                    "-wmo",
                    "-parse-as-library",
                    "-Osize",
                    "-import-bridging-header",
                    os.path.join("$PROJECT_SRC_DIR", "BridgingHeader.h"),
                    "$SOURCES",
                    "-c",
                    "-o",
                    "$TARGET",
                    '@"%s"'
                    % _file_long_data(
                        env,
                        " ".join(
                            ["-I%s" % inc for inc in env.get("CPPPATH", [])]
                        ),
                    ),
                ]
            ),
            "Compiling Swift `$SOURCES` files to `$TARGET`",
        ),
    )

    return swift_obj


swift_sources = [
    os.path.join(env.subst("$PROJECT_SRC_DIR"), f)
    for f in SWIFT_SOURCE_FILES
]

swift_obj_lib = compile_swift_sources(swift_sources)
env.Prepend(LINKFLAGS=[swift_obj_lib])
env.Depends("$BUILD_DIR/$PROGNAME$PROGSUFFIX", swift_obj_lib)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants