快速 CMake 教程
本教程将指导您在 CLion 中创建和开发一个简单的 CMake 项目。 逐步学习 CMake 作为构建系统的基础知识,以及 CMake 特定的 IDE 设置和操作。
1. 简单的 CMake 项目
CMake 是一个元构建系统,它使用称为 CMakeLists 的脚本为特定环境生成构建文件(例如,Unix 机器上的 makefiles)。
当您在 CLion 中创建一个新的 CMake 项目时,会在项目根目录下自动生成一个 CMakeLists.txt 文件。
启动一个示例 CMake 项目
请选择 从主菜单。
在左侧窗格中选择 C++ 可执行文件。
在我们的示例中,项目名称为 cmake_testapp ,选择的语言标准为 C++17。

点击 创建。
CLion 将生成一个包含单个源文件 main.cpp 和一个 CMakeLists.txt 脚本的初始项目。

自动生成的 CMakeLists.txt 包含以下命令:
点击 IDE 左侧工具栏上的
打开 CMake 工具窗口,您可以在其中检查项目加载的进度和状态:

2. CMake 目标和 CLion 配置
目标 是一个可执行文件或库,通过 CMake 脚本构建。 您可以在单个脚本中定义多个构建目标。
目前,我们的测试项目只有一个构建目标, cmake_testapp。 在首次加载项目时,CLion 会自动添加与此目标关联的运行/调试配置:

在切换器中,点击 编辑配置 查看详细信息。 目标名称和可执行文件名称与 CMakeLists.txt 中指定的相同:

请注意此对话框的 启动前 区域。 构建 默认设置为启动前步骤。 因此,我们不仅可以使用此配置调试或运行目标,还可以执行构建。 有关 CLion 中各种构建操作的更多信息,请查看 构建操作。
3. 向现有目标添加文件
让我们创建一个新的源文件 general.cpp 并将其添加到 cmake_testapp 目标。
右键点击项目树中的根文件夹,然后选择 新建 | C/C++ 源文件:

选中 添加到目标 复选框:

点击 确定 ,新文件将被添加到
add_executable命令中:
4. 添加新目标
现在让我们再添加两个文件,并为它们创建一个可执行目标和一个库目标。
新的可执行目标
右键点击项目树中的根文件夹,然后再次选择 新建 | C/C++ 源文件。
设置文件名(在我们的示例中为 calc )。
在 添加到目标 字段中,清除 cmake_testapp 复选框。
点击 添加新目标 链接:

指定目标名称(
cmake_testapp_calc),然后点击 添加:
新创建的目标将出现在列表中。
确保仅选择了
cmake_testapp_calc目标:
点击 确定。
CLion 将向 CMakeLists.txt 添加一个新的
add_executable命令并重新加载项目:
重新加载后,新配置将出现在配置切换器中:

新的库目标
右键点击项目树中的根文件夹,然后再次选择 新建 | C/C++ 源文件。
提供文件名( calc_lib )。
清除 添加到目标 字段中的复选框。
点击 添加新目标。

在下拉列表中,选择
add_library:
设置目标名称(
cmake_testapp_lib),然后点击 添加。
新创建的目标将出现在列表中。
确保其他目标的复选框已清除。

选中 创建关联头文件 复选框以同时添加一个头文件, calc_lib.h 。
点击 确定。
CLion 将向 CMakeLists.txt 添加一个
add_library命令并重新加载项目:
与可执行目标的情况类似,CLion 会自动为库目标创建配置:

然而,这是一个不可执行的配置,因此如果您尝试运行或调试它,您将收到
未指定可执行文件 错误消息:

要获取库文件,您需要构建此配置。 在切换器中选择它,然后按 Ctrl+F9 或点击构建图标:

结果, libcmake_testapp_lib.a 文件将出现在 cmake-构建-debug 文件夹中。

5. 重新加载项目
让我们手动在 CMakeLists.txt 中引入一些更改。 例如,将 STATIC 添加到库目标的声明中:

当我们在 CMakeLists.txt 中进行更改时,CLion 会显示一个图标,提示重新加载项目。 点击它或按快捷键:

