CMake指令:add_executable
目录
1.简介
2.普通可执行目标文件
2.1.单文件 / 多文件构建
2.2.结合平台属性(WIN32/MACOSX_BUNDLE)
2.3.排除默认构建(EXCLUDE_FROM_ALL)
2.4.目标属性配置(后续通过 target_* 指令补充)
3.导入可执行目标文件
3.1.导入第三方预编译二进制文件
3.2.导入属性配置
3.3.与 add_executable 构建目标的区别
4.别名可执行文件
5.注意事项
6.与其他指令的配合
1.简介
用于定义一个可执行文件目标,指定其源文件及相关属性。这里的目标可执行文件分为三类:普通可执行目标文件、导入可执行目标文件、别名可执行目标文件。
基本语法:
add_executable (<name> [WIN32] [MACOSX_BUNDLE][EXCLUDE_FROM_ALL][source1] [source2 ...])
add_executable (<name> IMPORTED [GLOBAL])
add_executable (<name> ALIAS <target>)
2.普通可执行目标文件
通过指定的源文件列表构建出可执行目标文件。
add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL][source1] [source2] ... [sourceN])
- name:可执行目标文件的名字,在一个cmake工程中,这个名字必须全局唯一。
- WIN32:用于windows系统下创建一个以WinMain为入口的可执行目标文件(通常入口函数为main),它不是一个控制台应用程序,而是一个GUI应用程序。当WIN32选项使用的时候,可执行目标的 WIN32_EXECUTABLE会被置位ON。
- MACOSX_BUNDLE:用于mac系统或者IOS系统下创建一个GUI可执行应用程序,当MACOSX_BUNDLE选项使用的时候,可执行目标的MACOSX_BUNDLE会被置位ON。
- EXCLUDE_FROM_ALL:用于指定可执行目标是否会被构建,当该选项使用的时候,可执行目标不会被构建。
-
[source1] [source2 …]:构建可执行目标文件所需要的源文件。也可以通过target_sources()继续为可执行目标文件添加源文件,要求是在调用target_sources之前,可执行目标文件必须已经通过add_executable或add_library定义了。
2.1.单文件 / 多文件构建
# 单源文件(生成名为 main 的可执行文件)
add_executable(main main.cpp) # 多源文件(指定多个 .cpp 文件)
add_executable(app src/main.cpp src/utils.cpp src/data.cpp) # 通配符匹配(自动包含 src 目录下所有 .cpp 文件)
file(GLOB SOURCES "src/*.cpp") # 先通过 file 指令收集源文件
add_executable(app ${SOURCES})
2.2.结合平台属性(WIN32/MACOSX_BUNDLE)
# Windows 窗口程序(无控制台)
add_executable(my_gui WIN32 main.cpp win_main.cpp) # macOS 应用 Bundle(需手动添加 Info.plist 等资源)
add_executable(my_app MACOSX_BUNDLE main.cpp mac_resources/Info.plist)
2.3.排除默认构建(EXCLUDE_FROM_ALL)
# 该可执行文件默认不参与构建,需通过 `make test_app` 单独生成
add_executable(test_app EXCLUDE_FROM_ALL test.cpp)
2.4.目标属性配置(后续通过 target_*
指令补充)
定义目标后,可通过 target_*
指令添加编译选项、依赖等:
add_executable(main main.cpp)
target_include_directories(main PRIVATE include) # 添加头文件路径
target_link_libraries(main PRIVATE my_lib) # 链接依赖库
target_compile_options(main PRIVATE -Wall -std=c++17) # 设置编译选项
3.导入可执行目标文件
将工程外部的可执行目标文件导入进来,不会有任何构建可执行目标文件的动作发生。
add_executable (<name> IMPORTED [GLOBAL])
- name:导入可执行文件目标的名字
- GLOBAL:可执行目标文件的范围为文件创建的目录及子目录;指定GLOBAL则会将范围扩大到整个工程。
- IMPORTED:选项指定后,属性IMPORTED会被置为TRUE,在工程内构建的可执行目标文件的属性IMPORTED会被置为FALSE。
示例:导入系统工具 git
# 导入 git 可执行文件
add_executable(git_exe IMPORTED)# 指定 git 可执行文件的路径(根据平台自动查找)
find_program(GIT_EXECUTABLE NAMES git)
if(NOT GIT_EXECUTABLE)message(FATAL_ERROR "Git not found!")
endif()# 设置导入目标的属性
set_property(TARGET git_exe PROPERTY IMPORTED_LOCATION ${GIT_EXECUTABLE})# 后续可通过 git_exe 引用该可执行文件
add_custom_target(print_git_versionCOMMAND ${git_exe} --version
)
3.1.导入第三方预编译二进制文件
若项目依赖第三方预编译的可执行文件(如 protobuf-compiler
),可按以下方式导入:
示例:导入 Protobuf 编译器
# 导入 protoc 可执行文件
add_executable(protoc_exe IMPORTED)# 查找或指定 protoc 路径(根据实际情况调整)
if(WIN32)set(PROTOC_PATH "C:/path/to/protoc.exe")
else()set(PROTOC_PATH "/usr/bin/protoc")
endif()# 设置导入目标的属性
set_property(TARGET protoc_exe PROPERTY IMPORTED_LOCATION ${PROTOC_PATH})# 使用 protoc 生成代码(自定义命令示例)
add_custom_command(OUTPUT generated.pb.cc generated.pb.hCOMMAND protoc_exe --cpp_out=. my_protobuf.protoDEPENDS my_protobuf.proto
)
3.2.导入属性配置
导入可执行文件后,可通过 set_property
或 set_target_properties
配置以下属性:
IMPORTED_LOCATION
:可执行文件的路径(必设)。IMPORTED_LOCATION_<CONFIG>
:特定配置的路径(如 Debug/Release)。IMPORTED_NO_SONAME
:忽略共享库的 SONAME(仅对动态库有效)。IMPORTED_LINK_INTERFACE_LIBRARIES
:链接时依赖的其他库。
示例:按配置类型设置路径
set_target_properties(my_exe PROPERTIESIMPORTED_LOCATION_DEBUG "${CMAKE_SOURCE_DIR}/bin/Debug/my_exe.exe"IMPORTED_LOCATION_RELEASE "${CMAKE_SOURCE_DIR}/bin/Release/my_exe.exe"
)
3.3.与 add_executable
构建目标的区别
特性 | add_executable (构建) | add_executable(... IMPORTED) (导入) |
---|---|---|
源文件 | 必须指定源代码 | 无需源文件,直接引用已有可执行文件 |
构建过程 | 参与编译链接流程 | 不参与编译,仅作为外部工具引用 |
主要用途 | 生成项目自身的可执行文件 | 引用系统或第三方预编译的可执行文件 |
核心属性 | 通过 target_* 配置编译选项 | 配置 IMPORTED_LOCATION 等导入属性 |
4.别名可执行文件
为可执行目标文件创建一个别名。创建该别名后,可以使用别名进行可执行目标的读、测试操作,但是不能利用别名对可执行目标的修改属性操作。
add_executable (<name> ALIAS <target>)
示例如下:
#CMakeLists.txt
cmake_minimum_required(VERSION 3.10.2)
project(test)SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY output)add_executable(runtest main.cpp)add_executable(test_name ALIAS runtest)
get_target_property(alias_name test_name ALIASED_TARGET)
if(alias_name)message(">>> The name test_name is an ALIAS for ${alias_name}")
endif()
5.注意事项
1.目标名称唯一性:同一个目录下的 add_executable
/add_library
目标名称不能重复。
2.源文件作用域:源文件列表仅对当前目标有效,子目录需通过 add_subdirectory
单独处理。
3.生成路径:可执行文件默认生成到 CMake 构建目录(${CMAKE_BINARY_DIR}
),可通过:
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
自定义输出路径。
4.通配符(GLOB
)的局限性:使用 file(GLOB SOURCES "src/*.cpp")
收集源文件时,新增文件需重新运行 CMake 才能被识别(不推荐用于大型项目,建议显式列出核心文件)。
5.依赖与属性配置顺序:需先通过 add_executable
定义目标,再用 target_*
系列指令(如 target_link_libraries
)配置依赖 / 编译选项,不可颠倒顺序(目标未定义时调用 target_*
会报错)。
6.避免全局变量污染:不推荐用全局变量(如 SET(SOURCES ...)
)存储源文件列表后直接传递给多个 add_executable
,建议每个目标单独管理源文件,或通过函数封装(防止变量覆盖)。
7.与 add_library
的区别:add_executable
生成可执行文件,需包含完整入口函数(如 main
);add_library
生成库文件(静态 / 动态),无入口函数要求,二者配置逻辑类似但目标类型不同。
6.与其他指令的配合
add_library
:构建库文件,与可执行文件相互依赖。target_*
系列指令:配置编译选项、链接库、头文件路径等。install
:定义可执行文件的安装规则。
通过合理使用 add_executable
,可高效管理项目的可执行文件构建,结合 CMake 的其他指令实现复杂的跨平台构建流程。
相关链接
- CMake 官网 CMake - Upgrade Your Software Build System
- CMake 官方文档:CMake Tutorial — CMake 4.0.2 Documentation
- CMake 源码:GitHub - Kitware/CMake: Mirror of CMake upstream repository
- CMake 源码:Sign in · GitLab