Context
A few weeks ago, I announced that I had managed to package Swift 5.10.1 for Gentoo using the official binaries built for Fedora 39. Fortuitous timing, of course, because as of a few days ago, Gentoo officially no longer supports the gold linker as being effectively abandoned upstream. Gentoo has used ld/lld as its default linker (depending on profile) for years while allowing you to install gold if you want, but packages can now no longer rely on gold. This is a problem, because all of the prebuilt Swift binaries currently built for Linux default to using gold, since it's readily available on those systems, and means that I'll need to transition over to source builds of Swift in order to keep packaging it.
In order to do this, I need to:
- Build the Swift project using
lldon Linux in such a way that, - The built Swift defaults to also using
lld
I haven't gotten to explore (2) yet, though, because I cannot get the Swift project to build using lld.
(For reference, the latest Gentoo profile uses Clang + LLVM 17 systemwide)
What I've Tried
The base build-script invocation I'm currently using is
./utils/build-script \
--verbose-build \
--release \
--swift-install-components='autolink-driver;compiler;clang-resource-dir-symlink;libexec;stdlib;swift-remote-mirror;sdk-overlay;static-mirror-lib;toolchain-tools;license;sourcekit-inproc' \
--llvm-install-components='llvm-ar;llvm-cov;llvm-profdata;IndexStore;clang;clang-resource-headers;compiler-rt;clangd;lld;LTO;clang-features-file' \
--llbuild --skip-test-llbuild \
--swiftpm --skip-test-swiftpm \
--swift-driver --skip-test-swift-driver \
--xctest --skip-build-xctest \
--libicu --skip-test-libicu \
--swiftdocc --skip-test-swiftdocc \
--lldb --skip-test-lldb \
--foundation --skip-test-foundation \
--libdispatch --skip-test-libdispatch \
--indexstore-db --skip-test-indexstore-db \
--sourcekit-lsp --skip-test-sourcekit-lsp \
--bootstrapping=bootstrapping \
--skip-early-swift-driver --skip-early-swiftsyntax
Most of these flags are pulled directly from the presets.ini for the Linux buildbot, with bootstrapping enabled (and since the system doesn't have a Swift installation, we have to bootstrap and skip the early Swift driver and Swift Syntax; I don't know what the bootstrapping story will be for Swift 6, but one thing at a time).
-
If I run this invocation, the project manages to build LLVM and cmark before failing to build Swift due to trying to link using
-fuse-ld=gold -
If I add
--extra-cmake-options="-DSWIFT_USE_LINKER=lld"to force the usage oflld, the project manages to build LLVM and cmark, before failing to build Swift due to missing symbols in Swift- It appears from searching around that
lldbehavior differs for ELF around--gc-sections, and the missing symbols are due to them being GC'd out by default
- It appears from searching around that
-
If I add
--extra-cmake-options="-DSWIFT_USE_LINKER=lld" --extra-swift-args="^.*\$;-Xlinker\;-z\;-Xlinker\;nostart-stop-gc", the project manages to build LLVM, cmark, Swift, and a few other dependencies before another one down the road fails to build due to-fuse-ld=gold -
It seems that all dependencies respect the
LLVM_USE_LINKERsetting (including Swift), so if I try--extra-cmake-options="-DLLVM_USE_LINKER=lld" --extra-swift-args="^.*\$;-Xlinker\;-z\;-Xlinker\;nostart-stop-gc", LLVM itself doesn't build due to undefined symbols:FAILED: lib/libIndexStore.so.15git : && /usr/lib/llvm/17/bin/clang++ --target=x86_64-unknown-linux-gnu -fPIC -Wno-unknown-warning-option -Werror=unguarded-availability-new -fno-stack-protector -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-class-memaccess -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wno-comment -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -Wl,-z,defs -Wl,-z,nodelete -fuse-ld=lld -Wl,--color-diagnostics -Wl,--version-script,"/home/itai/Development/swift-project/build/Ninja-ReleaseAssert/llvm-linux-x86_64/tools/clang/tools/IndexStore/IndexStore.exports" -shared -Wl,-soname,libIndexStore.so.15git -o lib/libIndexStore.so.15git tools/clang/tools/IndexStore/CMakeFiles/IndexStore.dir/IndexStore.cpp.o -Wl,-rpath,"\$ORIGIN/../lib:" lib/libclangIndex.a lib/libclangIndexDataStore.a lib/libLLVMSupport.a lib/libclangIndex.a lib/libclangFormat.a lib/libclangToolingInclusions.a lib/libclangFrontend.a lib/libclangDriver.a lib/libLLVMWindowsDriver.a lib/libclangParse.a lib/libclangCAS.a lib/libLLVMOption.a lib/libLLVMRemoteCachingService.a lib/libLLVMCAS.a lib/libLLVMRemoteNullService.a lib/libclangSerialization.a lib/libclangSema.a lib/libclangAPINotes.a lib/libclangEdit.a lib/libclangAnalysis.a lib/libclangASTMatchers.a lib/libclangAST.a lib/libLLVMFrontendOpenMP.a lib/libLLVMScalarOpts.a lib/libLLVMAggressiveInstCombine.a lib/libLLVMInstCombine.a lib/libLLVMTransformUtils.a lib/libLLVMAnalysis.a lib/libLLVMProfileData.a lib/libLLVMSymbolize.a lib/libLLVMDebugInfoPDB.a lib/libLLVMDebugInfoMSF.a lib/libLLVMDebugInfoDWARF.a lib/libLLVMObject.a lib/libLLVMMCParser.a lib/libLLVMMC.a lib/libLLVMDebugInfoCodeView.a lib/libLLVMIRReader.a lib/libLLVMAsmParser.a lib/libLLVMTextAPI.a lib/libclangSupport.a lib/libclangToolingCore.a lib/libclangRewrite.a lib/libclangLex.a lib/libclangBasic.a lib/libLLVMBitReader.a lib/libLLVMCore.a lib/libLLVMBinaryFormat.a lib/libLLVMRemarks.a lib/libLLVMBitstreamReader.a lib/libclangDirectoryWatcher.a lib/libLLVMSupport.a -lrt -ldl -lm /usr/lib64/libz.so /usr/lib64/libzstd.so /usr/lib64/libtinfo.so lib/libLLVMDemangle.a && : ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_store_units_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_store_set_unit_event_handler' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_occurrence_relations_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_record_reader_search_symbols' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_record_reader_symbols_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_record_reader_occurrences_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_record_reader_occurrences_in_line_range_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_record_reader_occurrences_of_symbols_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_unit_reader_dependencies_apply' failed: symbol not defined ld.lld: error: version script assignment of 'LLVM_15' to symbol 'indexstore_unit_reader_includes_apply' failed: symbol not defined clang++: error: linker command failed with exit code 1 (use -v to see invocation)It seems that the build script for LLVM toggles some setting when
LLVM_USE_LINKERis explicitly set, because it useslldjust fine when I don't set that -
I've also tried using
--extra-cmake-options="-DLLVM_USE_LINKER=lld,-DLLVM_NO_DEAD_STRIP:BOOL=TRUE"because--gc-sectionsis disabled whenLLVM_NO_DEAD_STRIPisn't set, but this doesn't appear to be the the issue -
I've also tried removing
--indexstore-db --skip-test-indexstore-dbbut it doesn't make a difference, as expected -
I've also tried, in conjunction with the above, pulling a page from
docs/OpenBSD.mdand adding--skip-build-clang-tools-extra --skip-build-compiler-rt --llvm-targets-to-build=hostjust in case it made a difference, but no dice
Is there a way to reliably build the Swift project on Linux with lld?
I'm not sure whether this is a supported configuration at all, or whether I should expect this to work. I could try somehow setting LLVM_USE_LINKER=lld for all dependencies other than LLVM itself, but I'm not sure that's a better solution than having consistent flags for compilation everywhere.
Are there any other flags or toggles I should be setting or trying to get things up and running? Thanks!