本文是关于 C/C++ 开发的开源 DevOps 工具系列文章的一部分。如果您从一开始就基于强大的工具链构建项目,您将从更快、更安全的开发中受益。除此之外,您将更容易让其他人参与到您的项目中。在本文中,我将准备一个基于 CMake 和 VSCodium 的 C/C++ 构建系统。像往常一样,相关的示例代码可以在 GitHub 上找到。
我已经测试了本文中描述的步骤。这是一个适用于所有平台的解决方案。
为什么选择 CMake?
CMake 是一个构建系统生成器,它为您的项目创建 Makefile。乍一看听起来很简单,但仔细一看可能会非常复杂。在高层次上,您定义项目的各个部分(可执行文件、库)、编译选项(C/C++ 标准、优化、架构)、依赖项(头文件、库)以及文件级别的项目结构。这些信息通过一种特殊的描述语言在 CMakeLists.txt
文件中提供给 CMake。当 CMake 处理此文件时,它会自动检测系统上安装的编译器并创建一个可用的 Makefile。
此外,CMakeLists.txt
中描述的配置可以被许多编辑器读取,例如 QtCreator、VSCodium/VSCode 或 Visual Studio。
示例程序
我们的示例程序是一个简单的命令行工具:它接受一个整数作为参数,并输出从 1 到提供的输入值范围内随机洗牌的数字。
$ ./Producer 10
3 8 2 7 9 1 5 10 6 4
在可执行文件的 main()
函数中,我们只处理输入参数,如果没有提供值(或无法处理的值),则退出程序。
producer.cpp
int main(int argc, char** argv){
if (argc != 2) {
std::cerr << "Enter the number of elements as argument" << std::endl;
return -1;
}
int range = 0;
try{
range = std::stoi(argv[1]);
}catch (const std::invalid_argument&){
std::cerr << "Error: Cannot parse \"" << argv[1] << "\" ";
return -1;
}
catch (const std::out_of_range&) {
std::cerr << "Error: " << argv[1] << " is out of range";
return -1;
}
if (range <= 0) {
std::cerr << "Error: Zero or negative number provided: " << argv[1];
return -1;
}
std::stringstream data;
std::cout << Generator::generate(data, range).rdbuf();
}
实际工作在 Generator 中完成,它被编译并链接为静态库到我们的 Producer
可执行文件。
Generator.cpp
std::stringstream &Generator::generate(std::stringstream &stream, const int range) {
std::vector<int> data(range);
std::iota(data.begin(), data.end(), 1);
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(data.begin(), data.end(), g);
for (const auto n : data) {
stream << std::to_string(n) << " ";
}
return stream;
}
函数 generate
接受对 std::stringstream 的引用和一个整数作为参数。基于整数 range
的值 n,创建了一个 1 到 n 范围内的整数向量,然后进行洗牌。然后将洗牌向量中的值转换为字符串并推送到 stringstream
中。该函数返回与作为参数传递的相同的 stringstream
引用。
顶层 CMakeLists.txt
顶层 CMakeLists.txt 是我们项目的入口点。子目录中可以有多个 CMakeLists.txt
文件(例如,与项目关联的库或其他可执行文件)。我们从逐步浏览顶层 CMakeLists.txt
开始。
前几行告诉我们处理该文件所需的 CMake 版本、项目名称及其版本,以及预期的 C++ 标准。
cmake_minimum_required(VERSION 3.14)
project(CPP_Testing_Sample VERSION 1.0)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
我们告诉 CMake 查看子目录 Generator
,使用以下行。此子目录包含构建 Generator
库的所有信息,并包含其自身的 CMakeLists.txt
。我们稍后会讲到。
add_subdirectory(Generator)
现在我们来到了一个绝对特殊的功能:CMake 模块。加载模块可以扩展 CMake 的功能。在我们的项目中,我们加载模块 FetchContent,这使我们能够在运行 CMake 时下载外部资源,在我们的例子中是 GoogleTest 。
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/bb9216085fbbf193408653ced9e73c61e7766e80.zip
)
FetchContent_MakeAvailable(googletest)
在下一部分中,我们执行通常在普通 Makefile 中执行的操作:指定要构建的二进制文件、其相关的源文件、应链接到的库以及编译器可以在其中找到头文件的目录。
add_executable(Producer Producer.cpp)
target_link_libraries(Producer PUBLIC Generator)
target_include_directories(Producer PUBLIC "${PROJECT_BINARY_DIR}")
使用以下语句,我们让 CMake 在构建文件夹中创建一个名为 compile_commands.json
的文件。此文件公开了项目中每个文件的编译选项。加载到 VSCodium 中,此文件告诉 IntelliSense 功能在哪里找到头文件(请参阅 文档)。
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
最后一部分定义了我们项目的测试。该项目使用了先前加载的 GoogleTest 框架。单元测试的整个主题将是另一篇文章的一部分。
enable_testing()
add_executable(unit_test unit_test.cpp)
target_link_libraries(unit_test gtest_main)
include(GoogleTest)
gtest_discover_tests(unit_test)
库级别 CMakeLists.txt
现在我们来看子目录 Generator
中的 CMakeLists.txt 文件,其中包含同名库。此 CMakeLists.txt
短得多,除了与单元测试相关的命令外,它只包含两个语句。
add_library(Generator STATIC Generator.cpp Generator.h)
target_include_directories(Generator INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
使用 add_library(...)
我们定义了一个新的构建目标:静态 Generator
库。使用语句 target_include_directories(...)
,我们将当前子目录添加到其他构建目标的头文件搜索路径中。我们还将此属性的范围指定为 INTERFACE
类型:这意味着该属性只会影响链接到此库的构建目标,而不会影响库本身。
VSCodium 入门
借助 CMakeLists.txt
中可用的信息,像 VSCodium 这样的 IDE 可以相应地配置构建系统。如果您还没有 VSCodium 或 VS Code 的经验,则此示例项目是一个很好的起点。首先,访问他们的 网站 并下载适用于您系统的最新安装包。打开 VSCodium 并导航到扩展 选项卡。
要正确构建、调试和测试项目,请搜索以下扩展并安装它们。

(Stephan Avenwedde,CC BY-SA 4.0)
如果尚未完成,请单击起始页上的克隆 Git 仓库 来克隆仓库。

(Stephan Avenwedde,CC BY-SA 4.0)
或手动输入
git clone https://github.com/hANSIc99/cpp_testing_sample.git
之后,通过键入以下内容检出标签 devops_1
git checkout tags/devops_1
或者单击 main 分支按钮(红色框),然后从下拉菜单(黄色框)中选择标签。

(Stephan Avenwedde,CC BY-SA 4.0)
一旦您在 VSCodium 中打开仓库的根文件夹,CMake Tools
扩展将检测到 CMakeLists.txt
文件并立即扫描您的系统以查找合适的编译器。您现在可以单击屏幕底部的构建 按钮(红色框)以启动构建过程。您还可以通过单击底部(黄色框)标记的区域来更改编译器,该区域显示当前活动的编译器。

(Stephan Avenwedde,CC BY-SA 4.0)
要开始调试 Producer
可执行文件,请单击调试器符号(黄色框),然后从下拉菜单中选择调试 Producer (绿色框)。

(Stephan Avenwedde,CC BY-SA 4.0)
如前所述,Producer
可执行文件期望将元素数量作为命令行参数。命令行参数可以在文件 .vscode/launch.json
中指定。

(Stephan Avenwedde,CC BY-SA 4.0)
好的,您现在可以构建和调试项目了。
结论
感谢 CMake,上述步骤应该可以在您运行的任何操作系统上工作。特别是对于与 CMake 相关的扩展,VSCodium 成为一个功能强大的 IDE。我没有提及 VSCodium 的 Git 集成,因为您已经可以在网上找到许多资源。我希望您看到提供正确的 CMake 配置可以使其他人更容易构建、使用和贡献您的项目。在以后的文章中,我将研究单元测试和 CMake 的 测试实用程序 ctest
。
评论已关闭。