target_link_libraries() 是 CMake 中用于为目标指定链接依赖的核心命令,它管理目标之间的依赖关系并传递编译属性。
基本语法
1. 基础语法
cmake
target_link_libraries(<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
2. 旧式语法(不推荐)
cmake
target_link_libraries(<target> <item>...)
3. 导入目标语法
cmake
target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <imported-target>...)
作用域关键字详解
PUBLIC - 公共依赖
- 作用:依赖项的接口和实现都传递给使用者
- 使用场景:目标接口的一部分,使用者也需要
- 传递性:完全传递
cmake
# mylib.h 使用了 Boost 的某个功能
add_library(mylib src/mylib.cpp)
target_link_libraries(mylib PUBLIC Boost::boost)
# app 使用 mylib,自动获得 Boost 依赖
add_executable(app main.cpp)
target_link_libraries(app PRIVATE mylib) # 自动获得 Boost
PRIVATE - 私有依赖
- 作用:仅内部实现需要,不暴露给使用者
- 使用场景:内部实现细节,使用者不需要知道
- 传递性:不传递
cmake
# mylib 内部使用了 spdlog 进行日志记录
add_library(mylib src/mylib.cpp)
target_link_libraries(mylib PRIVATE spdlog::spdlog)
# app 使用 mylib,不会获得 spdlog 依赖
add_executable(app main.cpp)
target_link_libraries(app PRIVATE mylib) # 不会链接 spdlog
INTERFACE - 接口依赖
- 作用:目标本身不需要,但使用者需要
- 使用场景:头文件库、纯接口库
- 传递性:传递,但目标本身不链接
cmake
# 纯头文件库,需要 C++17
add_library(myheader INTERFACE)
target_link_libraries(myheader INTERFACE cxx_std_17)
# 应用程序需要 C++17 支持
add_executable(app main.cpp)
target_link_libraries(app PRIVATE myheader) # 获得 C++17 要求
链接项类型
1. CMake 目标
cmake
add_library(mylib STATIC mylib.cpp)
add_executable(myapp main.cpp)
# 链接库到可执行文件
target_link_libraries(myapp PRIVATE mylib)
# 库之间的链接
add_library(utils STATIC utils.cpp)
add_library(core STATIC core.cpp)
target_link_libraries(core PUBLIC utils) # core 使用 utils
2. 系统库和框架
cmake
# 系统库(全名)
target_link_libraries(myapp PRIVATE pthread dl m)
# 框架(macOS)
if(APPLE)
target_link_libraries(myapp PRIVATE
"-framework Cocoa"
"-framework CoreFoundation"
"-framework IOKit"
)
endif()
# Windows 库
if(WIN32)
target_link_libraries(myapp PRIVATE
ws2_32 # Winsock
shell32
user32
gdi32
)
endif()
3. 导入目标(第三方库)
cmake
# Find 模块找到的库
find_package(OpenSSL REQUIRED)
target_link_libraries(myapp PRIVATE OpenSSL::SSL OpenSSL::Crypto)
find_package(ZLIB REQUIRED)
target_link_libraries(myapp PRIVATE ZLIB::ZLIB)
# Qt 模块
find_package(Qt5 COMPONENTS Core Widgets Gui REQUIRED)
target_link_libraries(myapp PRIVATE
Qt5::Core
Qt5::Widgets
Qt5::Gui
)
# Boost 库
find_package(Boost REQUIRED COMPONENTS filesystem system thread)
target_link_libraries(myapp PRIVATE
Boost::filesystem
Boost::system
Boost::thread
)
4. 链接选项和标志
cmake
# 链接器标志
target_link_libraries(myapp PRIVATE "-Wl,--as-needed")
# 库搜索路径
target_link_libraries(myapp PRIVATE "-L/path/to/libs" -lmylib)
# 条件链接
target_link_libraries(myapp PRIVATE
$<$<CONFIG:Debug>:-fsanitize=address>
$<$<PLATFORM_ID:Linux>:"-Wl,-rpath,$ORIGIN">
)
现代 CMake 链接模式
1. 传递依赖示例
cmake
# 库层次结构示例
add_library(base STATIC base.cpp)
target_include_directories(base PUBLIC include/base)
target_compile_definitions(base PUBLIC BASE_LIB=1)
add_library(utils STATIC utils.cpp)
target_include_directories(utils PUBLIC include/utils)
target_compile_definitions(utils PUBLIC UTILS_LIB=1)
target_link_libraries(utils PUBLIC base) # utils 需要 base
add_library(core SHARED core.cpp)
target_include_directories(core PUBLIC include/core)
target_link_libraries(core PUBLIC utils) # core 需要 utils(从而也获得 base)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE core) # app 获得 core, utils, base 的所有接口
2. 接口库的使用
cmake
# 创建编译要求接口库
add_library(compiler_requirements INTERFACE)
target_compile_features(compiler_requirements INTERFACE cxx_std_17)
target_compile_options(compiler_requirements INTERFACE
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)
# 创建头文件接口库
add_library(headers_only INTERFACE)
target_include_directories(headers_only INTERFACE include)
target_compile_definitions(headers_only INTERFACE HEADERS_ONLY=1)
# 实际库使用接口库
add_library(mylib mylib.cpp)
target_link_libraries(mylib
PUBLIC
compiler_requirements # 传递编译要求
headers_only # 传递头文件路径
PRIVATE
Threads::Threads # 私有线程依赖
)
# 应用程序继承所有接口
add_executable(app main.cpp)
target_link_libraries(app PRIVATE mylib) # 获得所有接口要求
3. 对象库的链接
cmake
# 创建对象库
add_library(common_objects OBJECT common1.cpp common2.cpp)
target_compile_definitions(common_objects PUBLIC COMMON_CODE=1)
# 多个目标共享对象文件
add_library(libA STATIC libA.cpp $<TARGET_OBJECTS:common_objects>)
add_library(libB SHARED libB.cpp $<TARGET_OBJECTS:common_objects>)
# 可执行文件也使用对象文件
add_executable(app main.cpp $<TARGET_OBJECTS:common_objects>)
# 对象库也可以有依赖
target_link_libraries(common_objects INTERFACE cxx_std_17)
高级链接特性
1. 条件链接
cmake
# 根据配置链接不同库
target_link_libraries(myapp
PRIVATE
$<$<CONFIG:Debug>:debug_lib>
$<$<CONFIG:Release>:optimized_lib>
$<$<CONFIG:Release>:-flto> # 链接时优化
)
# 根据特性启用链接
if(ENABLE_CUDA)
find_package(CUDA REQUIRED)
target_link_libraries(myapp PRIVATE CUDA::cudart)
endif()
if(ENABLE_OPENMP)
find_package(OpenMP REQUIRED)
target_link_libraries(myapp PRIVATE OpenMP::OpenMP_CXX)
endif()
# 平台特定链接
target_link_libraries(myapp PRIVATE
$<$<PLATFORM_ID:Linux>:rt> # Linux 实时扩展
$<$<PLATFORM_ID:Windows>:version> # Windows 版本库
$<$<PLATFORM_ID:Darwin>:"-framework CoreServices">
)
2. 链接顺序控制
cmake
# 显式控制链接顺序(有时需要)
target_link_libraries(myapp PRIVATE
# 基础库先链接
base_lib
# 中间层库
middle_lib
# 高层库最后
high_level_lib
# 系统库最后
pthread
dl
m
)
# 循环依赖解决方案
add_library(libA STATIC a.cpp)
add_library(libB STATIC b.cpp)
# 方法1:使用对象库打破循环
add_library(common_objects OBJECT common.cpp)
target_link_libraries(libA PUBLIC $<TARGET_OBJECTS:common_objects>)
target_link_libraries(libB PUBLIC $<TARGET_OBJECTS:common_objects>)
# 方法2:使用接口库定义公共接口
add_library(common_interface INTERFACE)
target_include_directories(common_interface INTERFACE include)
target_link_libraries(libA PRIVATE common_interface)
target_link_libraries(libB PRIVATE common_interface libA) # 单向依赖
3. 链接优化选项
cmake
# 链接时优化(LTO)
target_link_libraries(myapp PRIVATE
$<$<CONFIG:Release>:-flto>
$<$<CXX_COMPILER_ID:GNU>:-fuse-linker-plugin>
)
# 去除未使用符号
target_link_libraries(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-Wl,--gc-sections>
$<$<CXX_COMPILER_ID:GNU>:-ffunction-sections>
$<$<CXX_COMPILER_ID:GNU>:-fdata-sections>
$<$<CXX_COMPILER_ID:Clang>:-dead_strip>
$<$<CXX_COMPILER_ID:AppleClang>:-dead_strip>
$<$<CXX_COMPILER_ID:MSVC>:/OPT:REF>
$<$<CXX_COMPILER_ID:MSVC>:/OPT:ICF>
)
# 安全强化选项
target_link_libraries(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wl,-z,relro>
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-Wl,-z,now>
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:-fstack-protector-strong>
)
完整项目示例
示例1:复杂库依赖项目
cmake
cmake_minimum_required(VERSION 3.15)
project(EnterpriseApp VERSION 1.0.0)
# 基础工具库(完全私有)
add_library(tools STATIC src/tools/logger.cpp src/tools/config.cpp)
target_include_directories(tools PRIVATE include/tools)
target_compile_definitions(tools PRIVATE TOOLS_INTERNAL)
target_link_libraries(tools PRIVATE spdlog::spdlog) # 内部日志,不暴露
# 数据访问层(需要序列化,暴露给业务层)
add_library(data_access STATIC src/data/database.cpp src/data/cache.cpp)
target_include_directories(data_access PUBLIC include/data)
target_link_libraries(data_access
PUBLIC
cxx_std_17 # 要求 C++17
$<$<BOOL:${USE_SQLITE}>:SQLite::SQLite> # 条件依赖
PRIVATE
tools # 内部使用工具
$<$<BOOL:${USE_REDIS}>:hiredis> # 私有 Redis 客户端
)
# 业务逻辑层(核心库)
add_library(business_logic SHARED src/business/processor.cpp src/business/validator.cpp)
target_include_directories(business_logic PUBLIC include/business)
target_compile_definitions(business_logic PUBLIC BUSINESS_API)
target_link_libraries(business_logic
PUBLIC
data_access # 公开依赖数据层
Boost::asio # 公开网络功能
PRIVATE
tools # 私有工具
Threads::Threads # 私有线程支持
$<$<PLATFORM_ID:Linux>:rt> # 平台特定私有依赖
)
# Web 服务层
add_library(web_service MODULE src/web/server.cpp src/web/routes.cpp)
target_link_libraries(web_service
PUBLIC
business_logic # 依赖业务逻辑
civetweb::civetweb # Web 服务器
PRIVATE
nlohmann_json::nlohmann_json # JSON 处理(内部)
OpenSSL::SSL # HTTPS 支持
)
# 主应用程序
add_executable(main_server src/main/server_main.cpp)
target_link_libraries(main_server
PRIVATE
web_service # 主要功能
$<$<CONFIG:Debug>:backward> # 调试时的栈回溯
PUBLIC
cxx_std_17 # 传递 C++17 要求
)
# 命令行工具(共享部分依赖)
add_executable(cli_tool src/main/cli_tool.cpp)
target_link_libraries(cli_tool
PRIVATE
business_logic # 复用业务逻辑
cxxopts::cxxopts # CLI 参数解析
PUBLIC
cxx_std_17
)
# 测试可执行文件
add_executable(run_tests EXCLUDE_FROM_ALL src/tests/main.cpp)
target_link_libraries(run_tests
PRIVATE
business_logic
data_access
GTest::gtest_main
GTest::gmock
)
示例2:跨平台 GUI 应用
cmake
cmake_minimum_required(VERSION 3.16)
project(PhotoManager VERSION 2.1.0)
# 核心图像处理库(跨平台)
add_library(image_core SHARED
src/core/image_processor.cpp
src/core/filter_engine.cpp
)
target_include_directories(image_core PUBLIC include/core)
target_compile_definitions(image_core PUBLIC IMAGE_CORE_EXPORTS)
# 平台特定后端
if(WIN32)
add_library(backend_win32 STATIC src/backend/win32/directx_backend.cpp)
target_link_libraries(backend_win32 PRIVATE d3d11 dxgi)
target_link_libraries(image_core PRIVATE backend_win32)
elseif(APPLE)
add_library(backend_macos STATIC src/backend/macos/metal_backend.mm)
target_link_libraries(backend_macos PRIVATE
"-framework Metal"
"-framework MetalKit"
"-framework CoreGraphics"
)
target_link_libraries(image_core PRIVATE backend_macos)
elseif(UNIX)
add_library(backend_linux STATIC src/backend/linux/opengl_backend.cpp)
find_package(OpenGL REQUIRED)
target_link_libraries(backend_linux PRIVATE OpenGL::GL)
target_link_libraries(image_core PRIVATE backend_linux)
endif()
# 通用依赖
find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui)
find_package(libpng REQUIRED)
find_package(JPEG REQUIRED)
target_link_libraries(image_core
PUBLIC
OpenCV::opencv
libpng::libpng
JPEG::JPEG
PRIVATE
Threads::Threads
cxx_std_17
)
# GUI 层(平台特定)
if(WIN32)
# Windows: Win32 API
add_executable(photo_manager WIN32 src/win32/main.cpp src/win32/window.cpp)
target_link_libraries(photo_manager
PRIVATE
image_core
comctl32
comdlg32
shlwapi
PUBLIC
cxx_std_17
)
elseif(APPLE)
# macOS: Cocoa
add_executable(photo_manager MACOSX_BUNDLE src/macos/main.mm src/macos/app_delegate.mm)
set_target_properties(photo_manager PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_GUI_IDENTIFIER "com.company.photos"
)
target_link_libraries(photo_manager
PRIVATE
image_core
"-framework Cocoa"
"-framework QuartzCore"
"-framework CoreImage"
PUBLIC
cxx_std_17
)
else()
# Linux: GTK
find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
add_executable(photo_manager src/linux/main.cpp src/linux/gtk_window.cpp)
target_include_directories(photo_manager SYSTEM PRIVATE ${GTK3_INCLUDE_DIRS})
target_link_libraries(photo_manager
PRIVATE
image_core
${GTK3_LIBRARIES}
cairo
gdk_pixbuf-2.0
PUBLIC
cxx_std_17
)
endif()
# 插件系统
add_library(plugin_interface INTERFACE)
target_include_directories(plugin_interface INTERFACE include/plugins)
target_compile_definitions(plugin_interface INTERFACE PLUGIN_API_VERSION=2)
# 示例插件
add_library(filter_plugin MODULE src/plugins/filter_plugin.cpp)
target_link_libraries(filter_plugin
PRIVATE
plugin_interface
image_core
)
set_target_properties(filter_plugin PROPERTIES
PREFIX ""
SUFFIX ".pmplugin"
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
)
# 工具可执行文件(命令行版本)
add_executable(photo_cli src/cli/main.cpp)
target_link_libraries(photo_cli
PRIVATE
image_core
cxxopts::cxxopts
fmt::fmt
PUBLIC
cxx_std_17
)
示例3:高性能计算库
cmake
cmake_minimum_required(VERSION 3.18)
project(HighPerformanceCompute VERSION 3.0.0)
# 基础数学库
add_library(math_base STATIC
src/math/vector.cpp
src/math/matrix.cpp
src/math/quaternion.cpp
)
target_include_directories(math_base PUBLIC include/math)
target_compile_definitions(math_base PUBLIC MATH_BASE_API)
target_link_libraries(math_base PUBLIC cxx_std_17)
# SIMD 加速库(条件编译)
option(ENABLE_SIMD "启用 SIMD 优化" ON)
if(ENABLE_SIMD)
# 检测支持的 SIMD 指令集
include(CheckCXXCompilerFlag)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86|x86_64|AMD64")
check_cxx_compiler_flag(-msse2 HAS_SSE2)
check_cxx_compiler_flag(-mavx HAS_AVX)
check_cxx_compiler_flag(-mavx512f HAS_AVX512)
set(SIMD_SOURCES src/simd/x86/simd_math.cpp)
set(SIMD_FLAGS)
if(HAS_AVX512)
list(APPEND SIMD_FLAGS -mavx512f -mavx512cd)
target_compile_definitions(math_base PUBLIC USE_AVX512)
elseif(HAS_AVX)
list(APPEND SIMD_FLAGS -mavx)
target_compile_definitions(math_base PUBLIC USE_AVX)
elseif(HAS_SSE2)
list(APPEND SIMD_FLAGS -msse2)
target_compile_definitions(math_base PUBLIC USE_SSE2)
endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch64")
check_cxx_compiler_flag(-mfpu=neon HAS_NEON)
if(HAS_NEON)
set(SIMD_SOURCES src/simd/arm/neon_math.cpp)
set(SIMD_FLAGS -mfpu=neon)
target_compile_definitions(math_base PUBLIC USE_NEON)
endif()
endif()
if(SIMD_SOURCES)
add_library(math_simd STATIC ${SIMD_SOURCES})
target_compile_options(math_simd PRIVATE ${SIMD_FLAGS})
target_include_directories(math_simd PUBLIC include/simd)
target_link_libraries(math_simd PUBLIC math_base)
target_link_libraries(math_base PUBLIC math_simd)
endif()
endif()
# 并行计算支持
option(ENABLE_OPENMP "启用 OpenMP 并行" ON)
option(ENABLE_CUDA "启用 CUDA 加速" OFF)
option(ENABLE_OPENCL "启用 OpenCL 加速" OFF)
if(ENABLE_OPENMP)
find_package(OpenMP REQUIRED)
add_library(math_parallel STATIC src/parallel/openmp_math.cpp)
target_link_libraries(math_parallel PUBLIC math_base OpenMP::OpenMP_CXX)
target_link_libraries(math_base PUBLIC math_parallel)
endif()
if(ENABLE_CUDA)
find_package(CUDA REQUIRED)
enable_language(CUDA)
add_library(math_cuda STATIC src/cuda/cuda_math.cu)
set_target_properties(math_cuda PROPERTIES
CUDA_SEPARABLE_COMPILATION ON
CUDA_ARCHITECTURES "75;86" # Turing, Ampere
)
target_link_libraries(math_cuda PUBLIC math_base CUDA::cudart)
target_link_libraries(math_base PUBLIC math_cuda)
endif()
if(ENABLE_OPENCL)
find_package(OpenCL REQUIRED)
add_library(math_opencl STATIC src/opencl/opencl_math.cpp)
target_link_libraries(math_opencl PUBLIC math_base OpenCL::OpenCL)
target_link_libraries(math_base PUBLIC math_opencl)
endif()
# 线性代数求解器
find_package(LAPACK REQUIRED)
find_package(BLAS REQUIRED)
add_library(linear_algebra SHARED
src/linalg/solver.cpp
src/linalg/eigen.cpp
src/linalg/lu_decomposition.cpp
)
target_include_directories(linear_algebra PUBLIC include/linalg)
target_link_libraries(linear_algebra
PUBLIC
math_base
${LAPACK_LIBRARIES}
${BLAS_LIBRARIES}
PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-lm>
)
# 优化算法库
add_library(optimization STATIC
src/optimization/gradient_descent.cpp
src/optimization/genetic_algorithm.cpp
src/optimization/simulated_annealing.cpp
)
target_include_directories(optimization PUBLIC include/optimization)
target_link_libraries(optimization
PUBLIC
math_base
linear_algebra
PRIVATE
Threads::Threads
)
# 机器学习模块(可选)
option(BUILD_ML_MODULE "构建机器学习模块" OFF)
if(BUILD_ML_MODULE)
find_package(Eigen3 3.3 REQUIRED)
add_library(machine_learning SHARED
src/ml/neural_network.cpp
src/ml/decision_tree.cpp
src/ml/svm.cpp
)
target_include_directories(machine_learning PUBLIC include/ml)
target_link_libraries(machine_learning
PUBLIC
math_base
linear_algebra
optimization
Eigen3::Eigen
PRIVATE
$<$<BOOL:${ENABLE_CUDA}>:math_cuda>
)
endif()
# 主应用程序(计算密集型任务)
add_executable(hpc_demo src/apps/hpc_demo.cpp)
target_link_libraries(hpc_demo
PRIVATE
math_base
linear_algebra
optimization
$<$<BOOL:${BUILD_ML_MODULE}>:machine_learning>
fmt::fmt # 格式化输出
PUBLIC
cxx_std_17
$<$<BOOL:${ENABLE_OPENMP}>:OpenMP::OpenMP_CXX>
)
# 基准测试程序
add_executable(benchmark EXCLUDE_FROM_ALL src/benchmark/main.cpp)
target_link_libraries(benchmark
PRIVATE
math_base
linear_algebra
benchmark::benchmark
benchmark::benchmark_main
PUBLIC
cxx_std_17
)
调试和问题解决
1. 检查链接依赖
cmake
# 打印目标的链接依赖
function(print_link_dependencies target)
if(NOT TARGET ${target})
message(WARNING "目标 ${target} 不存在")
return()
endif()
message(STATUS "=== ${target} 的链接依赖 ===")
# 获取链接库
get_target_property(link_libs ${target} LINK_LIBRARIES)
if(link_libs)
message(STATUS "直接链接库:")
foreach(lib ${link_libs})
message(STATUS " - ${lib}")
endforeach()
endif()
# 获取接口链接库
get_target_property(interface_libs ${target} INTERFACE_LINK_LIBRARIES)
if(interface_libs)
message(STATUS "接口链接库:")
foreach(lib ${interface_libs})
message(STATUS " - ${lib}")
endforeach()
endif()
# 获取链接选项
get_target_property(link_opts ${target} LINK_OPTIONS)
if(link_opts)
message(STATUS "链接选项:")
foreach(opt ${link_opts})
message(STATUS " - ${opt}")
endforeach()
endif()
message(STATUS "======================")
endfunction()
# 使用示例
add_library(mylib mylib.cpp)
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE mylib pthread)
print_link_dependencies(myapp)
2. 诊断链接问题
cmake
# 检查未定义符号
if(UNIX)
set_target_properties(myapp PROPERTIES
LINK_FLAGS "-Wl,--no-undefined"
)
endif()
# 生成链接映射文件
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
target_link_libraries(myapp PRIVATE
$<$<CONFIG:Debug>:"-Wl,-Map,${CMAKE_CURRENT_BINARY_DIR}/myapp.map">
)
endif()
# 详细链接输出
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
target_link_libraries(myapp PRIVATE "-Wl,--verbose")
endif()
3. 验证依赖传递
cmake
# 验证 PUBLIC/PRIVATE 使用是否正确
function(validate_link_scope target)
get_target_property(link_libs ${target} LINK_LIBRARIES)
foreach(lib ${link_libs})
if(TARGET ${lib})
get_target_property(lib_type ${lib} TYPE)
# 检查接口库是否被 PRIVATE 链接
if(lib_type STREQUAL "INTERFACE_LIBRARY")
message(WARNING "目标 ${target} PRIVATE 链接了接口库 ${lib},考虑使用 INTERFACE")
endif()
endif()
endforeach()
endfunction()
最佳实践
1. 作用域选择原则
cmake
# PUBLIC: 当目标头文件使用了依赖项的功能时
add_library(network network.cpp)
target_include_directories(network PUBLIC include)
target_link_libraries(network PUBLIC Boost::asio) # 头文件需要 asio
# PRIVATE: 仅 .cpp 文件使用,头文件不暴露
add_library(logger logger.cpp)
target_link_libraries(logger PRIVATE spdlog::spdlog) # 仅在实现中使用
# INTERFACE: 目标本身不链接,但使用者需要
add_library(cpp17 INTERFACE)
target_link_libraries(cpp17 INTERFACE cxx_std_17) # 传递编译要求
2. 依赖管理策略
cmake
# 1. 明确声明所有依赖
# 2. 使用现代 CMake 目标而不是原始库名
# 3. 区分系统库和第三方库
# 4. 合理使用条件链接
# 5. 保持依赖层次清晰
3. 避免常见错误
cmake
# 错误:混合旧式和新式语法
target_link_libraries(myapp mylib) # 旧式,不指定作用域
target_link_libraries(myapp PUBLIC mylib2) # 新式
# 正确:统一使用新式语法
target_link_libraries(myapp
PRIVATE mylib # 私有依赖
PUBLIC mylib2 # 公共依赖
)
# 错误:错误的作用域
add_library(mylib mylib.cpp)
target_link_libraries(mylib PUBLIC internal_lib) # 应该用 PRIVATE
# 错误:循环依赖
target_link_libraries(libA PUBLIC libB)
target_link_libraries(libB PUBLIC libA) # 循环!
target_link_libraries() 是现代 CMake 依赖管理的核心,正确使用可以创建清晰、可维护的项目结构,自动处理复杂的依赖传递和属性传播。