Question bank — Static libraries — .a - .lib, creation and linking
The mechanics being probed: a static library is an ==archive of .o files plus a symbol
index, and the linker copies only the members it needs, resolving left-to-right in a
single pass==. Almost every trap here is a consequence of one of those two facts.
First, three pictures to anchor the vocabulary

The figure above shows the drawer: three envelopes (add.o, sub.o, mul.o), the index
card at the front listing which symbol lives in which envelope, and the rule that the
linker grabs a whole envelope or nothing.

Trace the figure left to right: main.o enters and puts add on the want-list (red).
When the scan reaches -lmath, add is pending, so the index matches and add.o is
pulled in (green), clearing the want-list. Reverse the order and the archive is scanned
with an empty want-list — nothing matches, nothing is pulled, and add fails later.

The figure shows the chain: pulling add.o introduces a new undefined symbol helper;
the linker loops back to the index, finds helper in util.o, and pulls that too — all
in one visit to the archive.

| aspect | static .a / .lib |
shared .so / import .lib → .dll |
|---|---|---|
| code lands in exe? | yes, copied at build time | no, only a reference is recorded |
| file needed at run time? | no — delete it freely | yes — the .so/.dll must be present |
what -l/import provides |
the actual object member | a stub pointing at the runtime library |
| mnemonic | "copy, not reference" | "reference, load later" |
See Shared libraries — .so / .dll and ELF and PE file formats for how the run-time loader finds the second column's files.
True or false — justify
A .a file must be present on disk for the finished executable to run.
Reordering main.o -lmath to -lmath main.o still links fine on GNU ld.
-lmath comes first, nothing is undefined yet so it pulls nothing, then main.o references add and it's too late.An archive built with ar rc (no s) can never be linked at all.
ranlib to add the index; the s flag just does that index step at creation time so the linker isn't stuck scanning members.If a static library defines 50 functions and you call 1, all 50 end up in your executable.
.o, unused ones are skipped, though everything inside a used member comes along.ar compiles your source code into the archive.
ar is a dumb archiver; it just bundles already-compiled .o files. The compiling was done earlier by gcc -c (Compilation pipeline — preprocess, compile, assemble, link).Two members of the same .a may define the same symbol without any problem.
.o files.Naming a file math.a lets you link it with -lmath.
-lNAME expands to lib<NAME>.a, so it searches for libmath.a; either rename the file or pass its full path directly.On Windows a .lib always contains real machine code just like a Unix .a.
.lib may be either a static library (real code) or an import library (tiny stubs pointing at a .dll); the second kind resolves names at link time but the code lives in the DLL loaded at run time.A static library has an entry point (a main) like a program.
main lives in the program that links against the library.Spot the error
gcc -lmath main.o -o app → what's wrong?
-lmath is scanned and add stays undefined; put main.o before -lmath.ar rc libmath.a add.o then a link fails with "archive has no index" — cause?
s flag was omitted, so there's no symbol table; fix with ar rcs at creation or ranlib libmath.a afterward.gcc -c add.c -o add.o but the file has no main — is that an error?
-c stops before linking and produces a relocatable object, which is exactly what a library member should be; main is neither needed nor wanted here.gcc main.c ./math.a -o app when the archive is named math.a — legal?
-l naming convention entirely, so math.a works even without the lib prefix.Cyclic dependency: -lA needs B, -lB needs A, listed once each — why might it fail?
-Wl,--start-group -lA -lB -Wl,--end-group to re-scan.nm libmath.a shows add marked U inside main.o's listing — is the library broken?
U means undefined/needed by that member, T means defined; main.o legitimately needs add, and some other member (or object) must provide the T.Shipping only the app.exe but the program crashes at launch with "DLL not found" — what happened?
.lib you linked was an import library, so real code stayed in a .dll that must ship alongside the exe — a shared-library trap, not a static one.Why questions
Why does the linker only pull members that resolve a currently undefined symbol?
Why must the library come after the objects that use it (Unix)?
ld is single-pass and only remembers symbols left undefined so far; a reference appearing later than its provider was never on the wanted list when the archive was scanned.Why is the symbol index (s) an optimization rather than raw necessity?
add → add.o) that makes resolution quick.Why can order within one archive be forgiving while order across libraries is strict?
-l is visited only once as the pass moves right, so cross-library dependencies must be ordered by hand.Why is it called a static library rather than dynamic?
Why do library sources get compiled with -c (stop before linking)?
Why does deleting the .a after building leave the executable working?
Edge cases
An empty archive (ar rcs libempty.a with no members) — is it valid?
-lempty simply resolves nothing and contributes no code, which is harmless unless a symbol was expected from it.You call a function that isn't defined in any linked object or library — what happens?
A used member of the .a itself references a symbol in another member — does that member get pulled too?
Two functions live in the same .o inside the library and you call only one — what comes in?
.o drags the whole object (and all its code) into the executable.The same symbol is defined both in your main.o and in a library member — which wins?
Linking the same -lmath twice on the command line — pointless or sometimes useful?
--start-group for ordering knots.Recall The single sentence that explains link-order failures
The linker keeps only symbols that are undefined so far, so a provider listed before its user is scanned with an empty want-list and contributes nothing.