FigmaCN完整指南:3分钟免费解锁中文版Figma的终极方案
2026/6/26 13:42:43
在 CMake 构建系统中,add_executable和target_sources是两个用于管理源文件的重要命令。理解它们的关系、区别和使用场景,对于编写高质量的 CMake 配置文件至关重要。本文将深入探讨这两个命令的用法、关系和最佳实践。
add_executable(目标名 [源文件1] [源文件2] ...)add_executable用于创建一个可执行文件目标,这是构建可执行程序的第一步。它可以:
# 方式1:创建目标并指定所有源文件 add_executable(myapp main.cpp utils.cpp helper.cpp ) # 方式2:只创建目标,稍后添加源文件 add_executable(myapp main.cpp)add_executable对应一个可执行文件target_sources添加target_sources(目标名 PRIVATE|PUBLIC|INTERFACE [源文件...])target_sources用于向已存在的目标添加源文件。它可以:
PRIVATE、PUBLIC、INTERFACE控制源文件的可见性# 先创建目标 add_executable(myapp main.cpp) # 然后添加更多源文件 target_sources(myapp PRIVATE utils.cpp helper.cpp utils.h # 可选:用于IDE显示和依赖跟踪 )add_executable或add_library创建目标add_executable (创建目标) → target_sources (添加源文件) ↓ ↓ 必须首先调用 目标必须已存在| 特性 | add_executable | target_sources |
|---|---|---|
| 功能 | 创建可执行文件目标 | 向目标添加源文件 |
| 调用时机 | 必须先调用 | 必须在目标创建后调用 |
| 能否创建目标 | ✅ 能 | ❌ 不能 |
| 能否添加源文件 | ✅ 能 | ✅ 能 |
| 调用次数 | 每个可执行文件一次 | 可以多次调用 |
| 可见性控制 | ❌ 不支持 | ✅ 支持(PRIVATE/PUBLIC/INTERFACE) |
add_executable(适合简单项目)# 一次性创建目标并指定所有源文件 add_executable(multifile main.cpp math_utils.cpp )优点:
缺点:
add_executable+target_sources(适合复杂项目)# 先创建目标 add_executable(multifile main.cpp) # 然后添加更多源文件 target_sources(multifile PRIVATE math_utils.cpp math_utils.h )优点:
缺点:
target_sources支持三个可见性关键字,用于控制源文件的传递性:
含义:源文件只用于构建当前目标,不会传递给依赖它的其他目标。
使用场景:
.cpp)示例:
add_executable(myapp main.cpp) target_sources(myapp PRIVATE math_utils.cpp # 实现文件 math_utils.h # 头文件(仅内部使用) )含义:源文件用于构建当前目标,并且会传递给依赖它的其他目标。
使用场景:
示例:
add_library(mylib STATIC math_lib.cpp) # PRIVATE:实现文件,不对外暴露 target_sources(mylib PRIVATE math_lib.cpp # 实现文件 ) # PUBLIC:公共头文件,使用者需要它 target_sources(mylib PUBLIC math_lib.h # 公共头文件,会传递给使用者 )含义:源文件不用于构建当前目标,但会传递给依赖它的其他目标。
使用场景:
示例:
# 创建接口库(只有头文件,没有实现) add_library(header_only_lib INTERFACE) target_sources(header_only_lib INTERFACE header_only.h # 头文件,不编译,但使用者可以访问 )| 关键字 | 用于构建当前目标 | 传递给依赖者 | 典型用途 |
|---|---|---|---|
| PRIVATE | ✅ 是 | ❌ 否 | 实现文件、内部头文件 |
| PUBLIC | ✅ 是 | ✅ 是 | 库的公共头文件 |
| INTERFACE | ❌ 否 | ✅ 是 | 接口库的头文件 |
假设有:库A→可执行文件B
# 库A add_library(A STATIC) target_sources(A PRIVATE file1.cpp # B 看不到 ) target_sources(A PUBLIC file2.h # B 可以看到 ) target_sources(A INTERFACE file3.h # B 可以看到(但A不编译它) ) # 可执行文件B add_executable(B main.cpp) target_link_libraries(B A)结果:
file2.h(PUBLIC)file3.h(INTERFACE)file1.cpp(PRIVATE)add_executable)cmake_minimum_required(VERSION 3.10) project(SimpleApp LANGUAGES CXX) # 所有源文件已知,一次性指定 add_executable(myapp main.cpp utils.cpp helper.cpp )适用情况:
target_sources)cmake_minimum_required(VERSION 3.10) project(ConditionalApp LANGUAGES CXX) # 先创建目标 add_executable(myapp main.cpp) # 根据平台添加不同的源文件 if(WIN32) target_sources(myapp PRIVATE windows_utils.cpp win_specific.cpp ) else() target_sources(myapp PRIVATE unix_utils.cpp unix_specific.cpp ) endif()适用情况:
cmake_minimum_required(VERSION 3.10) project(MyLibrary LANGUAGES CXX) # 创建静态库 add_library(mylib STATIC) # PRIVATE:实现文件,不对外暴露 target_sources(mylib PRIVATE math_lib.cpp # 实现文件 internal_helper.cpp # 内部辅助函数 internal_helper.h # 内部头文件 ) # PUBLIC:公共头文件,使用者需要它 target_sources(mylib PUBLIC math_lib.h # 公共头文件,会传递给使用者 ) # 创建可执行文件并链接库 add_executable(myapp main.cpp) target_link_libraries(myapp mylib)适用情况:
cmake_minimum_required(VERSION 3.10) project(IDEExample LANGUAGES CXX) # 创建目标 add_executable(myapp main.cpp) # 添加源文件 target_sources(myapp PRIVATE math_utils.cpp math_utils.h # 添加头文件,用于IDE显示和依赖跟踪 )适用情况:
让我们看一个完整的示例,演示两种方式的使用:
02-多文件示例/ ├── CMakeLists.txt ├── main.cpp ├── math_utils.h └── math_utils.cppadd_executable(当前方式)cmake_minimum_required(VERSION 3.10) project(MultiFile LANGUAGES CXX) # 添加所有源文件 add_executable(multifile main.cpp math_utils.cpp )add_executable+target_sourcescmake_minimum_required(VERSION 3.10) project(MultiFile LANGUAGES CXX) # 先创建目标 add_executable(multifile main.cpp) # 然后添加更多源文件 target_sources(multifile PRIVATE math_utils.cpp # 实现文件 math_utils.h # 头文件(可选,用于IDE显示) )两种方式效果相同,选择哪种取决于项目需求和个人偏好。
add_executable✅推荐使用:
target_sources✅推荐使用:
PRIVATEPRIVATEPUBLICINTERFACE技术角度:
.h)不需要在 CMake 中显式列出#include处理头文件实践角度:
PUBLIC列出# 推荐:清晰的注释和分组 cmake_minimum_required(VERSION 3.10) project(MyProject LANGUAGES CXX) # ========== 创建可执行文件 ========== add_executable(myapp main.cpp) # ========== 添加源文件 ========== target_sources(myapp PRIVATE utils.cpp helper.cpp utils.h helper.h )A: 技术上不需要,编译器会自动处理#include。但可以添加用于:
A: 技术上可以,但通常没有必要。因为可执行文件不会被其他目标依赖,所以PRIVATE就足够了。
add_executable和target_sources可以混用吗?A: 可以!可以先在add_executable中指定一些源文件,然后用target_sources添加更多。
add_executable(myapp main.cpp utils.cpp) target_sources(myapp PRIVATE helper.cpp)target_sources?A: 以下情况必须使用:
add_executable:创建可执行文件目标,可以同时指定源文件target_sources:向已存在的目标添加源文件,支持可见性控制add_executable创建目标,target_sources添加源文件PRIVATE(私有)、PUBLIC(公共)、INTERFACE(接口)add_executable一次性指定所有源文件add_executable+target_sources,更灵活target_sources区分公共接口和内部实现add_executable= 创建目标target_sources= 添加文件PRIVATE= 私有,自己用PUBLIC= 公共,大家用INTERFACE= 接口,给别人用