I just used the new Containerization tool written in Swift to build and test a linux Swift toolchain on my macOS desktop, thought I'd document how I did it.
- Install container 0.8.0 using the signed pkg, earlier releases don't work as well for building and testing the Swift toolchain. I have run it on macOS 15 and 26.
- The swift-docker repo contains the Dockerfiles that are run on the official CI for the various linux distros, so I copied over the one for Fedora 41, which simply installs package dependencies for the Swift toolchain build and a host release toolchain, renamed it to Containerfile (no reason other than it seemed appropriate, as both names work), and modified two lines: install Fedora 43 instead and the latest Swift 6.2.3 release. Finally, I followed the official container tutorial and command reference to build a new container image and then run a container using it:
> cp swift-docker/swift-ci/main/fedora/41/Dockerfile Containerfile
# Make the two edits above or whatever else you want in an editor
> container system start
> container build --tag fedora-43-swift --file Containerfile ./swift-docker
> container run --name linux-swift -it -c 6 -m 8G -v /Users/finagolfin/swift:/home/build-user/swift fedora-43-swift:latest /bin/bash
Building the image can take around 20 minutes with not much output shown at times, depending on the speed of your internet connection, so don't quit if it seems stuck. I configured the container with 6 CPU cores and 8 GiB of memory- more memory is always better when building Swift- then mounted my local Swift source checkout at /Users/finagolfin/swift/ onto the container, so I don't have to git clone all that source again.
- You are now in the running linux container, so go into the mounted
swift/directory and build the compiler and run it through the compiler validation suite:
> cd swift/
> ./swift/utils/build-script -ART --libdispatch
About 70% of the way through, the build failed because it tries to keep all 6 cores occupied, but the host Swift 6.2.3 compiler uses way too much memory for the 8 GiB I allocated, so I added the -j1 flag to turn off parallelism and get through that bit, then after 5 minutes, killed that and removed that flag again to go faster.
While I was able to build the compiler and corelibs before, container 0.8.0 is the first release where I was able to run the compiler validation suite and build SwiftPM later, as those really stress the container and there was a linux filesystem issue that would cause container 0.7.1 to lock up.
I saw some tests failing in this new Fedora 43 environment and filed an issue for that.
- To build the corelibs and package manager, I had to patch a line in llbuild:
diff --git a/utils/unittest/googletest/include/gtest/internal/gtest-port.h b/utils/unittest/googletest/include/gtest/internal/gtest-port.h
index b476a24c..f853f29f 100644
--- a/utils/unittest/googletest/include/gtest/internal/gtest-port.h
+++ b/utils/unittest/googletest/include/gtest/internal/gtest-port.h
@@ -354,6 +354,7 @@ typedef struct _RTL_CRITICAL_SECTION GTEST_CRITICAL_SECTION;
// mentioned above.
# include <unistd.h>
# include <strings.h>
+# include <stdint.h>
#endif // GTEST_OS_WINDOWS
#if GTEST_OS_LINUX_ANDROID
Next, I ran the following commands:
> ./swift/utils/build-script -ART --xctest -b --swift-testing --swift-testing-macros --skip-test-swift --install-llvm --install-swift --install-libdispatch --install-foundation --install-xctest --install-swift-testing --install-swift-testing-macros -p
> ./swift/utils/build-script -ART --xctest --skip-test-swift --skip-clean-libdispatch --skip-clean-foundation --skip-clean-xctest -p --skip-test-swiftpm --skip-clean-swiftpm --install-swiftpm --swift-driver --skip-test-foundation
> ./swift/utils/build-script -ART --xctest --skip-test-swift --skip-clean-libdispatch --skip-clean-foundation --skip-clean-xctest --swift-driver --skip-test-swift-driver --install-swift-driver --skip-clean-swift-driver
The reason it had to be split up into three separate commands is that some SwiftPM and Foundation tests fail on Fedora 43, which is not on the CI yet, so I had to skip those tests, but only after running them once to get their results.
A build preset won't work for the same reason, plus I only wanted the base toolchain, without extra tools that the presets add.
- You finally have a working toolchain at
build/Ninja-Release/toolchain-linux-aarch64/, which you can use to build and test packages like NIO:
> cd swift-nio/
> ../build/Ninja-Release/toolchain-linux-aarch64/usr/bin/swift test --parallel
Once you're done, simply exit to get back to your macOS shell and run container ls -a to see the stopped container. Any time you want to go back to working on the linux toolchain, run container start -i linux-swift to go back in.
That's it: thanks to the Containerization team for all their work on making this so easy to use, and Jaewon Hur for fixing the above linux filesystem issue. ![]()