-
Notifications
You must be signed in to change notification settings - Fork 0
Guide Linux Deployment
Native binaries produced by aro build link against the Swift runtime (libswiftCore.so, libswift_Concurrency.so, libFoundation.so, …). On Linux this matters because a fresh user-machine without a Swift install will refuse to start the binary:
./MyApp: error while loading shared libraries: libswiftCore.so: cannot open shared object file: No such file or directory
aro build offers two link modes to solve this — choose based on how much you control the target machine.
| Flag | What it does | Output |
|---|---|---|
--static (default)
|
Links Swift libraries as static archives from swift_static/linux/ (-Wl,-Bstatic … -Wl,-Bdynamic). |
A single binary. Foundation still needs to be present on the target (see "Why Foundation Stays Dynamic" below). |
--dynamic |
Links Swift libraries as .sos, embeds rpath=$ORIGIN, and copies every required .so next to the binary. |
A directory: myapp/{myapp, libswiftCore.so.5, libFoundation.so, libswift_Concurrency.so, …}. |
The two flags are mutually exclusive; passing both is a hard error.
aro build ./MyApp # static (default)
aro build ./MyApp --static # explicit static
aro build ./MyApp --dynamic # bundled .so directory- You control the target image (e.g. you ship a Docker image built
FROM ghcr.io/arolang/aro-runtime). - You're deploying to a managed Linux distribution where Foundation is or can be apt-installed (
libfoundation-dev). - You want the smallest possible deployment artifact.
- You don't know the target machine — handing the binary to a colleague, dropping it onto an arbitrary VM, attaching to a serverless function with a glibc-class runtime.
- You want a
tar.gzyou can extract anywhere and run without anapt installstep. - You're cross-compiling for a Linux machine you don't fully control.
Use the directory form like this:
$ aro build ./MyApp --dynamic
$ ls MyApp/
MyApp libFoundation.so.6 libswiftCore.so.5
libBlocksRuntime.so libFoundationEssentials.so.6 libswiftDispatch.so
libFoundationNetworking.so.6 libswift_Concurrency.so.5 libswift_StringProcessing.so.5
…
$ tar czf MyApp.tar.gz MyApp/
$ scp MyApp.tar.gz target:
$ ssh target 'tar xzf MyApp.tar.gz && ./MyApp/MyApp'The binary uses rpath=$ORIGIN, so the loader picks the Swift runtime up from the same directory as the binary.
Swift ships static archives next to its dynamic libraries. The findSwiftLibPath helper resolves to something like /usr/share/swift/usr/lib/swift/linux. The static sibling is /usr/share/swift/usr/lib/swift_static/linux and contains libswiftCore.a, libswift_Concurrency.a, libswiftGlibc.a, libswiftDispatch.a, libBlocksRuntime.a, libswift_StringProcessing.a, libswift_RegexParser.a, and libswiftSwiftOnoneSupport.a.
The linker invocation switches between modes using -Wl,-Bstatic / -Wl,-Bdynamic:
clang … <object files> -L/usr/share/swift/usr/lib/swift/linux \
-L/usr/share/swift/usr/lib/swift_static/linux \
-Wl,-Bstatic -lswiftCore -lswift_Concurrency -lswiftGlibc \
-lswiftDispatch -lBlocksRuntime \
-lswift_StringProcessing -lswift_RegexParser \
-Wl,-Bdynamic -lFoundation -lFoundationEssentials -lFoundationNetworking \
-lpthread -ldl -lm -lstdc++ -lz -lxml2 -lgit2 …
If swift_static/linux/ is missing from the toolchain (some minimal Swift installs strip it), aro build falls back to dynamic linking with the $ORIGIN rpath added — same effect as --dynamic without the .so copy.
Foundation on Linux pulls in libcurl, libxml2, libicu, and a handful of other C libraries. Apple has not published a fully-static Foundation for upstream Swift on Linux, so libFoundation.a doesn't exist in swift_static/linux. Two ways to deal with it:
-
Stay on
--dynamic—libFoundation.soand friends end up next to the binary, no further action needed. -
Use a runtime image —
ghcr.io/arolang/aro-runtimealready ships Foundation;--staticproduces a small binary that runs as-is inside that image. -
Use Apple's Static-Linux SDK (musl) — fully static, including Foundation. Not yet wired up in
aro build; tracked separately.
Two-stage build with --dynamic (the binary plus .sos end up alongside each other in the runtime stage):
FROM ghcr.io/arolang/aro-buildsystem:latest AS builder
WORKDIR /app
COPY . .
RUN aro build . --dynamic --optimize
FROM debian:bookworm-slim
WORKDIR /app
COPY --from=builder /app/MyApp /app/
COPY --from=builder /app/lib*.so* /app/
CMD ["/app/MyApp"]Or with --static and the ARO runtime image (smaller image, requires the runtime base):
FROM ghcr.io/arolang/aro-buildsystem:latest AS builder
WORKDIR /app
COPY . .
RUN aro build . --optimize # --static is the default
FROM ghcr.io/arolang/aro-runtime:latest
WORKDIR /app
COPY --from=builder /app/MyApp ./MyApp
CMD ["./MyApp"]- Chapter 27 of TheLanguageGuide: the full native-compilation chapter.
- Issue #226: the bug report that motivated this work.
Fundamentals
- The Basics
- Feature Sets
- Actions
- Variables
- Type System
- Control Flow
- Error Handling
- Computations
- Dates
- Concurrency
Runtime & Events
I/O & Communication
Advanced