[2026] CMake Link Errors: LNK2019, undefined reference, and Fixes [#49-2]
이 글의 핵심
Fix undefined reference and LNK2019: missing.cpp, missing libraries, extern C, vcpkg toolchain, and link order. CMake-focused troubleshooting for C++ builds.
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
아래 코드는 mermaid를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
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
아래 코드는 mermaid를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
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/ static in 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 .cpp in CMake target.
- For external libs: docs, nm, dumpbin.
- cmake —graphviz for 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
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) |