[WIP] internal lld linker by japaric · Pull Request #36120 · rust-lang/rust (original) (raw)
this commit embeds lld, the LLVM linker, into rustc. If the -Z use-lld
flag is passed to rustc, then rustc will use lld (via a library call),
instead of an external linker like cc, to link a Rust executable.
This has been tested in three different ways:
- Linking Hello World, but the
-pie
flag had to be omitted:
Note that lld doesn't implicitly pass libraries (-lc) or startup
object (crt1.o) like cc does, so one has to manually pass these to lld
via -C link-args
:
$ rustc -Z use-lld \
-C link-args='-dynamic-linker /lib64/ld-linux-x86-64.so.2 -L/usr/lib/gcc/x86_64-linux-gnu/5 -L/usr/lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o'
hello.rs
$ ./hello
Hello world!
- Linking a Rust program with zero C dependencies, i.e. a Rust "kernel".
Basically, I grabbed the "Hello, world" program from Intermezzos chapter 3 1
and turned it into a Cargo project 2 then proceeded to link it using lld.
This linked correctly and after turning the executable into a ISO image,
it also worked perfectly under QEMU!
- Linking A bare metal program for the Cortex-M3 microcontroller.
This didn't require a toolchain (arm-none-eabi-gcc
) or startup files
(newlib
). This test has been turned into a run-make test for this feature.
Extra notes
I've only tested ELF executables, not dylibs, MachO or COFF.
lld supports ELFs, MachO and COFF formats. So in theory, with an
internal lld we could drop the dependency on a external linker pretty
much on all the platforms we support.
Relevant news: "lld now implements almost all of the functionality
necessary to function as a system linker for FreeBSD/amd64" -- FreeBSD
folk @ LLVM mailing list 3. The e-mail also mentions that
support for other archs is not quite ready for prime time.
The question is: Would it make sense to start slowly integrating lld
into rustc right now? It would land behind an unstable flag '-Z
use-lld' and we could print a warning message about it being
experimental whenever the flag is used.
Scenarios where it could be advantageous to not depend on a external
linker:
- Building bare-metal/C-free programs, e.g. x86 kernel
development (already shown to work), embedded (microcontroller) ARM
programs (once lld supports Thumb). Today, to build C-free Rust
programs you still need a C linker (cc). Would be nice to drop the
dependency on cc if you are not going to compile C code. - @Diggsey mention that lld + the arm-musl targets effectively means one
can cross compile ARM binaries without relying on anything external:
no need for arm-gcc or arm-glibc. Justrustup target add $T
andcargo build --target $T
and you are done. This scenario hasn't been
tested though.
Downsides:
- lld is still being actively developed. some architectures have limited
support and features like linker scripts are not on parity with ld
yet. However, as mentioned above, the FreeBSD folks have had success
using it as a system linker on x86_64. At least, that architecture
appears to be reaching stability. - Maintenance. Upgrading LLVM means also having upgrading lld as those
need to be keep in sync or lld won't compile. This cuts both ways: if
we want to upgrade lld to support some new feature or fix some bug,
it's likely we'll have to upgrade LLVM as well -- this possibly means
updating LLVM more often.
P.S. This a PoC; the implementation is a mess/hack. It would have to be
cleaned up before merging it.
cc #9367
cc @alexcrichton @brson