跳到主要内容

CMake 可执行目标

本章将介绍如何使用 CMake 创建和管理可执行目标。

创建可执行目标

基本语法

add_executable(target_name [source1] [source2 ...])

简单示例

cmake_minimum_required(VERSION 3.15)
project(MyApp)

add_executable(myapp main.cpp)

多文件项目

# 方式一:直接列出
add_executable(myapp
src/main.cpp
src/app.cpp
src/utils.cpp
include/app.h
)

# 方式二:使用变量
set(SOURCES
src/main.cpp
src/app.cpp
src/utils.cpp
)
add_executable(myapp ${SOURCES})

使用 GLOB 收集文件

# 收集单个目录
file(GLOB SOURCES "src/*.cpp")

# 递归收集
file(GLOB_RECURSE SOURCES
"src/*.cpp"
"include/*.h"
)

add_executable(myapp ${SOURCES})
注意

使用 GLOB 时,新增文件后需要重新运行 cmake 命令,否则不会自动检测新文件。

目标属性

设置输出名称

add_executable(myapp main.cpp)

# 设置输出文件名
set_target_properties(myapp PROPERTIES
OUTPUT_NAME "my_application"
)

设置输出目录

# 设置可执行文件输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

add_executable(myapp main.cpp)

设置 C++ 标准

add_executable(myapp main.cpp)

# 方式一:使用目标属性
set_target_properties(myapp PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
)

# 方式二:使用编译特性
target_compile_features(myapp PUBLIC cxx_std_17)

编译选项

头文件路径

target_include_directories(myapp
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)

预处理器定义

target_compile_definitions(myapp
PRIVATE
DEBUG_MODE
VERSION="1.0.0"
PUBLIC
API_EXPORT
)

编译选项

target_compile_options(myapp
PRIVATE
-Wall
-Wextra
-Wpedantic
$<$<CONFIG:Debug>:-g -O0>
$<$<CONFIG:Release>:-O3 -DNDEBUG>
)

链接库

链接项目内库

# 创建库
add_library(mylib src/lib.cpp)
target_include_directories(mylib PUBLIC include)

# 创建可执行文件并链接
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)

链接系统库

# 链接线程库
find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

# 链接数学库(Linux)
target_link_libraries(myapp PRIVATE m)

链接外部库

# 使用 find_package
find_package(OpenCV REQUIRED)
target_link_libraries(myapp PRIVATE ${OpenCV_LIBS})

# 或使用现代目标
find_package(fmt REQUIRED)
target_link_libraries(myapp PRIVATE fmt::fmt)

条件编译

平台特定源文件

set(SOURCES
src/main.cpp
src/common.cpp
)

if(WIN32)
list(APPEND SOURCES src/windows_specific.cpp)
elseif(UNIX)
list(APPEND SOURCES src/linux_specific.cpp)
endif()

add_executable(myapp ${SOURCES})

平台特定编译选项

if(MSVC)
target_compile_options(myapp PRIVATE /W4 /utf-8)
else()
target_compile_options(myapp PRIVATE -Wall -Wextra)
endif()

安装配置

基本安装

add_executable(myapp src/main.cpp)

# 安装可执行文件
install(TARGETS myapp
RUNTIME DESTINATION bin
)

完整安装配置

install(TARGETS myapp
RUNTIME DESTINATION bin
BUNDLE DESTINATION . # macOS 应用包
)

# 安装配置文件
install(FILES config/settings.json
DESTINATION etc/myapp
)

# 安装文档
install(DIRECTORY docs/
DESTINATION share/doc/myapp
)

实战示例

完整项目示例

cmake_minimum_required(VERSION 3.15)
project(MyApp VERSION 1.0.0 LANGUAGES CXX)

# 设置默认构建类型
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

# 设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

# 收集源文件
file(GLOB_RECURSE SOURCES "src/*.cpp")
file(GLOB_RECURSE HEADERS "include/*.h")

# 创建可执行目标
add_executable(myapp ${SOURCES} ${HEADERS})

# 设置头文件目录
target_include_directories(myapp
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)

# 设置 C++ 标准
target_compile_features(myapp PUBLIC cxx_std_17)

# 编译选项
target_compile_options(myapp
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/W4 /utf-8>
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wpedantic>
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wpedantic>
)

# 预处理器定义
target_compile_definitions(myapp
PRIVATE
PROJECT_VERSION="${PROJECT_VERSION}"
PUBLIC
$<$<CONFIG:Debug>:DEBUG_MODE>
)

# 查找并链接依赖
find_package(Threads REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)

# 安装配置
install(TARGETS myapp RUNTIME DESTINATION bin)

小结

本章我们学习了:

  1. 创建可执行目标:add_executable
  2. 目标属性:输出名称、目录、C++ 标准
  3. 编译选项:头文件路径、预处理器定义、编译选项
  4. 链接库:项目内库、系统库、外部库
  5. 条件编译:平台特定配置
  6. 安装配置:安装目标文件

练习

  1. 创建一个多文件的可执行项目
  2. 配置 Debug 和 Release 不同的编译选项
  3. 实现跨平台的可执行文件构建
  4. 编写完整的安装配置