使用 CMake 和 VSCodium 设置一个构建系统

开发 后端
这篇文章是使用开源 DevOps 工具进行 C/C++ 开发系列文章的一部分。如果你从一开始就把你的项目建立在一个功能强大的工具链上,你的开发会更快和更安全。除此之外,这会使别人更容易地参与你的项目。


提供一个适当的 CMake 配置文件来使其他人可以更容易地构建、使用和贡献你的项目。


这篇文章是使用开源 DevOps 工具进行 C/C++ 开发系列文章的一部分。如果你从一开始就把你的项目建立在一个功能强大的工具链上,你的开发会更快和更安全。除此之外,这会使别人更容易地参与你的项目。在这篇文章中,我将搭建一个基于 ​​CMake​​ 和 ​​VSCodium​​ 的 C/C++ 构建系统。像往常一样,相关的示例代码可以在 ​​GitHub​​ 上找到。

我已经测试了在本文中描述的步骤。这是一种适用于所有平台的解决方案。

为什么用 CMake ?

​CMake​​ 是一个构建系统生成器,可以为你的项目创建 Makefile。乍一看简单的东西可能相当地复杂。在较高的层次上,你可以定义你的项目的各个部分(可执行文件、库)、编译选项(C/C++ 标准、优化、架构)、依赖关系项(头文件、库),和文件级的项目结构。CMake 使用的这些信息可以在文件 ​​CMakeLists.txt​​ 中获取,它使用一种特殊的描述性语言编写。当 CMake 处理这个文件时,它将自动地侦测在你的系统上已安装的编译器,并创建一个用于启动它的 Makefile 文件。

此外,在 ​​CMakeLists.txt​​ 中描述的配置,能够被很多编辑器读取,像 QtCreator、VSCodium/VSCode 或 Visual Studio 。

示例程序

我们的示例程序是一个简单的命令行工具:它接受一个整数来作为参数,输出一个从 1 到所提供输入值的范围内的随机排列的数字。

$ ./Producer 10
3 8 2 7 9 1 5 10 6 4

在我们的可执行文件中的 ​​main()​​ 函数,我们只处理输入的参数,如果没有提供一个值(或者一个不能被处理的值)的话,就退出程序。

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();
}

producer.cpp

实际的工作是在 ​​生成器​​ 中完成的,它将被编译,并将作为一个静态库来链接到我们的​​Producer​​ 可执行文件。

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;
}

Generator.cpp

函数 ​​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​​ 文件的内容更简短一些,除了单元测试相关的命令外,它仅包含 2 条语句。

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 并导航到 “扩展Extensions” 标签页。

为了正确地构建、调试和测试项目,搜索下面的扩展并安装它们:

Searching extensions

如果尚未完成,通过单击起始页的 “克隆 Git 存储库Clone Git Repository” 来克隆存储库。

Clone Git repository

或者手动输入:

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

之后,通过输入如下内容来签出标签 ​​devops_1​​:

git checkout tags/devops_1

或者,通过单击 “main” 分支按钮(红色框),并从下拉菜单(黄色框)中选择标签。

Select devops_1 tag

在你打开 VSCodium 内部中的存储库的根文件夹后,CMake Tools 扩展会侦测 ​​CMakeLists.txt​​ 文件并立即扫描你的系统寻找合适的编译器。你现在可以单击屏幕的底部的 “构建Build” 按钮(红色框)来开始构建过程。你也可以通过单击底部区域的按钮(黄色框)标记来更改编译器,它显示当前活动的编译器。

Build compiler

要开始调试 ​​Producer​​ 可执行文件,单击调试器符号(黄色框)并从下拉菜单中选择 “调试Debug Producer”(绿色框)。

Starting the debugger

如上所述,​​Producer​​ 可执行文件要求将元素的数量作为一个命令行的参数。命令行参数可以在 ​​.vscode/launch.json​​ 中具体指定。

Command-line arguments

好了,你现在能够构建和调试项目了。

结束语

归功于 CMake ,不管你正在运行哪种操作系统,上述步骤应该都能工作。特别是使用与 CMake 相关的扩展,VSCodium 变成了一个强大的 IDE 。我没有提及 VSCodium 的 Git 集成,是因为你已经能够在网络上查找很多的资源。我希望你可以看到:提供一个适当的 CMake 配置文件可以使其他人更容易地构建、使用和贡献于你的项目。在未来的文章中,我将介绍单元测试和 CMake 的测试实用程序 ​​ctest​​ 。

责任编辑:庞桂玉 来源: Linux中国
相关推荐

2023-09-05 09:00:00

工具Python抄袭检测系统

2016-09-21 12:54:10

CAAS系统镜像

2018-08-27 17:05:48

tensorflow神经网络图像处理

2023-02-13 14:47:32

人工智能机器学习ChatGPT

2009-04-28 09:44:31

jQueryAjaxphp

2018-11-14 19:00:24

PythonRedis共享单车

2014-02-26 10:14:51

OpenStack测试系统

2021-08-27 12:16:34

fastjarJAR文件Java

2019-10-22 11:42:29

sshuttle虚拟专网Linux

2021-07-14 17:39:46

ReactRails API前端组件

2018-05-25 08:44:22

树莓派PythonMySQL

2023-03-10 13:38:00

Python文档扫描器

2023-09-21 08:00:00

ChatGPT编程工具

2022-07-31 15:46:30

Web自动智能停车

2019-05-14 12:30:07

PythonPygame游戏框架

2018-03-26 11:39:13

LinuxAnsible计算系统

2023-10-31 07:21:05

开源安全工具

2023-12-11 11:56:24

图片服务器Rust

2023-09-15 10:10:05

R 语言

2009-11-11 10:38:11

点赞
收藏

51CTO技术栈公众号