Would it be possible to produce a statically linked linux binary using the embedded subsystem? I’ve gone through the documentation and got it to compile for macOS, but for linux I’m a little out of my depth. My idea is to invoke POSIX system calls from Swift and package the static binary into a bare (from-scratch) container (x86_64). A simple hello-world would be a great starter. Greetings!
It’s possible but requires lots of moving parts. I essentially had to do the same for the chiselled containers, which are built on top of scratch. You need to pull in all the dependencies that the Swift runtime requires and compile it as a static executable
Thanks, but that’s still too bloated for what I have in mind — my target being an equivalent to what zig does with cross compiling to linux with musl, producing static binaries of ~100KB for a minimal http server.
The furthest I got with Swift Embedded is a 'hello-world' binary that is static in Swift’s sense but still linked to the system glibc, which makes sense if the target triple includes gnu. Example ldd main output:
’libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fffff5dc000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffffffcb000)'
ls output:
’18 KB Thu Feb 12 16:55:57 2026 main
1.8 MB Fri Feb 13 15:19:57 2026 libc.so.6
210 KB Fri Feb 13 15:20:03 2026 ld-linux-x86-64.so.2’
Deploying it into a bare container (with the correct library paths) yields ~0.96 MB compressed (container image inspect shows "size": 1009266)
I'm sure Swift Embedded can be used with a patched musl, but how?
I think the problem is that you are targeting Linux. You need to target none and then implement the syscalls you want to use manually, like this guy: https://www.youtube.com/watch?v=IbibjkI1kIs
A led blinking embedded project would probably be a good second half for the starting point: GitHub - swiftlang/swift-embedded-examples: A collection of example projects using Embedded Swift
edit: you could also try targeting none and then manually including Musl headers and linking Musl.
Thanks, that pointed me in the right direction. Manually writing the sys calls in C with inline assembly totally works. Going back to my original proposition, I just had preliminary success linking with musl (and I've just read the edit xd):
146 KB Sat Feb 14 06:15:22 2026 bin
file bin:
bin: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped
it works as the sole file on a bare container! Here are the steps to reproduce:
project.swift:
@_extern(c, "write")
func c_write(_ fd: Int32, _ buf: UnsafeRawPointer, _ count: Int) -> Int
print("Hello, world!")
let message = "hello from write()\n"
let _ = c_write(1, message, message.utf8.count)
swiftc -enable-experimental-feature Embedded -enable-experimental-feature Extern -wmo -Osize -target x86_64-unknown-none-elf Sources/project/project.swift -c -o main.o
ld.lld -static -m elf_x86_64 -o bin ./musl-sdk/crt1.o ./musl-sdk/crti.o ./musl-sdk/libc.a main.o ./musl-sdk/crtn.o --entry=_start --gc-sections
You need the musl-sdk files from manually compiled musl or from alpine linux musl-dev package for the proper target arch, and of course a development snapshot of swift.
The binary can be made smaller with strip and without debug_info; also, I haven't tested bridging-headers in order to have consistent structs and preprocessor macros.
WIP
You'd have to create a separate Swift SDK from scratch built against Musl with Embedded Swift, similarly to how we have two Swift SDKs against WASI-libc (a fork of Musl) built with Embedded and non-Embedded Swift.