How to use swiftc with a static toolchain in cmake

I have installed the static toolchain according to: Swift.org - Getting Started with the Static Linux SDK

The examples work. I now want to embed swift into my cmake project, for this, and I want to set the flags for swiftc correctly:

find_program(SWIFTC_EXE NAMES "swiftc")
set(CMAKE_Swift_COMPILER "${SWIFTC_EXE}")
set(CMAKE_Swift_FLAGS "-sdk /root/.swiftpm/swift-sdks/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a_static-linux-0.0.1.artifactbundle/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/ -target x86_64-swift-linux-musl -static-executable -cxx-interoperability-mode=default")

Since there isn't any documentation on how to do that, I got the above by trial and error. Naturally, I am getting all sorts of compilation errors. question: what is the correct way of using swiftc with the static toolchain in a cmake project? If I do a swift build, the hello world example projects builds correctly, but I cannot use swift build, since it is a cmake project.

[build] : && /opt/swift/usr/bin/swiftc -j 16 -num-threads 16 -emit-library -static -o libMyKit.a -module-name MyKit -module-link-name MyKit -emit-module -emit-module-path MyKit.swiftmodule -emit-dependencies  -sdk /root/.swiftpm/swift-sdks/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a_static-linux-0.0.1.artifactbundle/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/ -target x86_64-swift-linux-musl -static-executable -cxx-interoperability-mode=default -Onone -g -incremental -cxx-interoperability-mode=default -Xcc -std=c++17 -enable-testing -output-file-map CMakeFiles/MyKit.dir/Debug/output-file-map.json  /workspace/Sources/MyKit/Elements.swift /workspace/Sources/MyKit/ElementsBuilders.swift /workspace/Sources/MyKit/Code.swift    && :
[build] <module-includes>:1:10: note: in file included from <module-includes>:1:
[build] 1 | #include "CoreFoundation.h"
[build]   |          `- note: in file included from <module-includes>:1:
[build] 2 | 
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:10: note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  75 | #include "CFConstantKeys.h"
[build]  76 | 
[build]  77 | #include "ForSwiftFoundationOnly.h"
[build]     |          `- note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  78 | 
[build]  79 | #if TARGET_OS_OSX || TARGET_OS_IPHONE || TARGET_OS_WIN32 || TARGET_OS_LINUX
[build] 
[build] <unknown>:0: error: could not build C module 'CoreFoundation'
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForSwiftFoundationOnly.h:108:20: error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 106 | _CF_EXPORT_SCOPE_BEGIN
[build] 107 | 
[build] 108 | CF_PRIVATE Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |                    `- error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 109 | 
[build] 110 | struct __CFSwiftObject {
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForFoundationOnly.h:71:9: note: previous declaration is here
[build]  69 | #endif
[build]  70 | 
[build]  71 | Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |         `- note: previous declaration is here
[build]  72 | typedef CF_ENUM(CFOptionFlags, _CFAllocatorHint) {
[build]  73 |     _CFAllocatorHintZeroWhenAllocating = 1
[build] <module-includes>:1:10: note: in file included from <module-includes>:1:
[build] 1 | #include "CoreFoundation.h"
[build]   |          `- note: in file included from <module-includes>:1:
[build] 2 | 
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:10: note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  75 | #include "CFConstantKeys.h"
[build]  76 | 
[build]  77 | #include "ForSwiftFoundationOnly.h"
[build]     |          `- note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  78 | 
[build]  79 | #if TARGET_OS_OSX || TARGET_OS_IPHONE || TARGET_OS_WIN32 || TARGET_OS_LINUX
[build] 
[build] <unknown>:0: error: could not build C module 'CoreFoundation'
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForSwiftFoundationOnly.h:108:20: error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 106 | _CF_EXPORT_SCOPE_BEGIN
[build] 107 | 
[build] 108 | CF_PRIVATE Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |                    `- error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 109 | 
[build] 110 | struct __CFSwiftObject {
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForFoundationOnly.h:71:9: note: previous declaration is here
[build]  69 | #endif
[build]  70 | 
[build]  71 | Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |         `- note: previous declaration is here
[build]  72 | typedef CF_ENUM(CFOptionFlags, _CFAllocatorHint) {
[build]  73 |     _CFAllocatorHintZeroWhenAllocating = 1
[build] <module-includes>:1:10: note: in file included from <module-includes>:1:
[build] 1 | #include "CoreFoundation.h"
[build]   |          `- note: in file included from <module-includes>:1:
[build] 2 | 
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:10: note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  75 | #include "CFConstantKeys.h"
[build]  76 | 
[build]  77 | #include "ForSwiftFoundationOnly.h"
[build]     |          `- note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  78 | 
[build]  79 | #if TARGET_OS_OSX || TARGET_OS_IPHONE || TARGET_OS_WIN32 || TARGET_OS_LINUX
[build] 
[build] <unknown>:0: error: could not build C module 'CoreFoundation'
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForSwiftFoundationOnly.h:108:20: error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 106 | _CF_EXPORT_SCOPE_BEGIN
[build] 107 | 
[build] 108 | CF_PRIVATE Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |                    `- error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 109 | 
[build] 110 | struct __CFSwiftObject {
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForFoundationOnly.h:71:9: note: previous declaration is here
[build]  69 | #endif
[build]  70 | 
[build]  71 | Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |         `- note: previous declaration is here
[build]  72 | typedef CF_ENUM(CFOptionFlags, _CFAllocatorHint) {
[build]  73 |     _CFAllocatorHintZeroWhenAllocating = 1
[build] error: emit-module command failed with exit code 1 (use -v to see invocation)
[build] <module-includes>:1:10: note: in file included from <module-includes>:1:
[build] 1 | #include "CoreFoundation.h"
[build]   |          `- note: in file included from <module-includes>:1:
[build] 2 | 
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:10: note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  75 | #include "CFConstantKeys.h"
[build]  76 | 
[build]  77 | #include "ForSwiftFoundationOnly.h"
[build]     |          `- note: in file included from /opt/swift/usr/lib/swift_static/CoreFoundation/CoreFoundation.h:77:
[build]  78 | 
[build]  79 | #if TARGET_OS_OSX || TARGET_OS_IPHONE || TARGET_OS_WIN32 || TARGET_OS_LINUX
[build] 
[build] <unknown>:0: error: could not build C module 'CoreFoundation'
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForSwiftFoundationOnly.h:108:20: error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 106 | _CF_EXPORT_SCOPE_BEGIN
[build] 107 | 
[build] 108 | CF_PRIVATE Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |                    `- error: declaration of '__CFAllocatorRespectsHintZeroWhenAllocating' has a different language linkage
[build] 109 | 
[build] 110 | struct __CFSwiftObject {
[build] 
[build] /opt/swift/usr/lib/swift_static/CoreFoundation/ForFoundationOnly.h:71:9: note: previous declaration is here
[build]  69 | #endif
[build]  70 | 
[build]  71 | Boolean __CFAllocatorRespectsHintZeroWhenAllocating(CFAllocatorRef _Nullable allocator);
[build]     |         `- note: previous declaration is here
[build]  72 | typedef CF_ENUM(CFOptionFlags, _CFAllocatorHint) {
[build]  73 |     _CFAllocatorHintZeroWhenAllocating = 1
[build] ninja: build stopped: subcommand failed.

You appear to be digging into CMake internals to build this, which might be clashing with other flags it sets. Take a look at these examples for the prescribed high-level way of building Swift with CMake, covering many of the same usecases you want.

It obviously doesn't include an example for the brand new static linux SDK so you will have to add the flags to use that, but you should invoke conventional CMake methods like target_compile_options(), rather than override CMake internal flags like CMAKE_Swift_FLAGS.

Let us know how it works out, and consider contributing a static SDK example to that repo afterwards. :wink:

1 Like

This is a cmake toolchain fine, I already have a working toolchain file for x86_64-linux-gnu (not static), now I want to set up a working x86_64-linux-musl and a wasm32-unknown-unknown toolchain (perhapt also a darwin one)

OK, even if you want to use toolchain files, I don't think you're supposed to set those internal CMake flags. For example, here is the official Android NDK toolchain file: it does not set any internal flags like you are.

I have never used a toolchain file, but from the official doc, I get the impression it is only to set up the toolchain and platform, but that compilation flags should still be specified by your project's CMake config, as shown in those Swift examples I linked.