CMake项目与目标指令
-
- 1、project
- 2、add_executable
-
- 3、add_library
-
- [3.1、STATIC 静态库](#3.1、STATIC 静态库)
- [3.2、SHARED 动态库](#3.2、SHARED 动态库)
- [3.3、MODULE 模块库](#3.3、MODULE 模块库)
- [3.4、OBJECT 对象库](#3.4、OBJECT 对象库)
- [3.5、INTERFACE 接口库](#3.5、INTERFACE 接口库)
- [3.6 STATIC IMPORTED静态库导入](#3.6 STATIC IMPORTED静态库导入)
- [3.7、SHARED IMPORTED动态库导入](#3.7、SHARED IMPORTED动态库导入)
- [3.8、ALIAS 别名库](#3.8、ALIAS 别名库)
| 命令 |
说明 |
project |
定义项目名称、版本、支持语言 |
add_executable |
创建可执行文件目标 |
add_library |
创建库目标(静态/动态/接口) |
enable_language |
启用额外的编程语言(如 CUDA) |
1、project
https://cmake.org/cmake/help/latest/command/project.html
project(<PROJECT-NAME> [<language-name>...])
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[COMPAT_VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[SPDX_LICENSE <license-string>]
[DESCRIPTION <description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
2、add_executable
https://cmake.org/cmake/help/latest/command/add_executable.html
add_executable(<name> <options>... <sources>...)
2.1、单个源文件
add_executable(hello-world main.cpp)
2.2、多个源文件
add_executable(hello-world main.cpp utils.cpp hello.cpp)
2.3、源文件变量
set(SOURCES main.cpp utils.cpp hello.cpp)
add_executable(hello-world ${SOURCES})
2.4、普通可执行文件
2.4.1、WIN32 - 创建 Windows GUI 应用
add_executable(hello-world WIN32 main.cpp)
- 在 Windows 上生成 GUI 程序(不显示控制台窗口)
- 内部调用
WinMain 而不是 main
- 其他平台上此选项无效
2.4.2、MACOSX_BUNDLE - 创建 macOS 应用包
add_executable(hello-world MACOSX_BUNDLE main.cpp)
- 生成
.app 包结构
- 常配合
Info.plist 使用
2.4.3、EXCLUDE_FROM_ALL - 排除默认构建
add_executable(hello-world EXCLUDE_FROM_ALL main.cpp)
- 该目标不会被默认的
all target 构建
- 需要显式指定
cmake --build . --target myapp 才会构建
2.5、导入可执行文件
用于引用外部已存在的可执行文件(不需要编译):
# 声明一个从外部构建系统导入的可执行文件
add_executable(helloIMPORTED IMPORTED)
# 设置导入的可执行文件的路径
set_target_properties(helloIMPORTED PROPERTIES
IMPORTED_LOCATION "/usr/bin/external/hello"
)
# 添加自定义命令来运行它
add_custom_target(my_hello
COMMAND $<TARGET_FILE:helloIMPORTED>
DEPENDS helloIMPORTED
)
2.6、别名可执行文件
add_executable(myapp main.cpp)
add_executable(MyProject::myapp ALIAS myapp)
- 常用于统一命名空间(尤其是子项目/包管理场景)
- Alias 目标是只读的,不能设置属性
3、add_library
https://cmake.org/cmake/help/latest/command/add_library.html
add_library(<name> [STATIC | SHARED | MODULE | OBJECT | INTERFACE] [EXCLUDE_FROM_ALL] [source1] [source2] ...)
| 类型 |
说明 |
文件后缀(Linux/Win) |
使用场景 |
STATIC |
静态库,编译时链接到目标程序中 |
.a / .lib |
不想暴露源码、避免运行时依赖 |
SHARED |
动态库,运行时加载 |
.so / .dll |
减小可执行文件体积、支持插件化 |
MODULE |
类似SHARED,但不参与链接,仅供 dlopen 等运行时加载 |
.so / .dll |
插件系统 |
OBJECT |
一组目标文件的集合,不打包成库文件 |
.o / .obj |
需要将中间对象文件复用到多个目标 |
INTERFACE |
不产生实际二进制文件,仅传递属性(头文件路径、编译选项等) |
无 |
Header-only 库、纯接口传递 |
3.1、STATIC 静态库
add_library(myLib STATIC
src/main.cpp
src/utils.cpp
)
target_include_directories(myLib PUBLIC include)
target_link_libraries(myLib PRIVATE pthread)
| 特点 |
说明 |
| 链接方式 |
编译时静态链接进最终二进制 |
| 优点 |
部署简单,无外部依赖 |
| 缺点 |
体积大,多个程序无法共享内存中的库代码 |
| 默认值 |
若未指定类型且 BUILD_SHARED_LIBS=OFF,默认为STATIC |
3.2、SHARED 动态库
add_library(myLib SHARED
src/main.cpp
src/utils.cpp
)
set_target_properties(myLib PROPERTIES
VERSION 1.2.0
SOVERSION 1
)
# Windows下简化符号导出
# set_target_properties(myLib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
| 属性 |
作用 |
VERSION |
设置库的完整版本号,生成 libmylib.so.1.2.0 |
SOVERSION |
设置API版本号,生成软链接 libmylib.so.1 |
WINDOWS_EXPORT_ALL_SYMBOLS |
Windows下自动导出所有符号(避免手写 __declspec(dllexport)) |
3.3、MODULE 模块库
add_library(myPlugin MODULE
src/plugin.cpp
)
| 对比项 |
SHARED |
MODULE |
能否被其他target target_link_libraries 直接链接 |
✅ 可以 |
❌ 通常不建议(部分平台不支持) |
| 典型用法 |
常规动态库 |
运行时 dlopen/LoadLibrary 加载的插件 |
3.4、OBJECT 对象库
add_library(myObjs OBJECT
src/a.cpp
src/b.cpp
)
# 在其他目标中复用这些对象文件
add_executable(app1 main1.cpp $<TARGET_OBJECTS:myObjs>)
add_executable(app2 main2.cpp $<TARGET_OBJECTS:myObjs>)
| 特点 |
说明 |
不生成 .a/.so |
只生成 .o 目标文件 |
| 引用方式 |
必须用 $<TARGET_OBJECTS:name> 生成器表达式 |
| 典型场景 |
多个可执行文件/库共享编译产物,避免重复编译 |
3.5、INTERFACE 接口库
add_library(myHeader_only INTERFACE)
target_include_directories(myHeader_only INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_compile_definitions(myHeader_only INTERFACE
USE_HEADER_ONLY_LIB=1
)
# 使用方
target_link_libraries(myapp PRIVATE myHeader_only)
| 特点 |
说明 |
| 无编译产物 |
不生成任何二进制文件 |
| 用途 |
Header-only库、编译选项/定义的集合传递 |
| 属性传递关键字 |
必须用 INTERFACE 而非 PUBLIC/PRIVATE |
3.6 STATIC IMPORTED静态库导入
# 静态库导入
add_library(external_static STATIC IMPORTED)
set_target_properties(external_static PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/libfoo.a"
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/libs/include"
)
target_link_libraries(myapp PRIVATE external_static)
| 关键属性 |
Linux/macOS |
Windows |
IMPORTED_LOCATION |
.so/.a 文件路径 |
.dll 文件路径(运行时) |
IMPORTED_IMPLIB |
不需要 |
.lib 文件路径(链接时需要) |
INTERFACE_INCLUDE_DIRECTORIES |
头文件目录 |
头文件目录 |
3.7、SHARED IMPORTED动态库导入
# 动态库导入(Windows 需要区分 .lib 和 .dll)
add_library(external_shared SHARED IMPORTED)
set_target_properties(external_shared PROPERTIES
IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/libs/foo.dll" # 运行时文件
IMPORTED_IMPLIB "${CMAKE_SOURCE_DIR}/libs/foo.lib" # 链接时文件(仅Windows需要)
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_SOURCE_DIR}/libs/include"
)
target_link_libraries(myapp PRIVATE external_shared)
3.8、ALIAS 别名库
add_library(mylib STATIC src/main.cpp)
add_library(MyProject::mylib ALIAS mylib)
# 使用别名(常用于统一命名空间风格)
target_link_libraries(myapp PRIVATE MyProject::mylib)
| 特点 |
说明 |
| 只读 |
不能对ALIAS目标设置属性 |
| 用途 |
统一子项目/第三方库的引用风格(Namespace::target) |
| 支持类型 |
STATIC/SHARED/MODULE/INTERFACE/OBJECT 均可创建别名 |