Build the executable project on Linux using -Xswiftc -static-stdlib failed

Hi.

Is it possible to build a swift project on Linux using the -Xswiftc -static-stdlib flags?
What I want to archive, is to create command line tool which can be executed on other Linux machines without the need to install the swift. As far as I understand the -Xswiftc -static-stdlib flag should allow this but adding this flag produce errors during the Linking stage.

Compile Swift Module 'ExampleProject' (1 sources)
Linking ./.build/x86_64-unknown-linux/release/ExampleProject
/usr/bin/ld.gold: error: cannot find -ldispatch
clang: error: linker command failed with exit code 1 (use -v to see invocation)
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)
error: terminated(1): /home/mateusz/Developer/swift/4.2.1/usr/bin/swift-build-tool -f /home/mateusz/Developer/ExampleProject/.build/release.yaml main output:

Steps to reproduce (I assume that the Swift has been already installed):

  1. Init new project: swift package init --type executable
  2. Add import Framework to the created main.swift
  3. Build: swift build -c release -Xswiftc -static-stdlib

Additional information
Swift version:

Swift version 4.2.1 (swift-4.2.1-RELEASE)
Target: x86_64-unknown-linux-gnu

Here you can found output from the swift build -c release -Xswiftc -static-stdlib -Xlinker --verbose command

I have read the Building distributable executable using SwiftPM but I'm not sure if it describes the same problem :(.

3 Likes

Seems that (static) libdispatch is missing. I had fixed that a while ago, but, that was broken on the 4.2 release, so you would need to build from the current master to get that to work.

Thanks a lot for your response!

I assume that you are talking about swift-corelibs-libdispatch.

Is it a known issue? Do we have an issue that I could follow?
If this is a regression, then I believe, it is a good candidate for a test somewhere (if possible :thinking:).

Yeah, it is a known issue. It should have been resolved for the 5.0 release along with a test for that in the validation set to ensure that both versions of the library are present.

1 Like

Hi,
Thank you for your patience :).

I tried to install manually the swift-corelibs-libdispatch using:

cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ <path-to-source>
ninja
ninja install

but this produces only the libdispatch.so and if I understand it correctly this kind of libraries are linked dynamically.
Do you know how I can build it to get a libdispatch.a? Is there some additional parameter? I tried a -BUILD_SHARED_LIBS:ON/OFF but without luck.

Thanks in advice :)

-DBUILD_SHARED_LIBS=NO is required if you want to build it statically. How did that fail? That is currently being built by build-script --build-libdispatch, so I would expect this to work.

After I added a -DBUILD_SHARED_LIBS=NO (so changed OFF to NO) I could find a static library:

find / -type f -name "libdispatch.a"e
/usr/local/lib/libdispatch.a
/builds/ios/swift-corelibs-libdispatch/src/libdispatch.a

Unfortunately, after that I still saw a lot of /usr/bin/ld.gold: error: cannot find -ldispatch.
I also spotted:

Attempt to open /usr/lib/swift_static/linux/libdispatch.a failed

so I copied the generated libdispatch.a to this location.
This fixed the error (/usr/bin/ld.gold: error: cannot find -ldispatch) but unfortunately I still have errors during linking stage:

/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '$S8Dispatch0A5QueueCMa'
/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '$S8Dispatch0A5QueueC6global3qosAcA0A3QoSV0E6SClassO_tFZ'
/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '_NSConcreteStackBlock'
/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '_Block_copy'
...

Do I miss something?

To sum up:
To build the libdispatch.a I do:

apt-get install -y cmake ninja-build clang systemtap-sdt-dev libbsd-dev linux-libc-dev
git clone https://github.com/apple/swift-corelibs-libdispatch.git
cd swift-corelibs-libdispatch
cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DBUILD_SHARED_LIBS=NO
ninja
ninja install
cp /usr/local/lib/libdispatch.a /usr/lib/swift_static/linux/libdispatch.a
cd /builds/ios/azimoSlack
swift build -c release -Xswiftc -static-stdlib

all this commands are running on a docker.

It's not linking in swiftDispatch and BlocksRuntime. Adding -lswiftDispatch -lBlocksRuntime should help with those. I would've expected the autolinking to kick in though...

Thanks again for your time.
Unfortunately adding those parameters do not help. I'm not sure if I used them correctly. Firstly I added them to the swift build command

swift build -c release -Xswiftc -static-stdlib -Xswiftc -lswiftDispatch -Xswiftc -lBlocksRuntime

and this ended up with:

