Libraries and linking targets

CMake · Essentials · 12 min

Real projects are a graph of libraries and executables; CMake models exactly that.

Most projects are a few libraries plus one or more executables and tests that use them. Create a library target with add_library:

  • add_library(core STATIC a.cpp b.cpp) an archive linked into each user.
  • add_library(core SHARED ...) a .so / .dll / .dylib loaded at run time.
  • add_library(core a.cpp b.cpp) without a type: static or shared depending on the BUILD_SHARED_LIBS option, letting whoever builds decide.
  • add_library(core INTERFACE) a header-only library with no sources to compile.
  • add_library(core OBJECT ...) compiled objects without an archive, reused by other targets.

Then connect targets: target_link_libraries(app PRIVATE core). This does far more than pass -lcore. CMake builds core first, links it into app, and propagates core's usage requirements (include directories, compile definitions, further dependencies) to app. That propagation is the heart of modern CMake and is covered next.

Always link by target name, not by file path. A target name lets CMake track the dependency, choose the correct file name per platform and pass on requirements.

It's common to give libraries a namespaced alias, add_library(myproj::core ALIAS core), so code linking myproj::core works the same whether the library is built in the project or found as an installed package. A name containing :: is known to be a target, so typos become errors instead of a silent -lmyproj::core.

Example

cmake_minimum_required(VERSION 3.25)
project(shop LANGUAGES CXX)

add_library(core STATIC src/cart.cpp src/price.cpp)
add_library(shop::core ALIAS core)
target_include_directories(core PUBLIC include)
target_compile_features(core PUBLIC cxx_std_20)

add_executable(shop src/main.cpp)
target_link_libraries(shop PRIVATE shop::core)    # include/ and C++20 come along

add_executable(cart_test tests/cart_test.cpp)
target_link_libraries(cart_test PRIVATE shop::core)

# $ cmake -S . -B build -G Ninja && cmake --build build
# [1/6] Building CXX object CMakeFiles/core.dir/src/cart.cpp.o
# ...
# [7/7] Linking CXX executable cart_test

Remember

  • add_library creates STATIC, SHARED, INTERFACE or OBJECT libraries
  • target_link_libraries links and propagates usage requirements
  • Link by target name; provide a namespaced ALIAS like proj::core

Watch out for

  • Linking by a path like ${CMAKE_BINARY_DIR}/libcore.a, which loses build ordering and usage requirements.

Check yourself

  1. What does target_link_libraries(app PRIVATE core) do besides adding the library to the link line?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: cmake.org/cmake/help/latest/command/add_library.html