5.3.3 · D3Build Systems & Toolchain

Worked examples — Static libraries — .a - .lib, creation and linking

2,426 words11 min readBack to topic

This page is the exhaustive drill for Static libraries — .a / .lib, creation and linking. The parent taught you what a static library is and the three-stage pipeline. Here we hammer every situation the archiver and linker can throw at you — every link-order case, every degenerate archive, every "why did it break" moment — until nothing surprises you.

If a term below feels unfamiliar, it was built in the parent note or in The Linker — symbol resolution & relocation and Object files and relocation.


The scenario matrix

Think of building-and-linking-a-static-library as a machine with a few dials. Each dial has a few settings. A "scenario" is one combination of settings. The matrix below lists every dial and its extreme settings — the examples afterward each land on one row so that, together, they cover every cell.

# Dial (what varies) The settings we must cover
A Link order user-before-lib ✓ · lib-before-user ✗ · cyclic A↔B (needs a group)
B Symbol index present? ar rcs (indexed) · ar rc (no index → error/repair with ranlib)
C Selectivity archive has extra members you don't call → they must be omitted from the exe
D Degenerate archive empty .a (0 members) · single-member .a
E Naming libX.a + -lX ✓ · X.a + -lX ✗ (must pass full path)
F Runtime dependency delete the .a after build → exe still runs (the static guarantee)
G Duplicate symbols same symbol defined in two members → which one wins?
H Platform Unix ar · Windows lib.exe (same three stages)
I Word problem "50 functions, 12 objects" — measure the size win of selectivity
J Exam twist reorder a broken command line to make it link

The dials are signs and quadrants of the build world: just as an angle can land in any of four quadrants, a link command lands in one of these rows, and the "naive" approach fails in specific ones (A, B, E) exactly the way the naive arctan fails in quadrants II–IV.


Example 1 — Cell A (correct order) + Cell F (runtime)


Example 2 — Cell A (wrong order) + Cell J (exam twist)


Example 3 — Cell A (cyclic dependency)


Example 4 — Cell B (missing symbol index) + repair


Example 5 — Cell C (selectivity) + Cell I (word problem)


Example 6 — Cell D (degenerate archives)


Example 7 — Cell E (naming) + Cell G (duplicate symbols)


Example 8 — Cell H (Windows / MSVC)


Recall

Recall Which cells make the

naive "libs first" command fail? Cell A (link order) and, indirectly, cyclic A. Also Cell E fails at file-lookup time. These are the "wrong quadrant" cases.

Recall Why is an empty archive not an error?

Members are pulled only to resolve undefined symbols; zero members ⇒ nothing to pull ⇒ no-op (unless something actually needed a symbol from it).

Recall Bare

.o on the link line vs .o inside a .a — the key difference? A bare object is always included; an archive member is conditional — included only if it resolves a pending undefined symbol.

Recall Two members define the same symbol — error?

No. The linker extracts the first resolver, then the symbol is defined, so the second is never pulled. (Two bare objects would clash.)


See also: The Linker — symbol resolution & relocation · Make and build dependency graphs · Compilation pipeline — preprocess, compile, assemble, link · Shared libraries — .so / .dll.