Building embedded project in debug mode

Hey all,

So I've been interested in building my Swift Embedded project in debug mode since building swift-mmio in release mode is MUCH slower (even painfully slow), and I like to have the ability to generate a debug binary for testing and analysis.

However, if I try to build my project in debug mode, a bunch of fun issues start to happen. At first, I get this error:

blink-mmio$ make
compiling...
swift build \
        --configuration debug \
        --swift-sdks-path ../swift-sdks \
        --swift-sdk stm32c0xx \

Building for debugging...
warning: ignoring '-enable-batch-mode' because '-whole-module-optimization' was also specified
remark: Incremental compilation has been disabled: it is not compatible with whole module optimization
<unknown>:0: error: index output filenames do not match input source files

make: *** [Makefile:24: build] Error 1

Fine. So if I add the --disable-index-store flag to swift build, then the next issue appears. Binaries are placed in the same directory as the make command instead of in the expected .build/debug subdirectory, and the Swift linker cannot find the object files (naturally):

blink-mmio$ make
compiling...
swift build \
        --configuration debug \
        --swift-sdks-path ../swift-sdks \
        --swift-sdk stm32c0xx --disable-index-store \

Building for debugging...
/home/xtremek/.local/share/swiftly/toolchains/6.0.1/usr/bin/llvm-ar: error: /home/xtremek/Programming/xtremekforever/swift-stm32c011-examples/blink-mmio/.build/armv6m-none-none-eabi/debug/Application.build/Application.swift.o: No such file or directory
[3/4] Archiving libApplication.a
make: *** [Makefile:24: build] Error 1
blink-mmio$ ls -l *
**-rw-rw-r-- 1 xtremek xtremek 1939976 Oct 27 20:52 Application.o**
**-rw-rw-r-- 1 xtremek xtremek  130752 Oct 27 20:52 CortexM.o**
-rw-rw-r-- 1 xtremek xtremek    1718 Oct 27 20:51 Makefile
**-rw-rw-r-- 1 xtremek xtremek   50020 Oct 27 20:52 MMIO.o**
-rw-rw-r-- 1 xtremek xtremek    1238 Oct 19 13:20 Package.resolved
-rw-rw-r-- 1 xtremek xtremek     740 Oct 19 13:20 Package.swift

Sources:
total 8
drwxrwxr-x 3 xtremek xtremek 4096 Oct 19 13:20 Application
drwxrwxr-x 3 xtremek xtremek 4096 Sep 29 06:40 Support

Any ideas why this sort of thing happens when using embedded mode? Here are the flags for Swift SDK that are being passed to the build for complete reference:

"swiftCompiler": {
    "extraCLIOptions": [
      "-Osize",
      "-wmo",
      "-enable-experimental-feature", "Embedded",
      "-Xfrontend", "-disable-stack-protector",
      "-Xfrontend", "-function-sections"
    ]
  },

Looking into SwiftPM issues I see this:

So I guess manually enabling -wmo doesn't work, and that's what I'm doing to build in debug mode and still be allowed to compile for embedded. I wonder if the merge related to the issue would fix this?

What version of SwiftPM are you using? The patch mentioned in that issue was merged about a month ago and should be in the nightly main toolchains.

Unfortunately I am extremely busy until November ~5th and wont be able to dig in until then.

1 Like

Small reminder: I recommend you update your toolchain from time to time (if you're not already on the latest version), I've had quite a few issues simply fixed by updating to the latest nightly version.

2 Likes

Yeah I was on Swift 6.0.1 when I posted this! Last night tried the latest main-snapshot after finding the patch (10-25) but still had issues. But today I realized that maybe the .enableExperimentalFeature("Embedded") flag needed to be added to Package.swift (which it wasn't in my project) and...it works!!

Thanks, I should have done this before I posted...

So I remembered that the reason why I had removed the setting from Package.swift is that I couldn't build any tests with this enabled. I have a "Core" library in my project that contains only core functionality that I want to unit test (no hardware or swift-mmio) but could not due to errors about not being able to import the module built for embedded.

I found a solution using env variables, like this:

var globalSwiftSettings = [SwiftSetting]()
if Context.environment["EMBEDDED_BUILD"] != nil {
    globalSwiftSettings.append(.enableExperimentalFeature("Embedded"))
}

Then, in my target I just use this:

        .target(
            name: "Core",
            swiftSettings: globalSwiftSettings
        ),

So now I can conditionally build for embedded whenever I need to, but by default this is disabled so I can build on the host and run the tests for my core code.