sylecn@agem10:~/fromsource/link-with-lld-example$ cabal build
Build profile: -w ghc-9.4.8 -O1
In order, the following will be built (use -v for more details):
- link-with-lld-example-1 (lib:link-with-lld-example, exe:link-with-lld-example) (first run)
Preprocessing executable 'link-with-lld-example' for link-with-lld-example-1..
Building executable 'link-with-lld-example' for link-with-lld-example-1..
[2 of 2] Linking /home/sylecn/fromsource/link-with-lld-example/dist-newstyle/build/x86_64-linux/ghc-9.4.8/link-with-lld-example-1/build/link-with-lld-example/link-with-lld-example
ld.lld: error: relocation R_X86_64_32S cannot be used against local symbol; recompile with -fPIC
>>> defined in /home/sylecn/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/../lib/x86_64-linux-ghc-9.4.8/base-4.17.2.1/libHSbase-4.17.2.1.a(Base.o)
>>> referenced by Base.o:(base_ControlziExceptionziBase_zdfShowNonTerminationzuzdcshowsPrec_info) in archive /home/sylecn/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/../lib/x86_64-linux-ghc-9.4.8/base-4.17.2.1/libHSbase-4.17.2.1.a
ld.lld: error: relocation R_X86_64_32S cannot be used against local symbol; recompile with -fPIC
>>> defined in /home/sylecn/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/../lib/x86_64-linux-ghc-9.4.8/base-4.17.2.1/libHSbase-4.17.2.1.a(Base.o)
>>> referenced by Base.o:(base_ControlziExceptionziBase_zdfShowNonTermination1_info) in archive /home/sylecn/.ghcup/ghc/9.4.8/lib/ghc-9.4.8/lib/../lib/x86_64-linux-ghc-9.4.8/base-4.17.2.1/libHSbase-4.17.2.1.a
It seems base package is not compatible with lld linker? What is the correct way to link with lld linker? Is the ghc installed by ghcup compatible with lld?
I have tried to uninstall and reinstall ghc using āghcup tuiā command, after installing lld, with
def-ghc-conf-options:
- "--enable-ld-override"
in ~/.ghcup/config.yaml
I believe this has the same effect as setting $LD. But I donāt know how to check whether it made a difference. Is there a command I can run or a log file I can check?
The build error persist after reinstall ghc this way.
Does setting $CC make a difference? should I set $LD and $CC and reinstall ghc?
So youāll have to edit the GHC settings file manually to add -fuse-ld=lld to āC compiler link flagsā. Otherwise it will likely not actually use lld.
OK. I was wrong. When I build the demo project, I forget to revert a local change I made that drop the lld settings. When I revert the change, build still fail.
On a second look on the ghc installer tarball (used by ghcup), it seems file ghc-9.4.8-x86_64-unknown-linux/lib/x86_64-linux-ghc-9.4.8/libHSbase-4.17.2.1-ghc9.4.8.so, ghc-9.4.8-x86_64-unknown-linux/lib/x86_64-linux-ghc-9.4.8/base-4.17.2.1/libHSbase-4.17.2.1.a
is included in the tarball. Would setting $LD and -fuse-ld=lld in settings file supposed to work at all? Since the original error is about that file not compiled with -fPIC.
tbh Iām not a big fan of editing settings directly. Sure, you need to jump through more hops to provide the right configure options, but configure does it job and checks for consistency; you are more likely to end up with a subtly broken bindist if you edit settings directly.
Side note: Since trying lld on linux is unsuccessful, I tried to build my own project on freebsd 14, which uses clang and lld by default. The build speed was not faster than on Linux despite using lld as linker. The VM used to run the build has similar hardware spec and runs on the same host.
In fact build with a clean cache took 22m29s in Linux VM, took 22m22s in FreeBSD VM.
The project that I built can be download from
if someone want to compare build speed between ld and lld linker.
On the subject of speed, Stackās CI was running its integration tests in an Alpine Linux Docker container on Ubuntu using ld.bfd as the linker (having built a statically-linked Stack for Linux).
Changing that to running them on Ubuntu and also specifying lld as the linker has reduced the time they take by a factor of 9.2 times. Some of that may be static v dynamic linking.
You can also remove the behaviour that GHC bakes in a specific linker at configure time by passing --disable-ld-override during configuration. If you pass that option then -fuse-ld will not be passed to the C compiler, and it will be free to determine under its own rules which linker to use.
By āat configure timeā are you referring to building GHC from source and configuring that build? (As I could not see a reference to --disable-ld-override in GHCās User Guide or at runghc Setup.hs configure --help.)
By ābindist configureā do you mean the configuration of building a GHC binary distribution from source? The only references to environment variables being used to configure GHC itself (once built) that I can see in its Userās Guide are at:
No, I mean the binary distribution tarball containing the compiled GHC. It also has a configure script. Iām not sure if its interface is documented at all.
I had previously looked at the contents of the āofficialā ghc-9.12.2-x86_64-unknown-mingw32.tar.xz and had not spotted anything going to configuration of GHC.
However, I see now that there is an (undocumented,§ I think) bin\ghc-toolchain-bin.exe. I tried:
> ghc-toolchain-bin --help
unrecognized option `--help'
ghc-toolchain
-t TRIPLE --triple=TRIPLE Target triple
-T PREFIX --target-prefix=PREFIX A target prefix which will be added to all tool names when searching for toolchain components
--llvm-triple=LLVM-TRIPLE LLVM Target triple
-v[N] --verbose[=N] set output verbosity
--keep-temp do not remove temporary files
-o OUTPUT --output=OUTPUT The output path for the generated target toolchain configuration
--enable-unregisterised Enable unregisterised backend
--disable-unregisterised Disable unregisterised backend
--enable-tables-next-to-code Enable info-tables-next-to-code optimisation
--disable-tables-next-to-code Disable info-tables-next-to-code optimisation
--enable-libffi-adjustors Enable the use of libffi for adjustors, even on platforms which have support for more efficient, native adjustor implementations.
--disable-libffi-adjustors Disable the use of libffi for adjustors, even on platforms which have support for more efficient, native adjustor implementations.
--enable-ld-override Enable override gcc's default linker
--disable-ld-override Disable override gcc's default linker
--enable-locally-executable Enable the use of a target prefix which will be added to all tool names when searching for toolchain components
--disable-locally-executable Disable the use of a target prefix which will be added to all tool names when searching for toolchain components
--cc=CC Path of C compiler
--cc-opt=OPTS Flags to pass to cc
--cpp=CPP Path of C preprocessor
--cpp-opt=OPTS Flags to pass to cpp
--hs-cpp=HS-CPP Path of Haskell C preprocessor
--hs-cpp-opt=OPTS Flags to pass to hs-cpp
--js-cpp=JS-CPP Path of JavaScript C preprocessor
--js-cpp-opt=OPTS Flags to pass to js-cpp
--cmm-cpp=CMM-CPP Path of C-- C preprocessor
--cmm-cpp-opt=OPTS Flags to pass to cmm-cpp
--cxx=CXX Path of C++ compiler
--cxx-opt=OPTS Flags to pass to cxx
--cc-link=CC-LINK Path of C compiler for linking
--cc-link-opt=OPTS Flags to pass to cc-link
--ar=AR Path of ar archiver
--ar-opt=OPTS Flags to pass to ar
--ranlib=RANLIB Path of ranlib utility
--ranlib-opt=OPTS Flags to pass to ranlib
--nm=NM Path of nm archiver
--nm-opt=OPTS Flags to pass to nm
--readelf=READELF Path of readelf utility
--readelf-opt=OPTS Flags to pass to readelf
--merge-objs=MERGE-OBJS Path of linker for merging objects
--merge-objs-opt=OPTS Flags to pass to merge-objs
--windres=WINDRES Path of windres utility
--windres-opt=OPTS Flags to pass to windres
--ld=LD Path of linker
--ld-opt=OPTS Flags to pass to ld
§Well-Typed LLP has, however, blogged in October 2023 about ghc-toolchain: