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:

2 Likes

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.

1 Like

I did adapt it, but there has not been any change, is there any guide on how to use the static sdk with the swiftc command (not swift build, I am not using that)

My setup so far:

FROM fedora:40

RUN dnf update -y
RUN dnf upgrade -y

# for fedora builds
RUN yum -y install \
    binutils \
    gcc \
    git \
    libcurl-devel \
    libedit-devel \
    libicu-devel \
    libuuid-devel \
    libxml2-devel \
    python3-devel \
    sqlite-devel \
    unzip

WORKDIR /tmp
RUN curl -O https://download.swift.org/swift-6.0-release/fedora39/swift-6.0-RELEASE/swift-6.0-RELEASE-fedora39.tar.gz
RUN tar xzf swift-6.0-RELEASE-fedora39.tar.gz
RUN mv swift-6.0-RELEASE-fedora39 swift
RUN mv swift /opt
ENV PATH=/opt/swift/usr/bin:"${PATH}"
RUN swift sdk install https://download.swift.org/swift-6.0-release/static-sdk/swift-6.0-RELEASE/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz --checksum 7984c2cf175bde52ba6ea1fcbe27fc4a148a6237c41c719209c9288ed3ceb652

a simple hello world program:

import Foundation

print("Hello World");

Compiling with: swiftc hw.swift -target x86_64-swift-linux-musl
yield: <unknown>:0: error: unable to load standard library for target 'x86_64-swift-linux-musl'

Compiling with swiftc hw.swift -static-executable yields all kinds of other errors

Is there any guide on how to use the static-sdk with swiftc?

(Thanks so far for your effort)

(Edit: The error exists both in fedora:40 and fedora:39)

1 Like

Swift SDKs are a SwiftPM feature, not a swiftc feature, so you'll have to rely on swift build to fully utilize it.

1 Like

Then how do I tell swiftc to build static executables/libraries?

If you're linking with Glibc, there's no way to do that with swiftc or any other language for that matter, as Glibc doesn't support static linking.

If you're not willing to use swift build for Musl Swift SDKs, you'll have to replicate manually what swift build does under the hood for Swift SDKs support: read Swift SDK metadata, parse provided toolset flags that point the toolchain to Musl in the Swift SDK bundle, and pass all of those flags correctly to each tool: the Swift driver, the Clang driver, and the linker (just off the top of my head, there may be more).

1 Like

As Max says, these SDK bundles are a SwiftPM feature, so they are meant to be used with the package manager. However, there's no reason they can't be used with CMake or other build systems also, as underneath SwiftPM simply uses swiftc. To see how SwiftPM is doing that, simply pass it the -v flag, so it verbosely shows you what it is doing.

For your example, if you find where the SDK bundle was unpacked (for normal linux users, it is installed in your home directory at ~/.swiftpm/swift-sdks/) and remove the Foundation import until the current 6.0 SDK is fixed, the following command worked for me:

> ./swift-6.0-RELEASE-fedora39/usr/bin/swiftc -target x86_64-swift-linux-musl -sdk ~/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -static-stdlib -resource-dir ~/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/ hw.swift

The -resource-dir flag shouldn't be necessary, but the new swift-driver introduced a regression years ago and the proposed fix linked there has been stalled for months now.

1 Like

Thank you so far.

I am quite willing to link with Musl, the problem is that this is a rather big Cmake/C++ project with some Swift on top of it, so I am not sure if I can switch to SwiftPM (I also use vcpkg and some ExternalProject_Add-Dependencies that have custom build configuration). I am pretty sure that SwiftPM is unable to build any of that (this is not meant as criticism).

The C++ will be compiled statically with clang/musl.

It's not as seamless as going the SPM route, but we can use a toolchain file to fill out most of what we need (or cmake cache files too).

The Musl SDK contains a sysroot in there, which CMake can use, though there is a bit of digging:

# Tell CMake what we're cross-compiling for
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR X86)

# Set sysroot info:
set(CMAKE_SYSROOT "${CMAKE_CURRENT_LIST_DIR}/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-09-11-a_static-linux-0.0.1.artifactbundle/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-09-11-a_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64")
set(CMAKE_STAGING_PREFIX "${CMAKE_CURRENT_LIST_DIR}/musl-staging")

# Set find_package behavior
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Setup languages
set(CMAKE_C_COMPILER $ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{CXX})
set(CMAKE_Swift_COMPILER $ENV{Swiftc})

set(triple  x86_64-swift-linux-musl)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_Swift_COMPILER_TARGET ${triple})

# Whoops, I forgot to hook up passing `${CMAKE_SYSROOT}` to the 
# swift compiler apparently....
# set(CMAKE_Swift_COMPILER_WORKS YES)
string(APPEND CMAKE_Swift_FLAGS "-sdk ${CMAKE_SYSROOT}")

Then set the CC, CXX, and Swiftc environment variables to the appropriate compilers from your cross-compiling toolchain.

And then build your project with something like:

cmake -G 'Ninja' --toolchain <path-to-toolchainfile>/toolchain.cmake -S <path to project sources>

edit: I should probably mention that the toolchain file above is set up to live next to the unpacked SDK file. You can change where it lives by replacing the $${CMAKE_CURRENT_LIST_DIR} with the absolute path to the static SDK.

1 Like

okay, thanks so far for your help, I got a little further:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)

# general config

#set(SWIFTPM_DIR "")
set(SDK_ROOT "/root/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1")
set(CMAKE_SYSROOT "${SDK_ROOT}/swift-linux-musl/musl-1.2.5.sdk/x86_64")
#set(CMAKE_STAGING_PREFIX "${SDK_ROOT}/musl-staging")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Set the C/++ compilers
set(CMAKE_C_COMPILER $ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{CXX})

set(CMAKE_C_COMPILER_TARGET x86_64-swift-linux-musl)
set(CMAKE_CXX_COMPILER_TARGET ${CMAKE_C_COMPILER_TARGET})

# flags for all files, including dependencies (DO NOT set -Werror here, it would break dependencies)
set(EXTERNAL_PROJECT_OPTIONS -fPIC)
add_compile_options(
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-march=native>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-mtune=native>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-m64>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-O3>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-fPIC>
)

# Set up toolchain for Swift
set(CMAKE_Swift_COMPILER $ENV{Swiftc})
set(CMAKE_Swift_COMPILER_TARGET ${CMAKE_C_COMPILER_TARGET})
set(CMAKE_Swift_FLAGS "${CMAKE_Swift_FLAGS} -sdk ${CMAKE_SYSROOT} -resource-dir ${CMAKE_SYSROOT}/usr/lib/swift_static/")
add_compile_options( 
    #$<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>
    #$<$<COMPILE_LANGUAGE:Swift>:-Xcc>
    #$<$<COMPILE_LANGUAGE:Swift>:-std=c++17>
    $<$<COMPILE_LANGUAGE:Swift>:-static-stdlib>
    $<$<COMPILE_LANGUAGE:Swift>:-static-executable>
)

# vcpkg config

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CMAKE_SYSTEM_NAME linux)
set(VCPKG_LIBRARY_LINKAGE static)
##  there is really no need to further complicate this by using debug versions
set(VCPKG_BUILD_TYPE release)
set(VCPKG_C_FLAGS ${EXTERNAL_PROJECT_OPTIONS})
set(VCPKG_CXX_FLAGS ${EXTERNAL_PROJECT_OPTIONS})

include(/workspace/Dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake)

Which can compile simple Programs that do not use any dependencies (such as a file containing an endless loop). But as soon as I try sophisticated programs (such as my attempt to print "Hello, World!" to the console), the toolchain still fails:


[build] [1/1] Linking Swift executable TestStaticSwiftHelloWorld
[build] FAILED: TestStaticSwiftHelloWorld CMakeFiles/TestStaticSwiftHelloWorld.dir/HelloWorld.swift.o 
[build] : && /opt/swift/usr/bin/swiftc -target x86_64-swift-linux-musl -j 16 -num-threads 16 -emit-executable -o TestStaticSwiftHelloWorld -emit-dependencies  -sdk /root/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -resource-dir /root/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/ -Onone -g -incremental -static-stdlib -static-executable -output-file-map CMakeFiles/TestStaticSwiftHelloWorld.dir/Debug/output-file-map.json  -sdk /root/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -resource-dir /root/.swiftpm/swift-sdks/swift-6.0-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/ -Onone -g -incremental  /workspace/HelloWorld.swift    && :
[build] error: emit-module command failed with exit code 1 (use -v to see invocation)
[build] <unknown>:0: error: missing required module '_FoundationCollections'
[build] <unknown>:0: error: missing required module '_FoundationCollections'

Source Code:

import Foundation

print("Hello, World!")

Thank you so far for your effort :)

There is currently an issue with the 6.0 static SDK and building Foundation: you will have to use the latest Sep.17 6.0 snapshot toolchain and 6.0 static SDK snapshot linked on the website to avoid that or wait for a fix in the next patch release.

1 Like

Ok thanks for the heads-up, I will wait for that fix and keep this post updated.

I have updated swift to the latest version, and it still fails:

My cmake file:

cmake_minimum_required(VERSION 3.28)
project(StaticLinuxTests C CXX Swift)

add_executable(TestStaticCHelloWorld HelloWorld.c)
add_executable(TestStaticCppHelloWorld HelloWorld.c++)
add_executable(TestStaticSwiftHelloWorld HelloWorld.swift)

My cmake preset:

{
    "version": 3,
    "configurePresets": [
        {
            "name": "default",
            "generator": "Ninja",
            "cacheVariables": {
                "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../../x86-64-unknown-linux-musl.cmake",
                "CMAKE_BUILD_TYPE": "Debug"
            }
        }
    ]
}

My toolchain file:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR x86_64)

# see https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html
# https://www.phoronix.com/news/GCC-fhardened-Hardening-Option

# general config

set(SWIFTPM_DIR "")
set(SDK_ROOT "/root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1")
set(CMAKE_SYSROOT "${SDK_ROOT}/swift-linux-musl/musl-1.2.5.sdk/x86_64")
set(CMAKE_STAGING_PREFIX "${SDK_ROOT}/musl-staging")

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

# Set the C/++ compilers
set(CMAKE_C_COMPILER $ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{CXX})

set(CMAKE_C_COMPILER_TARGET x86_64-swift-linux-musl)
set(CMAKE_CXX_COMPILER_TARGET ${CMAKE_C_COMPILER_TARGET})

# flags for all files, including dependencies (DO NOT set -Werror here, it would break dependencies)
set(EXTERNAL_PROJECT_OPTIONS -fPIC)
add_compile_options(
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-march=native>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-mtune=native>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-m64>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-O3>
    $<$<COMPILE_LANGUAGE:C,CXX,OBJC,OBJXX>:-fPIC>
)

# Set up toolchain for Swift
set(CMAKE_Swift_COMPILER $ENV{Swiftc})
set(CMAKE_Swift_COMPILER_TARGET ${CMAKE_C_COMPILER_TARGET})
set(CMAKE_Swift_FLAGS "${CMAKE_Swift_FLAGS} -sdk ${CMAKE_SYSROOT} -resource-dir ${CMAKE_SYSROOT}/usr/lib/swift_static/")
add_compile_options( 
    $<$<COMPILE_LANGUAGE:Swift>:-cxx-interoperability-mode=default>
    $<$<COMPILE_LANGUAGE:Swift>:-Xcc>
    $<$<COMPILE_LANGUAGE:Swift>:-std=c++17>
    $<$<COMPILE_LANGUAGE:Swift>:-static-stdlib>
    $<$<COMPILE_LANGUAGE:Swift>:-static-executable>
)

# vcpkg config

set(VCPKG_FORCE_SYSTEM_BINARIES 1)
set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CMAKE_SYSTEM_NAME linux)
set(VCPKG_LIBRARY_LINKAGE static)
##  there is really no need to further complicate this by using debug versions
set(VCPKG_BUILD_TYPE release)
set(VCPKG_C_FLAGS ${EXTERNAL_PROJECT_OPTIONS})
set(VCPKG_CXX_FLAGS ${EXTERNAL_PROJECT_OPTIONS})

include(/workspace/Dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake)

Output:

