CMake
CMake 保姆级教程(上) | CMake 保姆级教程(下) | CMake官方教程 | Cmake中文实战教程 | Modern CMake 简体中文版 | vscode-cmake | Visual Studio 中的 CMake 项目
# cmake 构建方式1cmake..cmake -G Ninja ..注意事项
跳转到“注意事项”(1)project() 命令用于定义项目名称和语言,并且可以影响后续命令的行为,包括如何解析工具链文件。
这里是为什么 project() 应该在前的原因:
- 项目上下文:
project()命令初始化了项目上下文,包括项目名称和使用的语言。这为后续的命令提供了必要的上下文信息。 - 命令依赖:一些CMake命令可能依赖于项目命令设置的上下文。例如,某些命令可能需要知道项目名称或使用的编程语言。
- CMake模块和脚本:在
project()之后调用的命令可以访问项目特定的变量和设置,这可能会影响到工具链文件的解析和应用。 - CMake缓存:
project()命令可能会影响CMake缓存的设置,这可能会间接影响工具链文件中的设置。 - CMake版本:从CMake 3.0开始,
project()命令提供了一种标准化的方式来设置项目信息,包括版本和所需的CMake版本。
(2)cmake关系
- 一个
CMakeLists.txt,可以包含多个目标,多个目标可以独立,可以依赖,但是要保证依赖项先构建; target_source是朝目标中添加源文件,add_executable命令是用来创建一个新的可执行文件目标的,它需要至少一个源文件作为参数。然而,这并不意味着在add_executable命令执行后,就不能再向该目标添加源文件了。target_sources命令就是用来在add_executable或add_library命令之后,向已经创建的目标添加更多源文件的。这样做的好处是,你可以在多个地方添加源文件到同一个目标,而不需要一开始就知道所有的源文件。这对于大型项目或者源文件在多个目录中的项目非常有用。
| 阶段 | 操作描述 | CMake代码示例 |
|---|---|---|
project()之前 | 设置CMake最低版本要求 | cmake_minimum_required(VERSION 3.10) |
| 定义宏和变量 | set(MY_VARIABLE "some_value") | |
| 设置CMake政策 | cmake_policy(SET CMP0054 NEW) | |
| 指定工具链文件 | set(CMAKE_TOOLCHAIN_FILE path/to/toolchain.cmake) | |
| 条件逻辑 | if(MY_CONDITION) ... endif() | |
project()之后 | 定义项目信息 | project(MyProject VERSION 1.0 LANGUAGES CXX) |
| 包含其他CMake文件或模块 | include(OtherCMakeFile) | |
| 定义源文件列表 | set(SOURCES main.cpp utils.cpp) | |
| 添加编译器定义 | add_definitions(-DDEBUG) | |
| 设置编译选项 | target_compile_options(my_target PRIVATE -Wall) | |
| 链接库到目标 | target_link_libraries(my_target some_library) | |
| 创建可执行文件或库 | add_executable(my_executable ${SOURCES}) | |
| 设置目标属性 | set_target_properties(my_target PROPERTIES OUTPUT_NAME "my_output") | |
| 设置安装规则 | install(TARGETS my_executable RUNTIME DESTINATION bin) | |
| 添加测试 | enable_testing()add_test(NAME MyTest COMMAND my_executable) | |
| 设置包信息 | set(CPACK_PACKAGE_VERSION "1.0.0") | |
| 配置文件生成 | configure_file(config.h.in config.h) | |
| 处理项目依赖项 | find_package(RequiredDependency REQUIRED) | |
| 自定义命令和规则 | add_custom_command(TARGET my_target POST_BUILD COMMAND ...) | |
| 设置CPack参数 | set(CPACK_GENERATOR "DEB") | |
使用project()设置的变量 | message(STATUS "Project version: ${PROJECT_VERSION}") |
(2)指定编译器
# 设置C和C++编译器的路径set(CMAKE_C_COMPILER "/usr/bin/gcc")set(CMAKE_CXX_COMPILER "/usr/bin/g++")cmake -G "MinGW Makefiles" -DCMAKE_MAKE_PROGRAM="D:/program/MinGW/bin/make.exe" -S . -B build`-G "MinGW Makefiles"`:这个选项告诉CMake使用MinGW Makefiles作为构建系统。`-S`选项后面跟随的是源代码目录的路径 .`-B`选项后面跟随的是构建目录的路径| 命令 | 说明 | 代码示例 |
|---|---|---|
project() | 定义项目名称和所需的CMake最低版本。 | project(MyProject VERSION 1.0 LANGUAGES CXX) |
cmake_minimum_required() | 指定工程需要的CMake的最低版本。 | cmake_minimum_required(VERSION 3.10) |
add_executable() | 创建一个可执行文件目标。 | add_executable(my_executable main.cpp) |
add_library() | 创建一个库目标。 | add_library(my_library STATIC my_library.cpp) |
target_sources() | 向目标添加源文件。 | target_sources(my_executable PRIVATE source.cpp) |
target_link_libraries() | 为目标链接库。 | target_link_libraries(my_executable PRIVATE my_library) |
include_directories() | 添加头文件搜索路径。 | include_directories(include) |
target_include_directories() | 为目标添加头文件搜索路径。 | target_include_directories(my_executable PUBLIC include) |
file(GLOB...) | 收集与模式匹配的文件。 | file(GLOB SOURCES "*.cpp") |
add_compile_options() | 为目标添加编译选项。 | add_compile_options(-Wall -Wextra) |
set() | 设置变量的值。 | set(MY_VARIABLE "my_value") |
list(append ) | ||
find_package() | 查找并加载外部依赖包的配置。 | find_package(Threads REQUIRED) |
enable_language() | 启用一种编程语言。 | enable_language(CXX) |
set_property() | 设置指定目标的属性。 | set_property(TARGET my_executable PROPERTY CXX_STANDARD 14) |
add_custom_command() | 向目标添加自定义命令。 | add_custom_command(TARGET my_executable POST_BUILD COMMAND echo "Build finished") |
add_custom_target() | 创建自定义目标。 | add_custom_target(my_custom_target COMMAND echo "Doing something") |
install() | 定义如何安装目标或文件。 | install(TARGETS my_executable RUNTIME DESTINATION bin) |
if(), elseif(), else() | 条件语句,用于基于条件执行不同的命令。 | if(MY_CONDITION) add_definitions(-DCONDITION_TRUE) endif() |
configure_file() | 复制文件到另一个位置并替换变量。 | configure_file(config.h.in config.h @ONLY)configure_file(${include} ${PROJECT_INCLUDE_DIR} COPYONLY) |
execute_process() | 执行一个外部命令并捕获输出。 | execute_process(COMMAND ls OUTPUT_VARIABLE output) |
| 变量名称 | 详细说明 |
|---|---|
CMAKE_SOURCE_DIR | 指向包含顶层CMakeLists.txt的项目的源代码根目录。在项目中任何位置,这个变量都指向同一路径。 |
CMAKE_BINARY_DIR | 指向当前的构建(输出)目录,即执行CMake命令时所在的目录。 |
CMAKE_CURRENT_SOURCE_DIR | 指向当前正在处理的CMakeLists.txt文件所在的相对路径。用于确定当前子项目的源文件位置。 |
CMAKE_CURRENT_BINARY_DIR | 对应于CMAKE_CURRENT_SOURCE_DIR,但是是构建时的二进制目录。 |
PROJECT_SOURCE_DIR | 当使用project()命令定义项目时设置,指向项目的源代码根目录。 |
PROJECT_BINARY_DIR | 对应于PROJECT_SOURCE_DIR,但是是项目的构建目录。 |
CMAKE_CACHE | 包含CMake缓存的完整路径和文件名,这个缓存文件存储了所有变量的值和选项。 |
CMAKE_CACHE_DEFAULT_DIR | 存储CMake默认缓存的目录,通常在首次运行CMake时使用。 |
CMAKE_CACHE_FILE | 存储CMake缓存的文件名,默认为CMakeCache.txt。 |
CMAKE_COMMAND | 完整路径到CMake的可执行文件,可以用来在脚本中调用CMake本身。 |
CMAKE_CTEST_COMMAND | 路径到CTest工具,用于测试驱动。 |
CMAKE_MAKE_PROGRAM | 指定的make工具(如make或ninja)的完整路径。 |
CMAKE_PROJECT_NAME | project()命令中定义的项目名称。 |
CMAKE_PROJECT_VERSION | project()命令中定义的项目版本信息。 |
EXECUTABLE_OUTPUT_PATH | 指定所有添加的可执行文件的输出路径。可以通过set()命令在CMakeLists.txt中修改。 |
LIBRARY_OUTPUT_PATH | 指定所有添加的库文件的输出路径。可以通过set()命令在CMakeLists.txt中修改。 |
CMAKE_RUNTIME_OUTPUT_DIRECTORY | 包含所有运行时输出文件(如可执行文件和动态库)的基础目录。 |
CMAKE_LIBRARY_OUTPUT_DIRECTORY | 包含所有库输出文件(如静态库和动态库)的基础目录。 |
CMAKE_ARCHIVE_OUTPUT_DIRECTORY | 包含所有静态库输出文件的基础目录。 |
CMAKE_BUILD_TYPE | 指定当前选择的配置类型(如Debug、Release、RelWithDebInfo等)。 |
CMAKE_SYSTEM_NAME | 目标系统的名称,这可以影响CMake选择的文件和工具链。 |
CMAKE_SYSTEM_PROCESSOR | 目标系统的处理器名称,可以用来定制特定于处理器的构建选项。 |
CMAKE_SYSTEM | 一个包含系统名称和处理器的组合的字符串,用于指定目标系统。 |
CMAKE_C_COMPILER | 指定的C编译器的路径,如果没有指定,则使用CMake检测到的默认编译器。 |
CMAKE_CXX_COMPILER | 指定的C++编译器的路径,如果没有指定,则使用CMake检测到的默认编译器。 |
CMAKE_Fortran_COMPILER | 指定的Fortran编译器的路径,如果没有指定,则使用CMake检测到的默认编译器。 |
CMAKE_EXPORT_COMPILE_COMMANDS | 选项的作用是生成 compile_commands.json 文件,该文件包含了编译每个源文件的详细命令。这对使用一些需要了解编译细节的工具和 IDE(例如 Clang 静态分析工具或一些代码补全插件)非常有用 |
| 关键字 | 作用域说明 | 链接属性说明 | 示例 |
|---|---|---|---|
| PRIVATE | 私有:仅用于编译指定目标,不会传递给依赖该目标的其他目标。 | 静态库:不导出任何符号。 动态库:不导出符号给依赖者。 | target_sources(my_lib PRIVATE source_file.cpp) |
| PUBLIC | 公共:用于编译指定目标,同时传递给依赖该目标的其他目标。 | 静态库:导出符号给依赖者。 动态库:导出符号给依赖者。 | target_link_libraries(my_exe PUBLIC my_lib) |
| INTERFACE | 接口:不用于编译指定目标,但会传递给依赖该目标的其他目标。 | 仅适用于动态库:导出符号给依赖者,但不链接库。 | target_link_libraries(my_exe INTERFACE my_lib) |