CMake Link Errors: LNK2019, undefined reference, and Fixes [#49-2]

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, .cpp not 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.

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 .cpp is independent; declarations are enough.
  • Link: the linker resolves symbols across objects and libraries.

Scenarios

ScenarioFix
New library, unresolved Boost/Asio symbolsfind_package + target_link_libraries with correct components
multiple definitionNo non-inline function definitions in headers included by multiple TUs; use inline, one .cpp, or static
cannot find -lfoo / find_package failsCMAKE_TOOLCHAIN_FILE (vcpkg), CMAKE_PREFIX_PATH
C library from C++extern "C" + link the C library
Subproject static libadd_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.


  • 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).


  • 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

  1. Extract symbol from the error.
  2. grep / IDE: declaration vs definition.
  3. Confirm .cpp in CMake target.
  4. For external libs: docs, nm, dumpbin.
  5. cmake --graphviz for dependency graph.
  6. CMAKE_EXE_LINKER_FLAGS=-Wl,--verbose (GCC) to see link line.

Quick fixes table

Error patternCheck
pthread_*Threads::Threads
dlopenCMAKE_DL_LIBS
_main / WinMainsubsystem and entry
vtable for ...virtuals implemented, .cpp linked
__atomic_*libatomic where needed
__gxx_personality_v0C++ 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.

  • 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

SymptomLikely causeFix
undefined referenceMissing definition or libAdd .cpp / target_link_libraries
cannot find -lfooPaths / toolchainvcpkg, find_library, PREFIX_PATH
C symbols missingManglingextern "C"
multiple definitionHeader definitionsinline / single .cpp

Next: Asio deadlock debugging (#49-3)

Previous: Segfault debugging (#49-1)


  • DB engine basics
  • Asio deadlock
  • Game engine basics