add_library() 是 CMake 中用于创建库目标的核心命令,它将源代码文件编译链接成静态库、共享库或接口库。
基本语法
1. 普通库文件
cmake
add_library(<target> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])
2. 导入的库
cmake
add_library(<target> [STATIC | SHARED | MODULE | UNKNOWN] IMPORTED
[GLOBAL])
3. 接口库
cmake
add_library(<target> INTERFACE
[IMPORTED] [GLOBAL])
4. 别名库
cmake
add_library(<target> ALIAS <aliased-target>)
5. 对象库
cmake
add_library(<target> OBJECT [<source>...])
参数详解
必需参数
<target>
- 作用:定义库目标名称
- 命名规则 :
- 在项目中必须唯一
- 建议使用小写字母、数字和下划线
- 避免使用 CMake 关键字
- 生成的文件名 :
- 可通过
set_target_properties()修改 - 默认使用目标名作为库名
- 可通过
库类型关键字
| 类型 | 说明 | 生成文件 | 典型用途 |
|---|---|---|---|
STATIC |
静态库 | .a (Unix), .lib (Windows) |
链接时复制代码到可执行文件 |
SHARED |
共享库 | .so (Linux), .dylib (macOS), .dll (Windows) |
运行时动态加载 |
MODULE |
模块库 | 同共享库,但不链接到其他目标 | 插件、可加载模块 |
INTERFACE |
接口库 | 不生成实际库文件 | 仅头文件库、传递依赖 |
OBJECT |
对象库 | .obj/.o 文件集合 |
源码级复用 |
IMPORTED |
导入库 | 引用外部已构建的库 | 第三方库、系统库 |
详细用法示例
1. 静态库
cmake
# 创建静态库
add_library(mystatic STATIC
src/mylib.cpp
src/utils.cpp
include/mylib.h
)
# 设置静态库属性
set_target_properties(mystatic PROPERTIES
OUTPUT_NAME "mystatic" # 输出文件名
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
POSITION_INDEPENDENT_CODE ON # 启用 PIC(某些情况下需要)
)
# 链接静态库
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE mystatic)
2. 共享库
cmake
# 创建共享库
add_library(myshared SHARED
src/mylib.cpp
src/utils.cpp
include/mylib.h
)
# 设置版本信息
set_target_properties(myshared PROPERTIES
VERSION 1.2.3 # 完整版本号
SOVERSION 1 # API 版本号
OUTPUT_NAME "myshared" # 库文件名(不含扩展名)
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" # Windows DLL
)
# 平台特定设置
if(WIN32)
# Windows DLL 需要导出符号
target_compile_definitions(myshared PRIVATE MYSHARED_EXPORTS)
target_sources(myshared PRIVATE src/mylib.def) # 模块定义文件
endif()
# 链接共享库
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE myshared)
3. 模块库
cmake
# 创建模块库(插件)
add_library(myplugin MODULE
src/plugin.cpp
src/plugin_impl.cpp
include/plugin.h
)
# 模块库特定设置
set_target_properties(myplugin PROPERTIES
PREFIX "" # 移除 "lib" 前缀
SUFFIX ".plugin" # 自定义后缀
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
)
# 设置插件符号可见性
target_compile_definitions(myplugin PRIVATE
MYPLUGIN_BUILDING_DLL
)
# 导出插件接口
target_include_directories(myplugin PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
4. 接口库
cmake
# 创建接口库(仅头文件库)
add_library(myheader INTERFACE)
# 添加头文件包含目录
target_include_directories(myheader INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# 添加编译定义
target_compile_definitions(myheader INTERFACE
USE_MYHEADER=1
)
# 添加编译特性
target_compile_features(myheader INTERFACE cxx_std_17)
# 添加链接选项
target_link_libraries(myheader INTERFACE
Threads::Threads
)
# 使用接口库
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE myheader)
5. 对象库
cmake
# 创建对象库
add_library(myobjects OBJECT
src/common.cpp
src/utils.cpp
)
# 在其他目标中重用对象文件
add_executable(app1 app1.cpp)
add_executable(app2 app2.cpp)
# 链接对象库
target_link_libraries(app1 PRIVATE myobjects)
target_link_libraries(app2 PRIVATE myobjects)
# 对象库也可以有自己的依赖
target_include_directories(myobjects PUBLIC include)
target_compile_definitions(myobjects PRIVATE COMMON_DEFINE=1)
6. 导入库
cmake
# 导入已存在的库
add_library(external_lib STATIC IMPORTED)
# 设置导入库的路径
set_target_properties(external_lib PROPERTIES
IMPORTED_LOCATION "/usr/lib/libexternal.a"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include/external"
)
# 导入不同配置的库
add_library(external_shared SHARED IMPORTED)
set_target_properties(external_shared PROPERTIES
IMPORTED_LOCATION_DEBUG "/path/to/debug/libexternal.so"
IMPORTED_LOCATION_RELEASE "/path/to/release/libexternal.so"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include/external"
)
# 使用导入库
add_executable(myapp main.cpp)
target_link_libraries(myapp PRIVATE external_lib external_shared)
高级特性
1. 条件编译库类型
cmake
# 根据选项决定构建静态库还是共享库
option(BUILD_SHARED_LIBS "构建共享库" ON)
if(BUILD_SHARED_LIBS)
add_library(mylib SHARED src/mylib.cpp)
else()
add_library(mylib STATIC src/mylib.cpp)
endif()
# 或者使用 CMake 内置变量
set(BUILD_SHARED_LIBS ON CACHE BOOL "构建共享库")
add_library(mylib src/mylib.cpp) # 类型由 BUILD_SHARED_LIBS 决定
2. 生成器表达式
cmake
# 根据配置添加不同的源文件
add_library(mylib
src/base.cpp
$<$<CONFIG:Debug>:src/debug_helpers.cpp>
$<$<CONFIG:Release>:src/optimizations.cpp>
$<$<BOOL:${ENABLE_FEATURE_X}>:src/feature_x.cpp>
)
# 平台特定的源文件
add_library(mylib
src/common.cpp
$<$<PLATFORM_ID:Windows>:src/win32_specific.cpp>
$<$<PLATFORM_ID:Linux>:src/linux_specific.cpp>
$<$<PLATFORM_ID:Darwin>:src/macos_specific.mm>
)
# 编译器特定的编译选项
target_compile_options(mylib PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-Wall>
$<$<CXX_COMPILER_ID:MSVC>:/W4>
)
3. 库的组合和聚合
cmake
# 创建多个子库
add_library(core STATIC src/core.cpp)
add_library(utils STATIC src/utils.cpp)
add_library(network STATIC src/network.cpp)
# 创建聚合库
add_library(full_lib INTERFACE)
target_link_libraries(full_lib INTERFACE core utils network)
# 或者创建实际的库包装
add_library(combined SHARED)
target_sources(combined PRIVATE
$<TARGET_OBJECTS:core>
$<TARGET_OBJECTS:utils>
$<TARGET_OBJECTS:network>
)
# 设置合并库的属性
set_target_properties(combined PROPERTIES
OUTPUT_NAME "combined"
VERSION 1.0.0
SOVERSION 1
)
4. 符号可见性控制
cmake
# 设置默认符号可见性
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
add_library(mylib SHARED src/mylib.cpp)
# 显式导出特定符号
target_compile_definitions(mylib PRIVATE
MYLIB_BUILDING_DLL
)
# 在头文件中使用:
# #ifdef MYLIB_BUILDING_DLL
# #define MYLIB_API __declspec(dllexport)
# #else
# #define MYLIB_API __declspec(dllimport)
# #endif
# 或者使用生成器表达式
target_compile_definitions(mylib PRIVATE
$<$<BOOL:${BUILD_SHARED_LIBS}>:MYLIB_BUILDING_DLL>
)
目标属性设置
常用库属性
cmake
add_library(mylib src/mylib.cpp)
# 输出文件相关
set_target_properties(mylib PROPERTIES
OUTPUT_NAME "mylib" # 基本名称
PREFIX "" # 前缀(默认为 "lib")
SUFFIX ".so" # 后缀
IMPORT_PREFIX "" # 导入库前缀
IMPORT_SUFFIX ".lib" # 导入库后缀
)
# 版本控制
set_target_properties(mylib PROPERTIES
VERSION ${PROJECT_VERSION} # 完整版本号
SOVERSION ${PROJECT_VERSION_MAJOR} # API 版本号
MACOSX_RPATH ON # macOS RPATH 处理
)
# 输出目录
set_target_properties(mylib PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" # Windows DLL
)
# 编译特性
set_target_properties(mylib PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON # 启用 PIC
)
平台特定属性
cmake
if(WIN32)
set_target_properties(mylib PROPERTIES
WINDOWS_EXPORT_ALL_SYMBOLS ON # 自动导出所有符号
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
)
# 添加模块定义文件
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/mylib.def)
target_sources(mylib PRIVATE mylib.def)
endif()
elseif(APPLE)
set_target_properties(mylib PROPERTIES
MACOSX_FRAMEWORK_IDENTIFIER "com.company.mylib"
MACOSX_FRAMEWORK_BUNDLE_VERSION ${PROJECT_VERSION}
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "Apple Development"
)
elseif(UNIX)
set_target_properties(mylib PROPERTIES
NO_SONAME FALSE # 是否生成 SONAME
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
)
endif()
完整项目示例
示例1:跨平台数学库
cmake
cmake_minimum_required(VERSION 3.15)
project(MathLibrary VERSION 2.1.0 LANGUAGES CXX)
# 选项配置
option(BUILD_SHARED_LIBS "构建共享库" ON)
option(BUILD_TESTING "构建测试" ON)
option(ENABLE_SIMD "启用 SIMD 优化" OFF)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 源文件分组
set(MATH_CORE_SOURCES
src/core/vector.cpp
src/core/matrix.cpp
src/core/quaternion.cpp
)
set(MATH_ALGEBRA_SOURCES
src/algebra/solver.cpp
src/algebra/eigen.cpp
src/algebra/lu_decomposition.cpp
)
set(MATH_GEOMETRY_SOURCES
src/geometry/shapes.cpp
src/geometry/intersection.cpp
src/geometry/transform.cpp
)
set(MATH_HEADERS
include/mathlib/core/vector.h
include/mathlib/core/matrix.h
include/mathlib/algebra/solver.h
include/mathlib/geometry/shapes.h
)
# SIMD 优化源文件(可选)
if(ENABLE_SIMD)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86|x86_64|AMD64")
list(APPEND MATH_CORE_SOURCES src/core/simd_x86.cpp)
target_compile_definitions(mathlib PRIVATE MATHLIB_USE_SIMD)
target_compile_options(mathlib PRIVATE -msse2 -mavx)
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm|aarch64")
list(APPEND MATH_CORE_SOURCES src/core/simd_arm.cpp)
target_compile_definitions(mathlib PRIVATE MATHLIB_USE_SIMD)
target_compile_options(mathlib PRIVATE -mfpu=neon)
endif()
endif()
# 创建主库
add_library(mathlib
${MATH_CORE_SOURCES}
${MATH_ALGEBRA_SOURCES}
${MATH_GEOMETRY_SOURCES}
${MATH_HEADERS}
)
# 设置库属性
set_target_properties(mathlib PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
OUTPUT_NAME "mathlib"
DEBUG_POSTFIX "_d"
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
# 包含目录
target_include_directories(mathlib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# 编译定义
target_compile_definitions(mathlib PUBLIC
MATHLIB_VERSION=${PROJECT_VERSION}
$<$<CONFIG:Debug>:MATHLIB_DEBUG=1>
)
# 依赖项
find_package(Eigen3 3.3 REQUIRED)
target_link_libraries(mathlib PUBLIC Eigen3::Eigen)
if(UNIX)
target_link_libraries(mathlib PUBLIC m) # 数学库
endif()
# 创建接口库用于头文件
add_library(mathlib_headers INTERFACE)
target_include_directories(mathlib_headers INTERFACE include)
# 安装配置
include(GNUInstallDirs)
install(TARGETS mathlib mathlib_headers
EXPORT MathLibraryTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mathlib
)
# 测试(可选)
if(BUILD_TESTING)
enable_testing()
add_subdirectory(tests)
endif()
示例2:插件系统
cmake
cmake_minimum_required(VERSION 3.16)
project(PluginSystem VERSION 1.0.0)
# 主应用程序
add_executable(plugin_host
src/host/main.cpp
src/host/plugin_manager.cpp
)
# 插件接口(头文件库)
add_library(plugin_api INTERFACE)
target_include_directories(plugin_api INTERFACE include)
target_compile_definitions(plugin_api INTERFACE PLUGIN_API_VERSION=2)
# 为插件接口设置导出宏
if(WIN32)
target_compile_definitions(plugin_api INTERFACE
PLUGIN_EXPORT=__declspec(dllexport)
PLUGIN_IMPORT=__declspec(dllimport)
)
else()
target_compile_definitions(plugin_api INTERFACE
PLUGIN_EXPORT=__attribute__((visibility("default")))
PLUGIN_IMPORT=
)
endif()
# 示例插件1:图像过滤器
add_library(filter_plugin MODULE
plugins/filter/src/filter_plugin.cpp
plugins/filter/src/blur_filter.cpp
plugins/filter/include/filter_plugin.h
)
target_link_libraries(filter_plugin PRIVATE plugin_api)
set_target_properties(filter_plugin PROPERTIES
PREFIX ""
SUFFIX ".plugin"
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins # Windows
)
# 示例插件2:效果插件
add_library(effect_plugin MODULE
plugins/effect/src/effect_plugin.cpp
plugins/effect/src/glow_effect.cpp
plugins/effect/include/effect_plugin.h
)
target_link_libraries(effect_plugin PRIVATE plugin_api)
set_target_properties(effect_plugin PROPERTIES
PREFIX ""
SUFFIX ".plugin"
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/plugins
)
# 设置插件符号可见性
if(NOT WIN32)
target_compile_options(filter_plugin PRIVATE -fvisibility=hidden)
target_compile_options(effect_plugin PRIVATE -fvisibility=hidden)
endif()
# 安装插件
install(TARGETS filter_plugin effect_plugin
LIBRARY DESTINATION lib/plugins
RUNTIME DESTINATION bin/plugins # Windows DLL
)
# 插件加载器库
add_library(plugin_loader SHARED
src/loader/plugin_loader.cpp
src/loader/plugin_registry.cpp
)
target_link_libraries(plugin_loader PRIVATE plugin_api)
target_link_libraries(plugin_host PRIVATE plugin_loader)
示例3:对象库的高级用法
cmake
cmake_minimum_required(VERSION 3.18)
project(ObjectLibraryDemo VERSION 1.0.0)
# 公共对象库(包含通用功能)
add_library(common_objects OBJECT
src/common/logging.cpp
src/common/config.cpp
src/common/utils.cpp
)
target_include_directories(common_objects PUBLIC include/common)
target_compile_definitions(common_objects PUBLIC COMMON_BUILD)
# 网络对象库
add_library(network_objects OBJECT
src/network/tcp_client.cpp
src/network/tcp_server.cpp
src/network/udp_socket.cpp
)
target_include_directories(network_objects PUBLIC include/network)
target_compile_definitions(network_objects PUBLIC NETWORK_BUILD)
target_link_libraries(network_objects PUBLIC common_objects)
# 数据库对象库
add_library(database_objects OBJECT
src/database/connection.cpp
src/database/query.cpp
src/database/transaction.cpp
)
target_include_directories(database_objects PUBLIC include/database)
target_compile_definitions(database_objects PUBLIC DATABASE_BUILD)
target_link_libraries(database_objects PUBLIC common_objects)
# 应用程序1:网络服务
add_executable(network_service
src/apps/network_service.cpp
$<TARGET_OBJECTS:common_objects>
$<TARGET_OBJECTS:network_objects>
)
target_compile_definitions(network_service PRIVATE SERVICE_NETWORK)
# 应用程序2:数据库工具
add_executable(database_tool
src/apps/database_tool.cpp
$<TARGET_OBJECTS:common_objects>
$<TARGET_OBJECTS:database_objects>
)
target_compile_definitions(database_tool PRIVATE TOOL_DATABASE)
# 应用程序3:完整应用(使用所有对象库)
add_executable(full_app
src/apps/full_app.cpp
$<TARGET_OBJECTS:common_objects>
$<TARGET_OBJECTS:network_objects>
$<TARGET_OBJECTS:database_objects>
)
# 创建静态库版本(重用对象)
add_library(full_static STATIC
$<TARGET_OBJECTS:common_objects>
$<TARGET_OBJECTS:network_objects>
$<TARGET_OBJECTS:database_objects>
)
set_target_properties(full_static PROPERTIES
OUTPUT_NAME "applib"
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)
最佳实践
1. 命名规范
cmake
# 使用清晰的前缀
add_library(company_core STATIC ...) # 公司核心库
add_library(project_utils SHARED ...) # 项目工具库
add_library(external_boost IMPORTED ...) # 外部库
# 避免通用名称
# 不好:add_library(utils ...)
# 好:add_library(myproject_utils ...)
2. 头文件管理
cmake
# 方法1:将头文件添加到源文件列表(IDE友好)
add_library(mylib
src/mylib.cpp
include/mylib/public.h
src/mylib/private.h
)
# 方法2:使用 PUBLIC_HEADER 属性
add_library(mylib src/mylib.cpp)
set_target_properties(mylib PROPERTIES
PUBLIC_HEADER "include/mylib/public.h"
)
# 方法3:接口库包装头文件
add_library(mylib_headers INTERFACE)
target_include_directories(mylib_headers INTERFACE include)
add_library(mylib src/mylib.cpp)
target_link_libraries(mylib PUBLIC mylib_headers)
3. 版本控制策略
cmake
# 语义化版本控制
set(PROJECT_VERSION_MAJOR 2)
set(PROJECT_VERSION_MINOR 1)
set(PROJECT_VERSION_PATCH 3)
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
add_library(mylib SHARED ...)
set_target_properties(mylib PROPERTIES
VERSION ${PROJECT_VERSION} # 完整版本号
SOVERSION ${PROJECT_VERSION_MAJOR} # API 版本(ABI 兼容)
)
# 生成版本头文件
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/include/mylib/version.h.in
${CMAKE_CURRENT_BINARY_DIR}/include/mylib/version.h
)
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/include>
)
4. 跨平台兼容性
cmake
add_library(mylib SHARED ...)
# Windows 特定设置
if(WIN32)
# 自动导出所有符号(简化方式)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# 或者使用模块定义文件
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/mylib.def)
target_sources(mylib PRIVATE mylib.def)
endif()
# 运行时库设置
if(MSVC)
set_target_properties(mylib PROPERTIES
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL"
)
endif()
endif()
# Unix 系统设置
if(UNIX AND NOT APPLE)
# RPATH 处理
set_target_properties(mylib PROPERTIES
BUILD_WITH_INSTALL_RPATH TRUE
INSTALL_RPATH "$ORIGIN/../lib"
)
endif()
# macOS 设置
if(APPLE)
set_target_properties(mylib PROPERTIES
MACOSX_RPATH ON
INSTALL_NAME_DIR "@rpath"
)
endif()
常见问题和解决方案
问题1:符号冲突
cmake
# 不同库中的同名函数冲突
# 解决方案1:使用命名空间
add_library(lib1 STATIC src1.cpp)
target_compile_definitions(lib1 PRIVATE LIB1_NAMESPACE=lib1)
add_library(lib2 STATIC src2.cpp)
target_compile_definitions(lib2 PRIVATE LIB2_NAMESPACE=lib2)
# 解决方案2:隐藏符号(共享库)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
add_library(mylib SHARED ...)
# 显式导出需要的符号
target_compile_definitions(mylib PRIVATE MYLIB_EXPORTS)
# 在头文件中:#ifdef MYLIB_EXPORTS
# #define API __declspec(dllexport)
# #else
# #define API __declspec(dllimport)
# #endif
问题2:循环依赖
cmake
# 库A依赖库B,库B又依赖库A
# 解决方案:提取公共接口
add_library(common INTERFACE)
target_compile_features(common INTERFACE cxx_std_17)
target_include_directories(common INTERFACE include)
add_library(libA STATIC libA.cpp)
target_link_libraries(libA PUBLIC common)
add_library(libB STATIC libB.cpp)
target_link_libraries(libB PUBLIC common libA) # 单向依赖
# 或者使用对象库
add_library(common_objects OBJECT common1.cpp common2.cpp)
add_library(libA STATIC libA.cpp $<TARGET_OBJECTS:common_objects>)
add_library(libB STATIC libB.cpp $<TARGET_OBJECTS:common_objects>)
问题3:安装后找不到库
cmake
# 安装时设置正确的 RPATH
include(GNUInstallDirs)
install(TARGETS mylib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} # Windows DLL
)
# 设置安装 RPATH
if(UNIX AND NOT APPLE)
set_target_properties(mylib PROPERTIES
INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}"
BUILD_WITH_INSTALL_RPATH TRUE
)
endif()
# 创建导入目标供 find_package 使用
install(EXPORT mylib-targets
FILE MyLibConfig.cmake
NAMESPACE MyLib::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyLib
)
调试技巧
检查库属性
cmake
add_library(mylib STATIC src.cpp)
# 查看所有属性
get_target_property(props mylib PROPERTIES)
foreach(prop ${props})
get_target_property(value mylib ${prop})
if(value)
message(STATUS "${prop} = ${value}")
endif()
endforeach()
# 查看源文件
get_target_property(sources mylib SOURCES)
message(STATUS "源文件: ${sources}")
# 查看链接库
get_target_property(link_libs mylib LINK_LIBRARIES)
message(STATUS "链接库: ${link_libs}")
验证库类型
cmake
function(validate_library target expected_type)
if(NOT TARGET ${target})
message(FATAL_ERROR "目标 ${target} 不存在")
endif()
get_target_property(actual_type ${target} TYPE)
if(NOT actual_type STREQUAL expected_type)
if(expected_type STREQUAL "STATIC_LIBRARY")
set(expected_str "静态库")
elseif(expected_type STREQUAL "SHARED_LIBRARY")
set(expected_str "共享库")
elseif(expected_type STREQUAL "MODULE_LIBRARY")
set(expected_str "模块库")
else()
set(expected_str ${expected_type})
endif()
message(WARNING "${target} 不是 ${expected_str}")
endif()
endfunction()
# 使用示例
add_library(mystatic STATIC ...)
validate_library(mystatic "STATIC_LIBRARY")
add_library(myshared SHARED ...)
validate_library(myshared "SHARED_LIBRARY")
add_library() 是 CMake 构建系统的核心,合理使用可以创建高效、可维护的库组件,支持复杂的项目结构和跨平台部署需求。掌握不同类型的库及其特性,对于构建专业级软件项目至关重要。