CMake 库目标
本章将介绍如何使用 CMake 创建和管理库目标,包括静态库、动态库和接口库。
库的类型
| 类型 | 关键字 | 特点 |
|---|---|---|
| 静态库 | STATIC | 编译时链接,体积大,性能好 |
| 动态库 | SHARED | 运行时加载,体积小,更新方便 |
| 模块库 | MODULE | 运行时动态加载(插件) |
| 对象库 | OBJECT | 编译但归档,供其他目标使用 |
| 接口库 | INTERFACE | 仅头文件,无编译输出 |
创建静态库
add_library(mylib STATIC
src/lib.cpp
src/helper.cpp
)
target_include_directories(mylib
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
创建动态库
add_library(mylib SHARED
src/lib.cpp
src/helper.cpp
)
# 设置导出符号
target_compile_definitions(mylib PRIVATE MYLIB_EXPORTS)
符号导出
mylib_export.h:
#ifdef MYLIB_EXPORTS
#define MYLIB_API __attribute__((visibility("default")))
#else
#define MYLIB_API
#endif
MYLIB_API void my_function();
Windows DLL 导出
#ifdef _WIN32
#ifdef MYLIB_EXPORTS
#define MYLIB_API __declspec(dllexport)
#else
#define MYLIB_API __declspec(dllimport)
#endif
#else
#define MYLIB_API
#endif
创建接口库
接口库用于纯头文件库:
add_library(mylib INTERFACE)
target_include_directories(mylib INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
# 设置编译特性
target_compile_features(mylib INTERFACE cxx_std_17)
使用库
链接库到可执行文件
add_library(mylib STATIC src/lib.cpp)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)
链接可见性
target_link_libraries(target
PRIVATE lib_internal # 仅当前目标使用
PUBLIC lib_public # 当前目标和依赖者都可使用
INTERFACE lib_interface # 仅依赖者可使用
)
示例:
# 库 A 依赖库 B
add_library(B ...)
add_library(A ...)
# 如果 B 的头文件出现在 A 的公共头文件中
target_link_libraries(A PUBLIC B)
# 如果 B 仅在 A 的实现中使用
target_link_libraries(A PRIVATE B)
对象库
对象库编译源文件但不创建库文件:
add_library(common_obj OBJECT
src/common.cpp
src/utils.cpp
)
# 静态库使用对象库
add_library(mylib STATIC $<TARGET_OBJECTS:common_obj>)
# 动态库使用同一对象库
add_library(mylib_shared SHARED $<TARGET_OBJECTS:common_obj>)
库的安装
导出配置
add_library(mylib src/lib.cpp)
# 安装库和头文件
install(TARGETS mylib
EXPORT mylibTargets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
install(DIRECTORY include/
DESTINATION include
)
# 导出目标
install(EXPORT mylibTargets
FILE mylibTargets.cmake
NAMESPACE mylib::
DESTINATION lib/cmake/mylib
)
版本控制
set_target_properties(mylib PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1 # API 版本
)
这将生成:
libmylib.so.1.0.0(实际文件)libmylib.so.1->libmylib.so.1.0.0libmylib.so->libmylib.so.1
小结
本章我们学习了:
- 库的类型:静态、动态、接口、对象库
- 创建库:add_library 命令
- 符号导出:跨平台 DLL/SO 导出
- 链接可见性:PUBLIC、PRIVATE、INTERFACE
- 库安装:导出配置和版本控制
练习
- 创建一个静态库并链接到可执行文件
- 实现跨平台的动态库导出
- 创建一个纯头文件库