5.3.3 · D1Build Systems & Toolchain

Foundations — Static libraries — .a - .lib, creation and linking

1,884 words9 min readBack to topic

Before you can read the parent note without tripping, you must own about ten little words: source file, compiler, object file, symbol, defined vs undefined, relocation, archive, symbol index, linker, executable. We'll define each in plain words, draw the picture it stands for, and say why the topic can't live without it. Each one leans on the one before, so read top to bottom.


1. Source file — the human-written recipe

Picture it as a recipe card written in English-ish words. The computer cannot run it directly; it's just letters. That's the whole reason the next tool exists.


2. Compiler — the translator

Figure — Static libraries — .a  -  .lib, creation and linking

Look at the figure: the recipe card (add.c, black) goes into the translator box and out comes a strip of numbers (the object file, red) — the same idea expressed in a language the chip can execute.


3. Object file — a half-built puzzle piece

Why "incomplete"? Imagine add.c calls a function helper() that lives in a different file. When the compiler translates add.c alone, it has no idea what numeric address helper will end up at. So it writes a placeholder: "call the function at ▢ — fill in later." That blank is the key to everything.


4. Symbol — the name on a piece

Figure — Static libraries — .a  -  .lib, creation and linking

In the figure, one object file has two lists. On the left, names it defines (its body exists here, marked with T = text/code). On the right, names it uses but does not define (marked U = undefined) — those are the ▢ blanks from step 3, each labelled with the name it's waiting for. The red add is the symbol we'll trace through the whole topic.

This exact T / U distinction is what nm libmath.a prints in the parent's Example 2. Now you know what those letters mean before you ever see them.


5. Archive — the labelled box

Picture a shoebox. You drop add.o, sub.o, mul.o into it and tape it shut as libmath.a. Nothing is combined or changed — each .o sits inside, whole, retrievable one at a time.


6. Symbol index — the box's table of contents

Without the index, the linker would have to open every .o in the box and scan it to find who defines add. With the index, it looks up add once and grabs the right member directly — like a book's index versus flipping through every page.


7. The Linker — the assembler of pieces

Figure — Static libraries — .a  -  .lib, creation and linking

Follow the figure left to right — this is the linker's single pass. It starts with main.o, which needs add (red, added to a "wanted" list). It then reaches the box libmath.a, looks add up in the index, pulls only add.o out, and copies its code into the growing program. sub.o, which nobody wanted, is left in the box. That selective grab is the "Selectivity" goal from the parent note.


8. Relocation — filling in the blanks (the gluing)

Once every U is matched and every blank filled, no requests remain unanswered → the result is a complete executable, a file the operating system can actually run. Because add's code was copied in, you can now delete libmath.a and the program still runs — the parent's "static guarantee."


The prerequisite map

compiler translates

Source file add dot c

Object file add dot o

Symbols defined T and undefined U

Archive dot a via ar

Symbol index via s flag

Linker matches U to T

Relocation fills blank addresses

Static library topic 5 dot 3 dot 3

Read it as a flow: text becomes an object file, which exposes symbols and goes into an archive; the index plus the symbols let the linker resolve names; relocation finishes the job — and all of that is the static-library topic.

Related build-system context worth peeking at once these click: Make and build dependency graphs · Compilation pipeline — preprocess, compile, assemble, link. And the Hinglish twin of the parent: 5.3.03 Static libraries — .a - .lib, creation and linking (Hinglish).


Equipment checklist

A source file is written in what and can/can't be run directly?
Plain text; it cannot be run directly — it must be compiled first.
What does a compiler produce and does it link?
Machine code in an object file; with -c it does NOT link — it stops at the relocatable .o.
Why is an object file called "relocatable"?
It contains blank placeholders for addresses (relocations) that the linker fills in later.
What is a symbol?
A name (function or global) that machine code provides or needs.
In nm output, what do T and U mean?
T = symbol defined here (text/code); U = symbol used but undefined here.
What is an archive (.a) physically?
A container file holding several .o object files side by side, built by ar.
What does the symbol index do and which flag writes it?
Maps each defined symbol to its member object for fast lookup; the s in ar rcs (or ranlib).
What are the linker's two jobs?
Match every undefined symbol to a definition, then relocate (fill in the real addresses) to make one executable.
Why can you delete the .a after building?
Static linking copied the needed code into the executable; the archive was only a build-time source.
Which single word distinguishes static from shared linking?
Timing — static binds at build time, shared binds at run time.