CMake Link Errors: LNK2019, undefined reference, and Fixes [#49-2]
이 글의 핵심
CMake link errors decoded: missing definitions, target_link_libraries, find_package, C++ vs C symbols, multiple definition, and production checklists.
Introduction: “undefined reference to ...” / LNK2019
undefined reference to 'symbol' (GCC/Clang) and LNK2019: unresolved external symbol (MSVC) mean the linker could not find a definition for a referenced symbol. Compile succeeds because declarations suffice; link fails when definitions are missing or wrong libraries are linked.
This article covers:
- Missing definitions, wrong translation units,
.cppnot in target - Missing
target_link_libraries find_package/ library not found (vcpkg toolchain,CMAKE_PREFIX_PATH)- C vs C++:
extern "C" - Link order and multiple definition
- CMake-centric debugging steps and CI hygiene
See also: CMake intro, Compilation pipeline, Advanced CMake.
Compile vs link
flowchart LR
subgraph Compile["Compile"]
A[.cpp] --> B[Compiler]
B --> C[.o / .obj]
end
subgraph Link["Link"]
C --> D[Linker]
E[.a / .so / .lib] --> D
D --> F[Executable / DLL]
end
- Compile: each
.cppis independent; declarations are enough. - Link: the linker resolves symbols across objects and libraries.
Scenarios
| Scenario | Fix |
|---|---|
| New library, unresolved Boost/Asio symbols | find_package + target_link_libraries with correct components |
multiple definition | No non-inline function definitions in headers included by multiple TUs; use inline, one .cpp, or static |
cannot find -lfoo / find_package fails | CMAKE_TOOLCHAIN_FILE (vcpkg), CMAKE_PREFIX_PATH |
| C library from C++ | extern "C" + link the C library |
| Subproject static lib | add_library + target_link_libraries(app PRIVATE mylib) |
Debugging flow
flowchart TB
A[Link error] --> B{Type?}
B -->|undefined| C[Symbol name → own code or lib?]
C -->|Own| D[Add .cpp / target_sources]
C -->|External| E[target_link_libraries]
B -->|multiple def| F[Header definitions / ODR]
B -->|not found| G[Toolchain / prefix path]
1. Reading error messages
- GCC/Clang:
undefined reference to \Qualified::Name“ - MSVC: mangled signature in LNK2019—match const, references, namespaces.
2. Missing definition / .cpp not built
Add the implementation .cpp to add_executable / add_library or target_sources. If logic lives in another static library, link that library to the executable.
3. Missing library link
find_package(Threads REQUIRED)→target_link_libraries(... Threads::Threads)- Boost: link
Boost::system,asio::asio, etc., not only include dirs. - Prefer imported targets over raw
-l.
4. Library not found
vcpkg:
vcpkg install fmt:x64-linux
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
find_package(fmt REQUIRED)
target_link_libraries(my_app PRIVATE fmt::fmt)
Always target_link_libraries after find_package—headers alone are not enough.
5. extern "C" for C libraries
C++ name mangling does not match C export names. Wrap C declarations in extern "C" (or use headers that already do).
6. Link order and multiple definition
- Some linkers are sensitive to left-to-right resolution; CMake target dependencies usually propagate order.
- ODR: one definition per symbol across the program;
inline/ single.cpp/staticin TU.
Example fixes (sketches)
Missing utils.cpp:
add_executable(app main.cpp utils.cpp)
Boost Asio:
find_package(Boost REQUIRED COMPONENTS system)
target_link_libraries(app PRIVATE Boost::system asio::asio)
Multiple definition from header:
inline int add(int a, int b) { return a + b; } // or move definition to .cpp
vcpkg fmt:
cmake -B build -DCMAKE_TOOLCHAIN_FILE=.../vcpkg.cmake
Debugging steps
- Extract symbol from the error.
grep/ IDE: declaration vs definition.- Confirm
.cppin CMake target. - For external libs: docs,
nm,dumpbin. cmake --graphvizfor dependency graph.CMAKE_EXE_LINKER_FLAGS=-Wl,--verbose(GCC) to see link line.
Quick fixes table
| Error pattern | Check |
|---|---|
pthread_* | Threads::Threads |
dlopen | CMAKE_DL_LIBS |
_main / WinMain | subsystem and entry |
vtable for ... | virtuals implemented, .cpp linked |
__atomic_* | libatomic where needed |
__gxx_personality_v0 | C++ linker / project(... LANGUAGES CXX) |
Production patterns
- IMPORTED / INTERFACE targets encapsulate paths.
- FetchContent pins versions.
- CI uses same vcpkg toolchain as dev.
- PUBLIC/PRIVATE propagation for includes and libs.
Related posts
- Segfault debugging
- Advanced CMake
- CMake intro
FAQ
Q. Practical use?
A. Any time link fails after compile: new deps, split modules, or cross-language boundaries.
Q. Read next?
A. Series index, CMake intro.
Q. Deep dive?
A. CMake documentation, GNU ld.
Summary
| Symptom | Likely cause | Fix |
|---|---|---|
undefined reference | Missing definition or lib | Add .cpp / target_link_libraries |
cannot find -lfoo | Paths / toolchain | vcpkg, find_library, PREFIX_PATH |
| C symbols missing | Mangling | extern "C" |
multiple definition | Header definitions | inline / single .cpp |
Next: Asio deadlock debugging (#49-3)
Previous: Segfault debugging (#49-1)
Related articles
- DB engine basics
- Asio deadlock
- Game engine basics