6. CMake 预设和 CLion CMake 配置文件
要为您的项目配置和共享 CMake 选项,您可以使用 CMake 预设、CLion 的 CMake 配置文件,或两者兼用。
CMake 配置文件 与 CMake 预设 有许多共同设置,并且也可以通过 VCS 共享。 主要区别在于配置文件引用了 CLion 的 toolchain ,其中包含 CMake 预设中不存在且不需要的信息(例如调试器或环境设置)。
CMake 预设
CMake 预设 是一种使用两个文件配置和共享 CMake 选项的方法:
用于项目作用域的构建的 CMakePresets.json 。 此文件可以通过 VCS 共享。
用于开发者本地构建的 CMakeUserPresets.json 。 此文件不应提交到 VCS。
这两个文件格式相同,应位于项目的根目录中。
CMake 配置文件
一个配置文件包括 toolchain 和 构建类型 ,以及 CMake 选项,例如 生成器 和 环境变量。 您可以为项目配置多个配置文件,例如使用不同的编译器或以不同的设置构建目标。
请参阅下一章,了解为 Release 构建添加配置文件的示例。
7. 构建类型
到目前为止创建的所有运行/调试配置都是 Debug 配置,这是为我们的项目自动配置的 CMake 配置文件 的默认构建类型。
例如,让我们将 Debug 和 Release 构建分开。 为此,在 中添加( )一个新的 CMake 配置文件,并将其构建类型设置为 Release:

请注意 构建目录 字段,它指定了构建结果的位置。 默认文件夹是 cmake-构建-debug 用于 Debug 配置文件, cmake-构建-release 用于 Release 配置文件。 您始终可以设置 其他您选择的位置。
保存配置文件后,它将出现在切换器中:

8. 添加包含目录
要使用位于单独目录中的额外头文件,您需要将它们添加到所有目标或某些特定目标。
例如,让我们在项目根目录下创建三个目录: 包含 、 包含/general 和 包含/math 。 在项目树上下文菜单中使用 选项。

打开 CMakeLists.txt 并添加以下命令:
target_include_directories (cmake_testapp_lib PUBLIC includes/math) target_include_directories (cmake_testapp_lib PUBLIC includes/general)这两个命令使位于 general 和 math 的头文件可从
cmake_testapp_lib目标的源文件中访问。例如,如果我们将一个名为 header_math.h 的头文件放在 包含/math 文件夹中,我们可以使用
#include "header_math.h"从 calc_lib.cpp 中包含它。
9. 链接库
静态库
在 第 4 步 中,我们创建了一个名为 cmake_testapp_lib 的静态库(默认文件名为 libcmake_testapp_lib.a )。
现在让我们看看如何将此库链接到我们的项目。 为了方便起见,我们将为其创建并使用一个单独的文件夹。
在项目根目录下创建一个 lib 目录。
将 libcmake_testapp_lib.a 从其默认位置(即 cmake-构建-debug )复制到 lib 文件夹。

添加以下命令以将此库链接到 cmake_testapp 目标:
find_library(TEST_LIBRARY cmake_testapp_lib lib) target_link_libraries(cmake_testapp LINK_PUBLIC ${TEST_LIBRARY})find_library 提供了库的完整路径,
然后我们通过
${TEST_LIBRARY}变量将其直接传递到 target_link_libraries 命令中。

动态库
为了说明共享(动态)库的情况,我们将以使用 LibPNG 为例,这是一个用于读取和写入便携式网络图形(PNG)文件的 C 库。
使用 vcpkg 安装库包
CLion 与 vcpkg 集成,这是一个 C/C++ 的包管理器。 我们将使用它直接从 IDE 快速安装库。
按照 此说明 安装 vcpkg。
在 vcpkg 工具窗口中搜索 libpng:

点击右侧窗格中的 安装 并等待安装完成。
将库添加到 CMakeLists.txt
打开 CMakeLists.txt 文件并添加以下命令:
find_package(PNG REQUIRED) include_directories(${PNG_INCLUDE_DIR}) target_link_libraries(cmake_testapp PRIVATE ${PNG_LIBRARY})要检查库是否正确链接,请尝试将其中一个库头文件包含到 main.cpp 中:

