What Is Linking? The Step That Builds the Final Binary
Linking is the build phase that takes compiled object files plus libraries and resolves all the references between them to produce a final runnable program.
Compiling and linking are two distinct steps. Compiling turns each source file into machine code with placeholders for anything it references elsewhere. Linking fills in those placeholders, connecting every reference to its definition and assembling the pieces into a complete executable or library. It is the moment separate compilation units become one program.
Where linking fits
A typical build compiles each source file independently, then links the results. Compilation catches per-file errors; linking catches cross-file ones. Only after linking succeeds do you have something you can actually run.
What linking resolves
- Function calls to definitions in other files or libraries.
- References to global variables and shared data.
- Library dependencies, static or dynamic.
- Final memory layout and entry point of the program.
Static vs dynamic linking
Static linking bakes library code into the executable at build time, producing a larger but self-contained binary. Dynamic linking leaves references to shared libraries resolved at load time, yielding smaller binaries that share libraries but depend on them being present.
Why linking can be slow
For large programs, linking can rival or exceed compilation in time, especially with many object files and big libraries. It is also memory-intensive, which is why link steps sometimes dominate or stall a build on constrained machines.
A quick example
Running gcc a.o b.o -o app is the linking step: it combines two already-compiled object files into one executable named app, resolving the references between them.
Linking in CI
Linking is a heavy, memory-hungry build phase, and a large link step can be slow or get OOM-killed on small runners. Larger runners (Latchkey) give the linker more memory and speed up builds, and transient OOM or toolchain failures during linking can be auto-retried.
Key takeaways
- Linking resolves references across compiled units to produce a runnable program.
- It is distinct from compiling and catches cross-file errors compilation cannot.
- Linking is memory-heavy and can be slow or OOM-killed on small runners.