Expand description
Finding a linker and telling it what to link.
Design: spec/04-driver-and-cli.md section 4.9. There is no linker of our own before 1.0, so
this finds one on the machine and builds the command line it wants.
The linker is invoked directly rather than through the system compiler driver. Going through
cc would be shorter to write and would borrow that compiler’s idea of where everything is,
and it would also mean this compiler cannot link on a machine that has no other compiler on
it, which is most of the machines a compiler ends up on. It would also make -### output a
line that does not say what happens, since the interesting half would be inside the program
being spawned.
§What is not decided here
The startup files and the library directories are looked for rather than configured, for the
same reason library looks for the headers: gcc settles this when it is built because a gcc
is built for the machine it will run on, and this is one binary that runs wherever it is
copied. So the shape of the answer is a list of candidates per platform of which the ones
that exist are taken, and a cross build says where the rest is with --sysroot.
§The compiler’s own runtime
crtbegin, crtend and the runtime libraries are found the same way, on the machine rather
than by configuration. Ours is librucc_builtins.a, looked for beside the compiler, and the
machine’s libgcc goes on after it for the parts we have not written, which today is the
unwinder and its personality routine. The C library goes in front of both, so that on a target
that has one its memcpy is the one that answers rather than ours. -fno-builtins-lib leaves
ours off, for somebody who wants libgcc to answer for everything.
On a static link the three archives go inside --start-group, because libc.a refers to the
unwinder and the unwinder refers back to libc.a, and a linker walking a list once resolves
whichever of the two it reaches first and leaves the other undefined. That circularity is the
whole reason -static failed before this, and it is issue #277.
§Linking for a machine that is not this one
Everything above describes a link against the machine running the compiler, and it is what runs
when the target is that machine. A target that is not is a different problem: there is no
crt1.o for it in /usr/lib, the libc.so there is the wrong architecture, and a line built
out of what is lying around either fails at the first input or, worse, links. So a cross link
does not look at this machine at all. It is built by rucc_sysroot::argv out of the target
and a sysroot under the cache directory, and spec/cross-compile/11-linking.md section 11.3 is
the design. cross_sysroot is the one place that decides which of the two it is.
Two conditions keep that out of the way of everything that works today. The target has to differ
from the host, and --sysroot must not have been given: somebody who assembled a tree and named
it is asking for the line above with their own root in front of every path, which is what a
cross compile with a real distribution tree in it has always been.
That second condition is also the escape hatch for a machine which has a distribution’s own cross
files installed, where /usr/lib/aarch64-linux-gnu really does hold an AArch64 crt1.o.
--sysroot=/ takes the line above, and then every directory it decides is that machine’s again.
§What is not here yet
Darwin, and Windows in Microsoft’s ABI. ld64 wants a platform version load command and a
different set of default libraries, and lld-link wants a /-style command line and an import
library set out of an SDK nobody may redistribute. Each arrives with the target that needs it,
and a cross link to either is refused by name rather than approximated. A mingw-w64 target does
have a line, because PE in that environment is written in the GNU style and the import libraries
for it are ours to produce.
The headers are the other half of a cross compile and crate::library::header_dirs is where
they are decided. It asks cross_sysroot the same question this file asks it, which is the
point: a compile that took its libc from the sysroot and its declarations from this machine would
be wrong in the quietest way available, and one function answering for both is what stops that
being possible.
Structs§
- Link
Options - What the command line said about linking.
- Linker
- A linker, found.
Enums§
- Error
- Why a link could not be run.
- Item
- One item on the link line, in the order it was written, because link order is semantic.
Functions§
- builtins_
archive - Our own runtime library for this target, if it was built.
- candidates
- Where the library’s own files might be, in search order.
- cross_
kernel - The kernel headers that go with
cross_sysroot, for the targets that have any. - cross_
sysroot - The sysroot a cross link would use, or
Nonefor a link against this machine. - find
- The linker to use, looked for where a linker is.
- find_
in_ search - The full path of a file with that name, when one of the search directories holds it.
- line
- What the linker is told, in order, not counting the linker itself.
- multiarch
- The name a distribution that holds two architectures at once files this target under.
- order
- The names to look for, in the order section 4.9 gives.
- preflight
- Whether this link can be run at all, asked before anything is compiled.
- render
- The whole invocation as one line, quoted the way
-###prints it. - run
- Runs the linker and waits for it.
- runtime_
dirs - Where a gcc on this machine keeps
crtbegin.o,crtend.oandlibgcc.a, newest first. - search_
dirs - Where a library is looked for, in the order it is looked for in.