官方教程
构建基础 CMake 项目
01 CMake 最基本组成
一个基础项目由 CMakeLists.txt 文件包含三句命令组成
目录结构
1 2 3
| - Help/guide/tutorial/Step1 - tutorial.cxx - CMakeLists.txt
|
CMakelists.txt
1 2 3 4 5 6
| # 1(必须)- 项目顶部指定最低可用CMake版本 cmake_minimum_required(VERSION 3.10) # 2(必须)- 指定项目名、语言及版本号等,必须在CMake版本声明之后 project(Tutorial) # 3(必须)- 告知CMake用于生成可执行程序的源代码文件 add_executable(Tutorial tutorial.cxx)
|
02 CMAKE_开头变量
通常以 CMAKE_开头的变量在 CMake
中有特殊含义,如CMAKE_CXX_STANDARD
和CMAKE_CXX_STANDARD_REQUIRED
配合使用可以用于指定
C++标准,可以通过set()
命令定义变量
CMakelists.txt
1 2 3
| # 指定使用 C++11 标准 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED True)
|
03 使用配置头文件
当我们需要 CMakelists.txt
中定义的变量在源代码中可见,可以通过配置头文件实现
通过configure_file()
命令替换输入文件中的由 CMakelists.txt
定义的变量值,然后复制到输出文件中
CMakelists.txt
1 2 3 4 5 6 7 8
| # 执行 project() 命令时,CMake 自动定义 Tutorial_VERSION_MAJOR 变量 和 Tutorial_VERSION_MINOR 变量 project(Tutorial VERSION 1.0) # TutorialConfig.h.in 作为输入配置头文件,变量 @Tutorial_VERSION_MAJOR@ 和 @Tutorial_VERSION_MINOR@ 在 TutorialConfig.h 中将会被替换 configure_file(TutorialConfig.h.in TutorialConfig.h) # 配置文件将输出到${PROJECT_BINARY_DIR}目录,添加该目录用于让CMake搜寻需要include的文件 target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" )
|
TutorialConfig.h.in
1 2 3
| #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@ #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
|
tutorial.cxx
1 2 3 4 5 6 7 8 9
| #include "TutorialConfig.h"
if (argc < 2) { std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR << std::endl; std::cout << "Usage: " << argv[0] << " number" << std::endl; return 1; }
|
添加库文件
01 创建一个库
- 通过
add_library()
命令添加库,并指定组成该库的源文件
- 通过
add_subdirectory()
命令添加子目录用于构建项目
- 通过
target_include_directories()
和target_link_libraries()
命令链接到可执行目标
目录结构
1 2 3 4 5 6 7 8 9 10 11
| - Help/guide/tutorial/Step2 - CMakeLists.txt - tutorial.cxx - MathFunctions - CMakeLists.txt - MathFunctions.h - mysqrt.h - MathFunctions.cxx [function] sqrt - mysqrt.cxx [function] mysqrt
|
MathFunctions/CMakeLists.txt
1 2
| # 创建 MathFunctions 库 add_library(MathFunctions MathFunctions.cxx mysqrt.cxx)
|
CMakeLists.txt
1 2 3 4 5 6 7 8 9
| # 使用 MathFunctions 库 add_subdirectory(MathFunctions) # 链接库到可执行目标 target_link_libraries(Tutorial PUBLIC MathFunctions) # 指定库头文件位置,使得 MathFunctions.h 头文件可见 target_include_directories(Tutorial PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/MathFunctions" )
|
tutorial.cxx
1 2
| #include "MathFunctions.h" const double outputValue = mathfunctions::sqrt(inputValue);
|
02 添加 Option
通过 option()
命令为用户提供变量用于配置构建,该配置将会保存在
cache,因此用户不需要每次都设置
MathFunctions/CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| # 相比于之前的配置移除了 mysqrt.cxx 文件,变更为随着 USE_MYMATH 的设置动态链接,减少资源消耗 add_library(MathFunctions MathFunctions.cxx)
# 为用户提供选项 USE_MYMATH,默认为 ON option(USE_MYMATH "Use tutorial provided math implementation" ON) # 创建 if() 语句检查 USE_MYMATH 的值 if (USE_MYMATH) # 设置编译定义 USE_MYMATH,可用于源代码中段的启用和废用 target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH") # 创建额外的库 SqrtLibrary 负责 mysqrt.cxx 的编译 add_library(SqrtLibrary STATIC mysqrt.cxx ) # 链接 SqrtLibrary 库到 MathFunctions target_link_libraries(MathFunctions PRIVATE SqrtLibrary) endif()
|
MathFunctions/MathFunctions.cxx
1 2 3 4 5 6 7 8 9 10 11 12
| #ifdef USE_MYMATH # include "mysqrt.h" #endif #include <cmath>
#ifdef USE_MYMATH return detail::mysqrt(x); #else return std::sqrt(x); #endif
|