CMake项目与目标指令

CMake项目与目标指令

命令 说明
project 定义项目名称、版本、支持语言
add_executable 创建可执行文件目标
add_library 创建库目标(静态/动态/接口)
enable_language 启用额外的编程语言(如 CUDA)

1、project

https://cmake.org/cmake/help/latest/command/project.html

bash 复制代码
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

bash 复制代码
add_executable(<name> <options>... <sources>...)

2.1、单个源文件

bash 复制代码
add_executable(hello-world main.cpp)

2.2、多个源文件

bash 复制代码
add_executable(hello-world main.cpp utils.cpp hello.cpp)

2.3、源文件变量

bash 复制代码
set(SOURCES main.cpp utils.cpp hello.cpp) 
add_executable(hello-world ${SOURCES})

2.4、普通可执行文件

2.4.1、WIN32 - 创建 Windows GUI 应用
bash 复制代码
add_executable(hello-world WIN32 main.cpp)
  • 在 Windows 上生成 GUI 程序(不显示控制台窗口)
  • 内部调用 WinMain 而不是 main
  • 其他平台上此选项无效
2.4.2、MACOSX_BUNDLE - 创建 macOS 应用包
bash 复制代码
add_executable(hello-world MACOSX_BUNDLE main.cpp)
  • 生成 .app 包结构
  • 常配合 Info.plist 使用
2.4.3、EXCLUDE_FROM_ALL - 排除默认构建
bash 复制代码
add_executable(hello-world EXCLUDE_FROM_ALL main.cpp)
  • 该目标不会被默认的 all target 构建
  • 需要显式指定 cmake --build . --target myapp 才会构建

2.5、导入可执行文件

用于引用外部已存在的可执行文件(不需要编译):

bash 复制代码
# 声明一个从外部构建系统导入的可执行文件  
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、别名可执行文件

bash 复制代码
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

bash 复制代码
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 静态库

bash 复制代码
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 动态库

bash 复制代码
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 模块库

bash 复制代码
add_library(myPlugin MODULE
    src/plugin.cpp
)
对比项 SHARED MODULE
能否被其他target target_link_libraries 直接链接 ✅ 可以 ❌ 通常不建议(部分平台不支持)
典型用法 常规动态库 运行时 dlopen/LoadLibrary 加载的插件

3.4、OBJECT 对象库

bash 复制代码
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 接口库

bash 复制代码
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静态库导入

bash 复制代码
# 静态库导入
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动态库导入

bash 复制代码
# 动态库导入(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 别名库

bash 复制代码
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 均可创建别名
相关推荐
沙盘客1 天前
AFSIM 官方案例库全景与解读方法论
c++·经验分享·后端
_wxd6661 天前
STL-stack与queue与priority_queue(容器适配器)
c++
zh路西法1 天前
【玩转VLA具身智能机械臂】(二):MoveIt2 运动规划——架构、配置与 C++ 上手
c++·机械臂·路径规划·vla·planner·moveit2
Yfhonier1 天前
【素数定理】素数个数的位数
c++·算法·素数
爱和冰阔落1 天前
【Linux】Ctrl+C 到底做了什么?从键盘、kill 到 alarm,一次讲清信号的产生
linux·运维·c++·安卓
水饺编程1 天前
第5章,[Win32 章节] :贝塞尔样条曲线(一)
c语言·c++·windows·visual studio
程序员打怪兽1 天前
C++:类与对象,封装,继承,多态,构造/析构,重载/重写
c++
AC赳赳老秦1 天前
多源数据关联挖掘:OpenClaw 打通工商、招投标、专利公开数据,挖掘企业业务关联关系
java·c语言·javascript·c++·python·deepseek·openclaw
Escalating_xu1 天前
【C++ STL简介】从六大组件到容器、迭代器与算法协作
java·c++·算法
Brilliantwxx1 天前
【Linux】 进程(3)深度解析:从查看进程到进程状态
linux·服务器·网络·c++