...
Linking ./.build/x86_64-unknown-linux/release/AzimoSlack
/usr/bin/ld.gold: error: cannot find -lswiftDispatch
/usr/bin/ld.gold: error: cannot find -lBlocksRuntime
/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '$S8Dispatch0A5QueueCMa'
/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '$S8Dispatch0A5QueueC6global3qosAcA0A3QoSV0E6SClassO_tFZ'
/builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/Core.build/Dispatch.swift.o:Array.swift.o:function $S4Core10background8functionyyyc_tF: error: undefined reference to '_NSConcreteStackBlock'
...

Adding them to the cmake -G Ninja ... produced an invalid parameter error.

You need to tell the linker where to fine the build of BlocksRuntime and the swift SDK overlay for libdispatch. They should be part of the libdispatch build.

Unfortunately I still have the same error.

What I have done is I installed the libblocksruntime-dev via apt-get install.
This gave me the libBlocksRuntime.a

find / -name "*BlocksRuntime*"e[0;m
/usr/lib/x86_64-linux-gnu/libBlocksRuntime.so.0.0.0
/usr/lib/x86_64-linux-gnu/libBlocksRuntime.so.0
/usr/lib/x86_64-linux-gnu/libBlocksRuntime.a
/usr/lib/x86_64-linux-gnu/libBlocksRuntime.so
/usr/local/lib/libBlocksRuntime.a
/builds/ios/swift-corelibs-libdispatch/cmake/modules/FindBlocksRuntime.cmake
/builds/ios/swift-corelibs-libdispatch/src/BlocksRuntime
/builds/ios/swift-corelibs-libdispatch/src/BlocksRuntime/BlocksRuntime.def
/builds/ios/swift-corelibs-libdispatch/CMakeFiles/BlocksRuntime.dir
/builds/ios/swift-corelibs-libdispatch/CMakeFiles/BlocksRuntime.dir/src/BlocksRuntime
/builds/ios/swift-corelibs-libdispatch/libBlocksRuntime.a```

and now I can see, in verbose mode of linker:

/usr/bin/ld.gold: Released descriptor 272 for "(null)"
/usr/bin/ld.gold: Attempt to open /usr/lib/swift_static/linux/libBlocksRuntime.so failed
/usr/bin/ld.gold: Attempt to open /usr/lib/swift_static/linux/libBlocksRuntime.a failed
/usr/bin/ld.gold: Attempt to open /builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/libBlocksRuntime.so failed
/usr/bin/ld.gold: Attempt to open /builds/ios/azimoSlack/.build/x86_64-unknown-linux/release/libBlocksRuntime.a failed
/usr/bin/ld.gold: Attempt to open //usr/lib/gcc/x86_64-linux-gnu/5.4.0/libBlocksRuntime.so failed
/usr/bin/ld.gold: Attempt to open //usr/lib/gcc/x86_64-linux-gnu/5.4.0/libBlocksRuntime.a failed
/usr/bin/ld.gold: Opened new descriptor 272 for "//usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/libBlocksRuntime.so"
/usr/bin/ld.gold: Attempt to open //usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/libBlocksRuntime.so succeeded
/usr/bin/ld.gold: Unlocking file "//usr/lib/gcc/x86_64-linux-gnu/5.4.0/../../../x86_64-linux-gnu/libBlocksRuntime.so"
/usr/bin/ld.gold: Released descriptor 272 for "(null)"

but errors remain the same :frowning:.

You mentioned also about linking to the swiftDispatch but I can not find anything related to this library.
Do I miss something?

That is part of the swift-corelibs-libdispatch build, which you cannot find a pre-existing package for. The libblocksruntime dependency should no longer be necessary as we are building that always now. The build output should contain a libswiftDispatch.so.

You're right, the libblocksruntime is not required. I don't know how I could miss that before.

Unfortunately, I can not found this share object after the swift-corelibs-libdispatch is built.
I'm searching it using:

find / -name "*swiftDispatch*"

and there is no output.
I'm building the master branch of the swift-corelibs-libdispatch. Today I also tried the swift-4.2-branch but with the same result.

Did you build swift-corelibs-libdispatch with -DENABLE_SWIFT=YES?

No, I didn't :(.
After I added this flag to the cmake -G Ninja ... I've got:

CMake Error at CMakeLists.txt:55 (message):
CMAKE_SWIFT_COMPILER must be defined to enable swift

so I added a -DCMAKE_SWIFT_COMPILER=/usr/bin/swiftc

and now I have this error:

  CMake Error at CMakeLists.txt:58 (find_package):
  Could not find a package configuration file provided by "Swift" with any of
  the following names:

    SwiftConfig.cmake
    swift-config.cmake

  Add the installation prefix of "Swift" to CMAKE_PREFIX_PATH or set
  "Swift_DIR" to a directory containing one of the above files.  If "Swift"
  provides a separate development package or SDK, be sure it has been
  installed.

but I can't find non of those files.

Those are in the swift build directory. You should pass -DSwift_DIR=/path/to/swift/build/lib/cmake/swift to the configure. You should take a look at my toolchain infrastructure for building the toolchain (GitHub - compnerd/toolchain-infrastructure: infrastructure for building a complete swift, clang, llvm toolchain) or look through build-script-impl (or alternatively, backport the changes and then use build-script to build everything).

Hi,
I've tried to use the build-script but unfortunately I couldn't do this on the docker as it required to much space on disk :frowning:.
I've also tried to install it on a laptop with the linux but after some time I ended up with this error:

./swift/utils/build-script --extra-cmake-options="-DBUILD_SHARED_LIBS=NO"  --libdispatch -- --install-libdispatch
(...)
/Developer/swift/swift-source
symlinking the system headers (/usr/include/c++) into the local clang build directory (/home/mateusz/Developer/swift/swift-source/build/Ninja-DebugAssert/llvm-linux-x86_64/include).
+ ln -s -f /usr/include/c++ /home/mateusz/Developer/swift/swift-source/build/Ninja-DebugAssert/llvm-linux-x86_64/include
+ /usr/bin/cmake --build /home/mateusz/Developer/swift/swift-source/build/Ninja-DebugAssert/llvm-linux-x86_64 -- -j8 all
[2360/2837] Building CXX object tools/clang/lib/DirectoryWatcher/CMakeFiles/clangDirectoryWatcher.dir/DirectoryWatcher.cpp.o
/home/mateusz/Developer/swift/swift-source/llvm/tools/clang/lib/DirectoryWatcher/DirectoryWatcher.cpp:34:41: warning: unused function 'getModTime' [-Wunused-function]
static Optional<llvm::sys::TimePoint<>> getModTime(StringRef path) {
                                        ^
1 warning generated.
[2617/2837] Linking CXX executable bin/clang-6.0
FAILED: bin/clang-6.0 
: && /usr/bin/clang++   -Wno-unknown-warning-option -Werror=unguarded-availability-new -g -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -std=c++11 -Wall -W -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wcovered-switch-default -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wstring-conversion -fcolor-diagnostics -fno-common -Woverloaded-virtual -Wno-nested-anon-types -g  -Wl,-allow-shlib-undefined   -Wl,--export-dynamic  -Wl,-rpath-link,/home/mateusz/Developer/swift/swift-source/build/Ninja-DebugAssert/llvm-linux-x86_64/./lib tools/clang/tools/driver/CMakeFiles/clang.dir/driver.cpp.o tools/clang/tools/driver/CMakeFiles/clang.dir/cc1_main.cpp.o tools/clang/tools/driver/CMakeFiles/clang.dir/cc1as_main.cpp.o tools/clang/tools/driver/CMakeFiles/clang.dir/apinotes_main.cpp.o tools/clang/tools/driver/CMakeFiles/clang.dir/cc1gen_reproducer_main.cpp.o  -o bin/clang-6.0  lib/libLLVMX86CodeGen.a lib/libLLVMX86AsmParser.a lib/libLLVMX86AsmPrinter.a lib/libLLVMX86Desc.a lib/libLLVMX86Disassembler.a lib/libLLVMX86Info.a lib/libLLVMX86Utils.a lib/libLLVMARMCodeGen.a lib/libLLVMARMAsmParser.a lib/libLLVMARMAsmPrinter.a lib/libLLVMARMDesc.a lib/libLLVMARMDisassembler.a lib/libLLVMARMInfo.a lib/libLLVMARMUtils.a lib/libLLVMAArch64CodeGen.a lib/libLLVMAArch64AsmParser.a lib/libLLVMAArch64AsmPrinter.a lib/libLLVMAArch64Desc.a lib/libLLVMAArch64Disassembler.a lib/libLLVMAArch64Info.a lib/libLLVMAArch64Utils.a lib/libLLVMPowerPCCodeGen.a lib/libLLVMPowerPCAsmParser.a lib/libLLVMPowerPCAsmPrinter.a lib/libLLVMPowerPCDesc.a lib/libLLVMPowerPCDisassembler.a lib/libLLVMPowerPCInfo.a lib/libLLVMSystemZCodeGen.a lib/libLLVMSystemZAsmParser.a lib/libLLVMSystemZAsmPrinter.a lib/libLLVMSystemZDesc.a lib/libLLVMSystemZDisassembler.a lib/libLLVMSystemZInfo.a lib/libLLVMMipsCodeGen.a lib/libLLVMMipsAsmParser.a lib/libLLVMMipsAsmPrinter.a lib/libLLVMMipsDesc.a lib/libLLVMMipsDisassembler.a lib/libLLVMMipsInfo.a lib/libLLVMAnalysis.a lib/libLLVMCodeGen.a lib/libLLVMCore.a lib/libLLVMipo.a lib/libLLVMInstCombine.a lib/libLLVMInstrumentation.a lib/libLLVMMC.a lib/libLLVMMCParser.a lib/libLLVMObjCARCOpts.a lib/libLLVMOption.a lib/libLLVMScalarOpts.a lib/libLLVMSupport.a lib/libLLVMTransformUtils.a lib/libLLVMVectorize.a -lpthread lib/libclangBasic.a lib/libclangAPINotes.a lib/libclangCodeGen.a lib/libclangDriver.a lib/libclangFrontend.a lib/libclangFrontendTool.a lib/libLLVMX86AsmPrinter.a lib/libLLVMX86Utils.a lib/libLLVMARMDesc.a lib/libLLVMARMAsmPrinter.a lib/libLLVMARMUtils.a lib/libLLVMARMInfo.a lib/libLLVMGlobalISel.a lib/libLLVMAArch64Desc.a lib/libLLVMAArch64AsmPrinter.a lib/libLLVMAArch64Info.a lib/libLLVMAArch64Utils.a lib/libLLVMPowerPCAsmPrinter.a lib/libLLVMSystemZDesc.a lib/libLLVMSystemZAsmPrinter.a lib/libLLVMSystemZInfo.a lib/libLLVMAsmPrinter.a lib/libLLVMDebugInfoCodeView.a lib/libLLVMDebugInfoMSF.a lib/libLLVMSelectionDAG.a lib/libLLVMMipsAsmPrinter.a lib/libLLVMMCDisassembler.a lib/libclangCodeGen.a lib/libLLVMCoroutines.a lib/libLLVMCoverage.a lib/libLLVMLTO.a lib/libLLVMObjCARCOpts.a lib/libLLVMPasses.a lib/libLLVMCodeGen.a lib/libLLVMipo.a lib/libLLVMBitWriter.a lib/libLLVMIRReader.a lib/libLLVMAsmParser.a lib/libLLVMLinker.a lib/libLLVMInstrumentation.a lib/libLLVMScalarOpts.a lib/libLLVMInstCombine.a lib/libLLVMVectorize.a lib/libLLVMTransformUtils.a lib/libLLVMTarget.a lib/libLLVMAnalysis.a lib/libLLVMObject.a lib/libclangRewriteFrontend.a lib/libclangARCMigrate.a lib/libclangStaticAnalyzerFrontend.a lib/libclangStaticAnalyzerCheckers.a lib/libclangStaticAnalyzerCore.a lib/libclangCrossTU.a lib/libclangIndex.a lib/libclangFrontend.a lib/libclangDriver.a lib/libLLVMOption.a lib/libLLVMProfileData.a lib/libclangParse.a lib/libLLVMMCParser.a lib/libclangSerialization.a lib/libclangSema.a lib/libclangAPINotes.a lib/libLLVMBitReader.a lib/libclangAnalysis.a lib/libclangEdit.a lib/libclangFormat.a lib/libclangToolingCore.a lib/libclangRewrite.a lib/libclangASTMatchers.a lib/libclangAST.a lib/libclangLex.a lib/libclangBasic.a lib/libLLVMCore.a lib/libLLVMBinaryFormat.a lib/libLLVMMC.a lib/libLLVMSupport.a -lz -lrt -ldl -ltinfo -lpthread -lm lib/libLLVMDemangle.a -Wl,-rpath,"\$ORIGIN/../lib" && :
clang: error: unable to execute command: Killed
clang: error: linker command failed due to signal (use -v to see invocation)
[2624/2837] Linking CXX executable bin/clang-check
ninja: build stopped: subcommand failed.
./swift/utils/build-script: fatal error: command terminated with a non-zero exit status 1, aborting

Did I do something wrong? You mentioned: backport the changes. What do you mean by that?

Seems like you ran out of memory during the link step. You will probably need 32G of RAM if you are using ld.bfd, and probably around 16G if you are using gold or lld. As to backporting the changes … you need to find the relevant changes, rewrite them to apply and adjust for semantic changes from the tree for the version of swift that you are trying to use and apply them and rebuild the projects.

1 Like

I've changed the default linker from ld.bfd to ld.gold but this do not help. The errors occurs definitely later then when using the ld.bfd so most likely memory is the reason (laptop has 16 GB of RAM).

this sounds really complicated :smile:. I don't know eaven where to start looking for those changes.
Maybe I will wait for swift 5 :thinking: