source code file(.cpp,.cxx,.cc,.C,.c++) -> object files(.o,.obj) -> link object files together into an executable (app.exe, app), static library(.lib, .a), or dynamic library(.dll, .so)
If any of the source code files changed, we recompile them to generate a new object file and then run the linker with all the unchanged object files too.
a binary file that is specific to a particular version of a particular compiler configured with particular settings
If the compiler, version, or settings change, all the code needs to be rebuilt.
dynamic library: a library of machine code, just like an executable. it can be loaded and unloaded by an executable or other dynamic library at runtime.
static library: can only be loaded at compile time and can never be unloaded.
Because static libraries are available at build time, the linker builds them directly into the resulting executable.
Critically for performance, all calls into functions in the static library are just normal function calls. This means there’s no indirection through a pointer that is set at runtime when a dynamic library is loaded. It also means that the linker can perform “link time optimizations” such as inlining these functions.
The main downsides stem from needing the static libraries to be present at compile time. This makes them unsuitable for tasks such as loading user-created plugins. Perhaps most importantly for large projects, they must be linked in every build even if just one small source file was changed. Link times grow proportionally and can hinder rapid iteration. As a result, sometimes dynamic libraries will be used in development builds and static libraries will be used in release builds.