Description
Description
In order to build Swift for platforms such as armv6, armv7, or even less-powerful arm64 architectures, the ideal way to build is to cross-compile instead of trying to build the Swift toolchain directly on the target, which is very slow.
However, currently the build scripts in the swiftlang/swift repo do not properly support cross compilation for Linux architectures. For example, when trying to build for armv7 and an external sysroot, the first build steps completely fail to build for the desired architecture. As an example, here is the failure from cmark:
CMake Error at /usr/share/cmake-3.28/Modules/CMakeTestCCompiler.cmake:67 (message):
The C compiler
"~/.local/share/swiftly/bin/clang"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: '~/swift-main-build/build/Ninja-DebugAssert/cmark-linux-armv7/CMakeFiles/CMakeScratch/TryCompile-igXlDK'
Run Build Command(s): /usr/bin/ninja -v cmTC_8dc74
[1/2][ 50%][0.022s] ~/.local/share/swiftly/bin/clang --target=arm-unknown-linux-gnueabihf --sysroot=/usr/arm-linux-gnueabihf -Wno-unknown-warning-option -Werror=unguarded-availability-new -MD -MT CMakeFiles/cmTC_8dc74.dir/testCCompiler.c.o -MF CMakeFiles/cmTC_8dc74.dir/testCCompiler.c.o.d -o CMakeFiles/cmTC_8dc74.dir/testCCompiler.c.o -c ~/swift-main-build/build/Ninja-DebugAssert/cmark-linux-armv7/CMakeFiles/CMakeScratch/TryCompile-igXlDK/testCCompiler.c
[2/2][100%][0.039s] : && ~/.local/share/swiftly/bin/clang --target=arm-unknown-linux-gnueabihf --sysroot=/usr/arm-linux-gnueabihf -Wno-unknown-warning-option -Werror=unguarded-availability-new CMakeFiles/cmTC_8dc74.dir/testCCompiler.c.o -o cmTC_8dc74 && :
FAILED: cmTC_8dc74
: && ~/.local/share/swiftly/bin/clang --target=arm-unknown-linux-gnueabihf --sysroot=/usr/arm-linux-gnueabihf -Wno-unknown-warning-option -Werror=unguarded-availability-new CMakeFiles/cmTC_8dc74.dir/testCCompiler.c.o -o cmTC_8dc74 && :
/usr/bin/ld.gold: fatal error: /usr/arm-linux-gnueabihf/lib/../lib/Scrt1.o: unsupported ELF machine number 40
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Reproduction
To reproduce the first issue with cmark, run the following command in Linux/Ubuntu:
./swift/utils/build-script --cross-compile-hosts=linux-armv7 --build-llvm=0
Otherwise, run it without --build-llvm=0 to see other crashes that occur after LLVM is built for the host:
./swift/utils/build-script --cross-compile-hosts=linux-armv7
Basically, every step of compilation will fail without being patched.
Expected behavior
I would expect the above commands to succeed as long as the armv7 (armhf) libraries are installed in the host using something like:
apt install gcc-arm-linux-gnueabihf
Cross compilation should also work if using an external sysroot, like this:
./swift/utils/build-script --cross-compile-hosts=linux-armv7 --cross-compile-deps-path ./sysroot-debian-bookworm --cross-compile-append-host-target-to-destdir=False
Environment
Swift version 6.0.3 (swift-6.0.3-RELEASE)
Target: x86_64-unknown-linux-gnu
Additional information
I intend to look at updating the scripts to properly cross compile to linux- hosts. If this is not the proper path, please let me know, but this seems to be the most logical thing to use since --cross-compile-hosts can already cross-compile to other Apple platforms.
Here are the short terms goals of being able to cross compile using the build-script. Let's get the build scripts updated to make it possible to cross compile the following components to linux-armv7:
- Swift stdlib (which is libdispatch + stdlib)
- libdispatch
- foundation
- xctest
- swift-testing
This is the "minimal installation" that is needed for something like a cross-compilation Swift SDK (swift-sdk-generator).