例如,包含 png.h 。 然后您可以按 Ctrl+B 打开此文件:

10. CMake 调试
如果在 CMake 配置期间出现错误或不希望的行为,您可以像调试项目中的其他代码一样调试 CMake 脚本。
在您的 CMakeLists.txt 文件或文件中设置断点。
打开顶层 CMakeLists.txt ,点击第一个命令旁边的边距图标,然后选择 Debug:

CLion 将启动一个 CMake 调试会话:

有关更多信息,请参阅 CMake 调试功能。
11. 编辑 CMakeLists.txt 的提示
CLion 提供代码洞察功能,帮助您高效地处理 CMake 脚本。 例如:
12. 使用 CTest
本章提供了一个简单的示例,说明如何使用 CTest ,这是一个在 CMake 构建过程中编译和运行测试的框架。 您可以在 CTest 支持 中找到该框架的一般描述。
将 CTest 添加到示例项目
在项目根目录下创建一个 ctest 目录。
将以下文件添加到 ctest 目录中:
一个源文件 addvalues_zero.cpp 。 暂时不要将此文件链接到任何 CMake 目标。
一个头文件 assert_macro.h 。 暂时不要将此文件链接到任何 CMake 目标。
一个 CMakeLists.txt 脚本。

将以下行添加到 ctest/CMakeLists.txt 中:
cmake_minimum_required(VERSION 3.14.0 FATAL_ERROR) add_executable(ctest_exe_addvalues_zero addvalues_zero.cpp) target_link_libraries(ctest_exe_addvalues_zero LINK_PUBLIC cmake_testapp_lib) add_test(NAME ctest_addvalues_zero COMMAND ctest_exe_addvalues_zero) set_tests_properties(ctest_addvalues_zero PROPERTIES PASS 0)第一行声明了 CTest 的最低支持版本,对应于 CMake 的版本 3.14。
我们在这里使用 add_test 命令将
ctest_exe_addvalues_zero可执行文件注册到 CTest。接下来,我们需要在顶层 CMakeLists.txt 中启用 CTest 并声明子项目:
enable_testing() add_subdirectory(ctest)enable_testing 命令创建了一个内置目标
test,执行 CTest。重新加载项目。
添加要测试的代码
让我们准备一段代码以使用 CTest 进行测试。
在 calc_lib.cpp 中添加一个简单函数。
int add_values (int a, int b) { return a+b;}在关联的头文件 calc_lib.h 中添加函数声明:
int add_values (int a, int b);
将代码添加到测试源中
assert_macro.h :
#include <iostream> #include <sstream> #define assertEqual( ... ) \ do { \ if( !( __VA_ARGS__ ) ) { \ std::cerr << "Unit test assert [ " \ << ( #__VA_ARGS__ ) \ << " ] failed in line [ " \ << __LINE__ \ << " ] file [ " \ << __FILE__ << " ]" \ << std::endl; \ err_code = 1; \ } \ } while( false )addvalues_zero.cpp :
#include "assert_macro.h" #include "../calc_lib.h" int test_addvalues_zero() { int err_code = 0; assertEqual (add_values(0, 0) == 0); assertEqual (add_values(-5, 5) == 0); return err_code; } int main() { return test_addvalues_zero(); }
编辑 CTest 配置
在主菜单中,进入 .
在 CTest 应用程序 节点下,您将找到自动创建的 所有 CTest 配置。
由于要测试的代码位于
ctest_exe_addvalues_zero可执行文件中,我们需要在配置设置中选择该可执行文件作为构建目标:
我们还检查一下 要运行的测试列表 字段。 点击笔图标打开 可用测试列表 对话框,在其中我们可以查看和调整测试集:

运行 CTest 配置并查看结果
在配置切换器中选择 所有 CTest ,然后点击
或按 Shift+F10。

在 测试运行器 窗口中找到结果:

13. 有用的链接
要深入了解 CLion 中的 CMake,请学习以下内容:



