# CMake Linking **`target_link_libraries(target PRIVATE|PUBLIC|INTERFACE libs)` links a target to libraries**. The keyword controls visibility: `PRIVATE` (only target needs it), `PUBLIC` (target and consumers), `INTERFACE` (only consumers). Basic linking: ```cmake add_executable(myapp main.cpp) target_link_libraries(myapp PRIVATE mylib) ``` This links the executable `myapp` to the library `mylib`. The library is private — consumers of `myapp` don't need it. Linking multiple libraries: ```cmake target_link_libraries(myapp PRIVATE mylib1 mylib2 mylib3) target_link_libraries(myapp PUBLIC system_lib) ``` Modern CMake uses **target names**, not raw flags or paths: ```cmake find_package(Eigen3 REQUIRED) target_link_libraries(myapp PRIVATE Eigen3::Eigen3) find_package(OpenGL REQUIRED) target_link_libraries(myapp PRIVATE OpenGL::GL) ``` Avoid the old style: ```cmake # OLD: don't do this target_link_libraries(myapp "-lm") link_directories(/usr/lib) include_directories(/usr/include/eigen3) # NEW: use targets find_package(Eigen3 REQUIRED) target_link_libraries(myapp PRIVATE Eigen3::Eigen3) ``` Visibility keywords: - `PRIVATE` — only `myapp` uses it at link time - `PUBLIC` — `myapp` uses it, and anything linking to `myapp` also needs it - `INTERFACE` — only consumers of `myapp` need it (used for header-only libraries) Example with header-only library: ```cmake add_library(headeronly INTERFACE) target_include_directories(headeronly INTERFACE include/) target_link_libraries(headeronly INTERFACE some_dependency) add_executable(myapp main.cpp) target_link_libraries(myapp PRIVATE headeronly) ``` Transitive linking: ```cmake add_library(liba a.cpp) add_library(libb b.cpp) target_link_libraries(libb PUBLIC liba) # libb depends on liba publicly add_executable(myapp main.cpp) target_link_libraries(myapp PRIVATE libb) # myapp gets both libb and liba ``` With `PUBLIC`, consumers automatically get transitive dependencies. This propagates include paths, compile definitions, and linking requirements. Use `target_include_directories()` and `target_compile_options()` for parallel configuration. They follow the same `PRIVATE|PUBLIC|INTERFACE` pattern. Modern CMake means target-based linking. Each target declares its dependencies explicitly, making builds predictable and modular.