Preset CMake variables:

  CMAKE_BUILD_TYPE="Debug"
  CMAKE_TOOLCHAIN_FILE="/workspace/Build/Toolchains/Tests/StaticLinux/../../x86-64-unknown-linux-musl.cmake"

-- The Swift compiler identification is Apple 6.0.1
-- Check for working Swift compiler: /opt/swift/usr/bin/swiftc
-- Check for working Swift compiler: /opt/swift/usr/bin/swiftc - broken
CMake Error at /usr/share/cmake/Modules/CMakeTestSwiftCompiler.cmake:40 (message):
  The Swift compiler

    "/opt/swift/usr/bin/swiftc"

  is not able to compile a simple test program.

  It fails with the following output:

    Change Dir: '/workspace/Build/Toolchains/Tests/StaticLinux/out/CMakeFiles/CMakeScratch/TryCompile-6kr2g0'
    
    Run Build Command(s): /bin/ninja-build -v cmTC_5ebe5
    [1/1] : && /opt/swift/usr/bin/swiftc -target x86_64-swift-linux-musl -j 16 -num-threads 16 -emit-executable -o cmTC_5ebe5 -emit-dependencies  -sdk /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -resource-dir /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/  -cxx-interoperability-mode=default -Xcc -std=c++17 -static-stdlib -static-executable -output-file-map CMakeFiles/cmTC_5ebe5.dir//output-file-map.json  -sdk /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -resource-dir /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/  /workspace/Build/Toolchains/Tests/StaticLinux/out/CMakeFiles/CMakeScratch/TryCompile-6kr2g0/main.swift    && :
    FAILED: cmTC_5ebe5 CMakeFiles/cmTC_5ebe5.dir/main.swift.o 
    : && /opt/swift/usr/bin/swiftc -target x86_64-swift-linux-musl -j 16 -num-threads 16 -emit-executable -o cmTC_5ebe5 -emit-dependencies  -sdk /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -resource-dir /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/  -cxx-interoperability-mode=default -Xcc -std=c++17 -static-stdlib -static-executable -output-file-map CMakeFiles/cmTC_5ebe5.dir//output-file-map.json  -sdk /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64 -resource-dir /root/.swiftpm/swift-sdks/swift-6.0.1-RELEASE_static-linux-0.0.1.artifactbundle/swift-6.0.1-RELEASE_static-linux-0.0.1/swift-linux-musl/musl-1.2.5.sdk/x86_64/usr/lib/swift_static/  /workspace/Build/Toolchains/Tests/StaticLinux/out/CMakeFiles/CMakeScratch/TryCompile-6kr2g0/main.swift    && :
    error: link command failed with exit code 1 (use -v to see invocation)
    clang: warning: argument unused during compilation: '-pie' [-Wunused-command-line-argument]
    ld.lld: error: unable to find library -lswiftCxx
    ld.lld: error: unable to find library -lswiftCxxStdlib
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.
    
    

  

  CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
  CMakeLists.txt:2 (project)


-- Configuring incomplete, errors occurred!

Re: the CoreFoundation language linkage build error, see this issue and PR.

Thank you for your help so far :grinning: I have summarised all approaches here, and I am still getting errors:GitHub - b521f771d8991e6f1d8e65ae05a8d783/swift-cmake-static

what works: building using swiftpm in non-static-mode
what does not work: building swiftpm using the static SDK and CxxInterop, trying to do the same using cmake

Both fail with the following error:

ld.lld: error: unable to find library -lswiftCxx
ld.lld: error: unable to find library -lswiftCxxStdlib

If anyone can give me some pointers on how to continue, that would be greatly appreciated,
have a great day

The static resource directory in the linux toolchain and the static Musl SDK do not ship those C++ interop libraries:

> find swift-6.0.2-RELEASE-fedora39/ .swiftpm/swift-sdks/swift-DEVELOPMENT-SNAPSHOT-2024-09-25-a_static-linux-0.0.1.artifactbundle/ -name "libswiftCxx*"
swift-6.0.2-RELEASE-fedora39/usr/lib/swift/linux/libswiftCxx.a
swift-6.0.2-RELEASE-fedora39/usr/lib/swift/linux/libswiftCxxStdlib.a

Probably an oversight in the toolchain build: what do you think, @egor.zhdan?