Static Library and Shared Library
Usually, you have files (ex: main.cpp) calling functions from other files, which we call libraries.
We divide into 2 types of libraries
- static libraries (“
.a” extension) - shared libraries (”
.so” extension)
What is the difference between the 2 kinds of libraries?
The difference is that a static library will generate a copy each time it is called, and the shared library has only one copy, which saves space.
// Static Library
add_library( hello libHelloSLAM.cpp )
// Shared library
add_library( hello_shared SHARED libHelloSLAM.cpp )
...
// Link the files at the end
target_link_libraries(helloExecutable hello)When do I need
add_library?Whenever you are including other
.hfiles, and these interface files have implementation files (.cppformat), you need to add those so they are linked properly. For Eigen,add_libraryis not needed because it doesn’t have.cppfiles, only.hfiles.
it searches for the makefile and executes it. A makefile can look like the following:
default:
g++ main.cpp -o outIsn't everything just a library?
im a little confused, isnt everything a library, like it just doesnt have a main?
- Object file (
.o): compiled output of one translation unit. It can contain functions/classes, and it can have undefined references.- Library (
.a/.so): a bundle of compiled code meant to be reused/linked by other targets.- Executable: a linked program that has an entry point (
mainin C/C++ is your entry point; the real entry is_startprovided by CRT/startup code).
Static libraries (.a)
When linking, the linker does NOT copy the whole .a into the executable, but rather extracts & copies only the needed member .os.
Result: Bigger binary, but the executable has no runtime dependency on the .a.
Shared libraries (.so/.dylib/.dll)
The linker does NOT copy the library code into your executable.
Result: smaller binary, but you must have the shared library available at runtime.
When we
apt install?Usually yes: when you apt install a library (the runtime package), you’re typically installing a shared library that lives on disk as versioned .so files.
How does the linker link a shared library (ex:libfoo.so) to an executable?
Executable contains:
- A dependency list (on Linux/ELF these show up as
NEEDEDentries): e.g. “needslibfoo.so.1” - A dynamic symbol table / relocation info: “I need symbol
foo_init” - Call indirections so calls can be patched once the real address is known
(Linux/ELF: PLT/GOT; Windows: import tables; macOS: dyld stubs)
So the executable contains instructions for how to connect, not the code itself.
How does a program call a shared library??
1) OS loads your executable
Kernel maps your executable into memory and transfers control to the runtime loader (dynamic linker).
- Linux:
ld-linux-x86-64.so.2(varies by arch) - macOS:
dyld - Windows: loader handles DLLs
2) Loader finds the shared libraries
It reads the executable’s dependency list (“NEEDED: libfoo.so.1”) and searches in paths like:
- embedded paths in the binary (e.g., rpath/runpath)
- environment variables (Linux:
LD_LIBRARY_PATH) - system library dirs (
/lib,/usr/lib, etc.) - cache (
ldconfigon Linux)
3) Loader maps the .so into memory
It memory-maps the library file into the process address space (like loading more code pages). Now the library’s code is in memory alongside your executable’s code.
4) Loader resolves symbols + relocations
It finds where foo_init actually lives inside libfoo.so and patches the call indirections so your program’s call to foo_init() jumps to the correct address.
After this, calling a library function is just a normal CPU jump/call to an address.
What happens when 2 programs use the same library at runtime?
Are there 2 copies of the library, or just 1 copy? It’s just 1 copy.
Then, can’t there be data race? but then can there not be data races?
no, because the library’s writable state (globals/heap, etc.) is per-process, so the two programs aren’t actually reading/writing the same bytes.
The library’s writable global state (its .data/.bss) is generally per-process, not shared across unrelated processes.
Link order rule (static libs)
For static libs, put objects before libraries:
- ✅
g++ main.o -lfoo - ❌
g++ -lfoo main.o(can fail: library scanned before symbols are known)