使用 CMake 和 VSCodium 设置构建系统

提供正确的 CMake 配置可以使其他人更容易构建、使用和贡献您的项目。
10 位读者喜欢这个。
woman on laptop sitting at the window

CC BY 3.0 US Mapbox Uncharted ERG

本文是关于 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 并导航到扩展 选项卡。

要正确构建、调试和测试项目,请搜索以下扩展并安装它们。

如果尚未完成,请单击起始页上的克隆 Git 仓库 来克隆仓库。

或手动输入

git clone https://github.com/hANSIc99/cpp_testing_sample.git

之后,通过键入以下内容检出标签 devops_1 

git checkout tags/devops_1

或者单击 main 分支按钮(红色框),然后从下拉菜单(黄色框)中选择标签。

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

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

如前所述,Producer 可执行文件期望将元素数量作为命令行参数。命令行参数可以在文件 .vscode/launch.json 中指定。

好的,您现在可以构建和调试项目了。

结论

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

接下来阅读什么

放弃 Autotools,选择 CMake

CMake 是一套跨平台套件,用于构建、测试和打包软件,即使您以前从未使用过构建系统,它也很容易使用。

标签
User profile image.
Stephan 是一位技术爱好者,他欣赏开源,因为它能深入了解事物的工作原理。Stephan 在工业自动化软件这个大部分是专有领域的公司担任全职支持工程师。如果可能,他会致力于他基于 Python 的开源项目、撰写文章或骑摩托车。

评论已关闭。

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© 2025 open-source.net.cn. All rights reserved.