引言:当“在我机器上能编译”成为灾难
每位C++开发者至少都听过这样一句话:“我这边一切正常,奇怪你的怎么运行不了。”或者自己也说过。模板编译、链接、不同标准(C++17、C++20)的特性、平台相关的宏——C++充满了在环境切换时才会暴露的意外问题。
CI/CD流水线(持续集成/持续部署)对于C++来说不是奢侈品,而是必需品。它能自动构建项目、运行测试、检查代码质量,并在成功后部署应用程序到服务器(或发布库)。在本文中,我们将使用GitHub Actions、CMake和C++从零开始配置一个完整的流水线。您将获得一个可直接用于您项目的现成配置。
1. 项目准备:结构与构建系统
在编写流水线之前,需要先整理好项目。我们将使用CMake——现代C++项目的事实标准。我们的示例将是一个简单的字符串处理工具,并包含基于Google Test的单元测试。
仓库结构
my_cpp_project/├── .github/│ └── workflows/│ └── ci.yml # 流水线配置文件├── src/│ ├── main.cpp│ └── string_utils.cpp├── include/│ └── string_utils.hpp├── tests/│ ├── CMakeLists.txt│ └── test_string_utils.cpp├── CMakeLists.txt # 根CMake文件├── Dockerfile # 用于最终部署└── README.md根CMakeLists.txt
构建库和可执行文件。注意测试的导出:
cmake_minimum_required(VERSION 3.20)project(MyStringUtils VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 主库add_library(string_utils STATIC src/string_utils.cpp include/string_utils.hpp)target_include_directories(string_utils PUBLIC include)
# 可执行文件add_executable(my_app src/main.cpp)target_link_libraries(my_app PRIVATE string_utils)
# 测试(可选,通过选项启用)option(BUILD_TESTS "Build unit tests" ON)if(BUILD_TESTS) enable_testing() add_subdirectory(tests)endif()测试示例(tests/test_string_utils.cpp)
#include <gtest/gtest.h>#include "string_utils.hpp"
TEST(StringUtilsTest, ToUpper) { EXPECT_EQ(to_upper("hello"), "HELLO"); EXPECT_EQ(to_upper("C++20"), "C++20");}
TEST(StringUtilsTest, Trim) { EXPECT_EQ(trim(" spaced "), "spaced"); EXPECT_EQ(trim("\\t\\r"), "");}项目准备就绪后,我们进入正题——配置C++的CI/CD流水线。
2. GitHub Actions:编写第一个流水线
GitHub Actions是开源项目中最流行的CI/CD工具。其配置使用YAML编写,存放在.github/workflows文件夹中。让我们创建ci.yml文件。
基本结构:在推送和PR时触发
name: C++ CI/CD Pipeline
on: push: branches: [ main, develop ] pull_request: branches: [ main ]
jobs: build-and-test: runs-on: ubuntu-latest
steps: - name: Checkout code uses: actions/checkout@v4
- name: Install dependencies run: | sudo apt-get update sudo apt-get install -y cmake g++ libgtest-dev
- name: Configure CMake run: cmake -B build -DCMAKE_BUILD_TYPE=Release
- name: Build run: cmake --build build --parallel $(nproc)
- name: Run tests run: cd build && ctest --output-on-failure这是一个最小但可用的C++ CI/CD流水线。如果测试失败,流水线将报错终止,您会收到通知。但我们还会更进一步