macOS: 26.0.1 (25A362)
Xcode: 26.0 (17A324)
Swift: Apple Swift version 6.2 (swiftlang-6.2.0.19.9 clang-1700.3.19.1)
Linux SDK: swift-6.2-RELEASE_static-linux-0.0.1.artifactbundle.tar.gz
% swift sdk list
swift-6.2-RELEASE_static-linux-0.0.1
Questions:
1)Is there a way to list all released Static SDKs for Linux and Windows?
2Did I make a mistake? Why can't I compile the HelloWrold with Static Linux SDK?
Build and run on macOS
% swift build
[1/1] Planning build
Building for debugging...
[1/1] Write swift-version--58304C5D6DBC2206.txt
Build complete! (0.10s)
% ./.build/debug/Hello
Hello, World!
Build with "Static Linux SDK"
% swift build --swift-sdk aarch64-swift-linux-musl
import Foundation
| `- error: compiled module was created by a different version of the compiler
Package.swift
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyCLI",
targets: [
.executableTarget(
name: "Hello"
)
]
)
Hello.swift
// The Swift Programming Language
// https://docs.swift.org/swift-book
import Foundation
@main
struct MyCLI {
static func main() {
print("Hello, World!")
}
}
If you are using macOS, note that you cannot use the toolchain provided with Xcode to build programs using the SDK. Instead, you must use the Swift compiler from the open-source toolchain (see above).
The Swift toolchain shipped with Xcode is unlikely to support targets other than Apple platforms, so that unfortunately isn't going to change anytime soon.
I do like this separation though, as Apple platform development has a lot of intricate requirements and Apple's toolchain pretty much tuned to exactly what you need, while I can use Swift OSS snapshots for my hobby projects on server-side / Web Assembly freely, without worrying about choices and (closed source) modifications Apple made in distributing and configuring these toolchains.
I tried Apple’s toolchain and encountered some issues when running swift build .
build for macOS with warnings?
Running hello on the remote machine failed?
The size of the hello executable is about 70 times larger compared to Golang(I’m very sorry to say that).
Build for macOS with warnings
% swift build -c release
Fetching https://github.com/swiftlang/example-package-figlet.git from cache
Fetched https://github.com/swiftlang/example-package-figlet.git from cache (0.01s)
Creating working copy for https://github.com/swiftlang/example-package-figlet.git
Working copy of https://github.com/swiftlang/example-package-figlet.git resolved at main (166eef4)
Building for production...
ld: warning: building for macOS-11.0, but linking with dylib '/usr/lib/swift/libswiftCore.dylib' which was built for newer version 13.0
ld: warning: building for macOS-11.0, but linking with dylib '/usr/lib/swift/libswift_Builtin_float.dylib' which was built for newer version 13.0
[8/8] Linking hello
Build complete! (13.14s)
% ./.build/release/hello
_ _ _ _ ____ _ __ _ _
| | | | ___ | | | | ___ / ___| __ __ (_) / _| | |_ | |
| |_| | / _ \ | | | | / _ \ \___ \ \ \ /\ / / | | | |_ | __| | |
| _ | | __/ | | | | | (_) | _ ___) | \ V V / | | | _| | |_ |_|
|_| |_| \___| |_| |_| \___/ ( ) |____/ \_/\_/ |_| |_| \__| (_)
|/
Build and run for Linux
% swift build -c release --swift-sdk aarch64-swift-linux-musl
Fetching https://github.com/swiftlang/example-package-figlet.git from cache
Fetched https://github.com/swiftlang/example-package-figlet.git from cache (0.01s)
Creating working copy for https://github.com/swiftlang/example-package-figlet.git
Working copy of https://github.com/swiftlang/example-package-figlet.git resolved at main (166eef4)
Building for production...
[8/8] Linking hello
Build complete! (4.93s)
% scp hello user_name@remote.ip.address:~/Downloads
user_name@remote.ip.address ~/Downloads % ./hello
Figlet/resource_bundle_accessor.swift:12: Fatal error: could not load resource bundle: from /home/user_name/Downloads/swift-figlet_Figlet.resources
or
/Users/user_name/Heros/MyCLI/.build/aarch64-swift-linux-musl/release/swift-figlet_Figlet.resources
Trace/breakpoint trap
Apple's toolchain information on macOS
% swift --version
Apple Swift version 6.2 (swift-6.2-RELEASE)
Target: arm64-apple-macosx26.0
Build config: +assertions
% swift sdk list
swift-6.2-RELEASE_static-linux-0.0.1
Package.swift
// swift-tools-version: 6.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyCLI",
products: [
.executable(name: "hello", targets: ["Hello"]),
],
dependencies: [
.package(url: "https://github.com/swiftlang/example-package-figlet.git", branch: "main"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.executableTarget(
name: "Hello",
dependencies: [
.product(name: "Figlet", package: "example-package-figlet")
]
)
]
)
Hello.swift
// The Swift Programming Language
// https://docs.swift.org/swift-book
import Foundation
import Figlet
@main
struct MyCLI {
static func main() {
Figlet.say("Hello, Swift!")
}
}
My mistake.
I reviewed the Figlet source code again, and indeed, standard.flf is placed within the resources bundle when compiling, so copying the resources bundle makes perfect sense.
The helloworld executable I compiled is a whopping 147MB , which is truly quite large.
My own HelloWorld executable is "just" 8.1MB. Big - thanks to the Swift runtime etc - but not quite 147MB. I'm assuming the dependencies Figlet imports like Foundation are the culprit
I see, you have an explicit dependency on the Figlet package, which does require Foundation for resource bundles and makes Foundation a transitive dependency of your package. To remove Foundation, you'd have to replace uses of Bundle in Figlet with some lower level code that finds and loads supplied resources manually.
What's the binary size that you get for a "Hello, World!" printer without any dependencies?
My mistake!
I’ve always assumed that release mode would remove all symbols (both debug info and symbol tables).
It was only by using the option -Xlinker -s that the binary size actually decreased.
If you want absolute minimum size, you should use "Embedded Swift". But that also requires not importing random libraries that aren't optimized for using on embedded devices (i.e. they import Foundation)
Small binaries that can be as tiny as a few hundred bytes for “Hello World”-like programs (fully self-contained).
Other modes will give you binary sizes that are acceptable on Apple devices where regular Swift is the primary language for development.
When creating an Xcode project for an executable target, STRIP_STYLE will be set to all, which is equivalent to -Xlinker -s. For Package.swift, you have to set that manually. There might be other differences too, you would have to compare the verbose output of a freshly created Xcode project build and Package.swift build.
I was just surprised by the 147 MB binary size!
But by using the option -Xlinker -s , the problem was resolved.
In the end, the resulting binary size turned out to be acceptable.
Have you checked how much of that is debug info? Without full generics specialization and dead code elimination that's only available in Embedded Swift mode, such statically linked binary is also likely to include debug info for all your dependencies, which would explain the final size.