add_executable用于注册可执行目标,基本写法为add_executable(myapp main.cpp),其中myapp是全局唯一目标名,main.cpp为源文件路径;它不编译而仅生成构建规则,源文件须显式列出且仅支持.c/.cpp等可编译扩展名。

add_executable 生成可执行文件的基本写法
add_executable 的作用就是告诉 CMake:“这里要编一个可执行程序”,它本身不编译,只注册目标。最简形式是 add_executable(myapp main.cpp),其中 myapp 是最终生成的可执行文件名(Windows 下自动加 .exe),main.cpp 是源文件路径(相对 CMakeLists.txt 所在目录)。
常见错误是把头文件、资源文件或未声明的变量直接塞进参数列表——add_executable 只接受源文件(.c、.cpp、.cc、.cxx 等),头文件不会被编译,也不会触发依赖检查;若漏掉某个 .cpp,链接时大概率报 undefined reference。
- 源文件路径必须存在,CMake 不会自动递归查找,
add_executable(app *.cpp)在大多数 shell 下无效(glob 展开发生在 shell 层,而 CMake 不调用 shell 解析该行) - 可执行目标名不能和已存在的库名、变量名冲突,否则后续
target_link_libraries可能静默失败 - 同一
CMakeLists.txt中多次调用add_executable没问题,但目标名必须唯一
带条件或变体的 add_executable 写法
实际项目常需区分构建类型或平台,比如 Windows 下加 WIN32 标志让 GUI 程序不弹黑窗,或者用 EXCLUDE_FROM_ALL 把测试程序默认排除出 make all:
add_executable(mytool main.cpp) set_target_properties(mytool PROPERTIES EXCLUDE_FROM_ALL ON) if(WIN32) add_executable(gui_app WIN32 main.cpp) endif()
WIN32 和 MACOSX_BUNDLE 是仅影响可执行文件属性的修饰符,不改变编译逻辑;EXCLUDE_FROM_ALL 则直接影响构建行为——它不会阻止你手动 make gui_app,但会跳过 make 或 cmake --build . 默认目标。
-
add_executable(target_name WIN32 ...)必须放在源文件列表最前面,顺序错会导致 CMake 报错 “unknown argument WIN32” -
MACOSX_BUNDLE仅对 macOS 有效,且要求源码中包含 Info.plist 或由 CMake 自动生成,否则链接可能失败 - 想按配置生成不同名字的可执行文件(如
app_debug/app_release),不能靠if(CMAKE_BUILD_TYPE STREQUAL "Debug")动态改名——目标名必须在 configure 阶段确定,应改用add_executable+set_target_properties(... OUTPUT_NAME ...)
add_executable 和 target_sources 的配合使用
大型项目源文件多,硬编码在 add_executable 里难维护,推荐先定义变量再传入,或用 target_sources 增量添加:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
add_executable(myapp main.cpp) target_sources(myapp PRIVATE util.cpp helper.cpp)
这样做的好处是:源文件可分批组织,支持条件添加(比如 if(ENABLE_FEATURE_X) target_sources(myapp PRIVATE feature_x.cpp) endif()),也方便复用已有变量。注意 target_sources 的作用域关键字:PRIVATE 表示只影响本目标,PUBLIC 或 INTERFACE 会向依赖它的目标传递头文件路径或定义,一般可执行文件用 PRIVATE 就够了。
-
target_sources必须在add_executable之后调用,否则 CMake 报 “target ‘xxx’ does not exist” - 重复添加同一源文件不会报错,但可能导致编译两次(取决于生成器),应避免
- 用
file(GLOB ...)收集源文件虽方便,但 CMake 不自动检测新增文件——修改CMakeLists.txt或手动 touch 才会重新运行 glob,CI 环境容易遗漏
为什么 add_executable 后找不到符号或链接失败?
最常见的原因是源文件没加全,或依赖的库没链接。CMake 不会自动推断 main() 在哪,也不会自动链接标准库以外的任何东西。例如用了 std::thread 却没显式链接 pthread(Linux)或 dylib(macOS),就会卡在链接阶段。
典型症状:undefined reference to `pthread_create'、cannot find -lxxx、symbol not found。解决路径很明确:确认源文件是否都已加入 add_executable 或 target_sources,再检查 target_link_libraries 是否覆盖所有依赖。
- 第三方库路径未通过
find_package或add_subdirectory导入前,直接写target_link_libraries(myapp PRIVATE some_lib)会失败 - 静态库依赖动态库时,链接顺序重要:被依赖的库要放在后面,CMake 通常自动处理,但跨目录或自定义导入时可能出错
- Windows 下用 MinGW 编译却链接了 MSVC 编译的
.lib,或反过来,也会报符号找不到——ABI 不兼容,不是 CMake 问题,但现象相似
真正麻烦的是隐式依赖:比如头文件里 #include <json.hpp></json.hpp>,但没把 json.hpp 所在目录加进 target_include_directories,编译就挂了,这时候 add_executable 本身没错,只是上下游没配齐。










