如何在 C++ 和 Qt 项目中使用 GitHub Actions

你可能已经在 GitHub 上托管代码了,但你知道吗?GitHub 提供了一个内置的持续集成(CI)解决方案 —— GitHub Actions。它不仅非常容易设置,而且对公共仓库完全免费。
在这篇文章中,我会给你一个速成教程,介绍 什么是 GitHub Actions,以及 如何在你的 C++ 和 Qt 项目中使用它
简而言之
GitHub 自带一个叫做 GitHub Actions 的 CI/自动化系统,它具有以下特点:

  • 通过 .github/workflows 目录下的 YAML 文件 来配置。
  • 可以运行在 GitHub 提供的 云端 Runner 上,也可以运行在 自建服务器(on-prem) 上。
  • 支持在 MacOS、Windows 和 Linux 上运行。
  • 也可以在 容器(containers) 中运行。
  • 对于 公共仓库,云端 Runner 完全 免费;对于 私有仓库,也会提供一定量的免费构建分钟数。
  • 支持把常用的 CI 流程封装成 可复用的组件,并且有一个 官方市场 可以直接获取这些组件:
    https://github.com/marketplace?type=actions
    什么是 GitHub Actions?
    GitHub Actions(下面简称 GHActions)是 GitHub 提供的一个 持续集成(CI)系统
  • 它的配置文件放在仓库的 .github/workflows 文件夹 里。
  • 这个系统非常灵活、可配置(文档见 https://docs.github.com/en/actions)。
  • 每个文件 对应一个 workflow(工作流)
  • 一个工作流可以包含多个 job(任务),这些任务既可以 并行执行,也可以 顺序执行
  • 每个任务包含多个 step(步骤),也就是要执行的实际命令。
  • 工作流通过仓库中发生的 事件(events) 来触发。
    • 事件不一定和代码直接相关,种类很多。
      举个例子:
  • 在仓库里创建一个新的 issue 本身就是一个事件。
  • 你可以编写一个 Action 来监听这个事件,例如:
    • 检查 issue 描述是否包含必要信息;
    • 如果是首次贡献者,可以自动留言欢迎。
      除了事件触发,GitHub Actions 还可以通过 API 从外部触发、手动运行,或者按照 定时任务(cron schedule) 来运行。
      https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows
      重点 takeaway:
      GitHub Actions 不只是用来跑代码测试,它可以 自动化整个仓库里的各种流程 —— 不论是代码构建、测试,还是 issue、PR、文档管理等等。

Actions 在哪里执行?

GitHub Actions 可以在两个地方运行:

  1. GitHub 提供的云端 Runner
    • 这些 Runner 运行在 Azure 上(就像下面例子里那样)。
    • 这是默认和最常见的方式。
  2. 自托管 Runner(Self-hosted runners)
    • 由你自己提供并连接到你的 GitHub 账号的机器。
    • 你可以用自己的服务器、虚拟机、甚至本地电脑来作为 Runner。
    • 具体配置可以参考官方文档 Self-hosted runners
      想了解 GitHub 官方提供的云 Runner 的规格(CPU、内存、预装的软件),可以查阅 官方文档
      无论你用 云端 Runner 还是 自托管 Runner,都有两种执行方式:
  • 直接在 Runner 的操作系统上运行工作流
    (比如 Ubuntu、Windows、macOS 系统本身)。
  • 在 Docker 容器里运行工作流
    文档参考 Running jobs in a container
    理解要点:
  • 默认情况下,Action 是跑在 GitHub 提供的虚拟机上的。
  • 如果你想要更多控制(比如硬件规格、网络环境),就用自托管 Runner。
  • 如果你需要隔离环境(比如测试不同依赖版本),可以把 Job 放到 Docker 容器 里运行。

矩阵 (Matrices)

GitHub Actions 有一个很有趣的功能,类似于其他 CI 系统,就是 矩阵构建
你可以定义一些 轴 (axes),然后 GitHub Actions 会自动根据这些轴的 所有组合 来生成对应的任务 (jobs)。
例如:

jobs:
  example_matrix:
    strategy:
      matrix:
        version: [10, 12, 14]
        os: [ubuntu-latest, windows-latest]

这里定义了两个轴:

  • version:10、12、14
  • os:ubuntu-latest、windows-latest
    GitHub Actions 会自动生成 3 × 2 = 6 个 job,分别对应:
  1. version=10, os=ubuntu-latest
  2. version=10, os=windows-latest
  3. version=12, os=ubuntu-latest
  4. version=12, os=windows-latest
  5. version=14, os=ubuntu-latest
  6. version=14, os=windows-latest
    理解要点
  • 矩阵可以让你同时在多个操作系统、多个编译器版本、多个依赖版本上运行测试。
  • 非常适合 C++ 项目,因为可以同时测试 gcc/clang/msvc,或者不同的 C++ 标准版本 (c++14, c++17, c++20)。
  • 避免手动重复写一堆 Job,减少 YAML 文件的冗余。

可扩展性 (Extensibility)

在 GitHub Actions 里,job 的步骤 (steps) 可以被打包成 可复用的组件,这些组件就叫 actions

  • Action 可以有 输入 (inputs)输出 (outputs)
  • 你可以自己写 自定义 action,它们通常是用 JavaScript 写的。
    使用 action 的方式是通过在步骤里写 uses:
- name: Setup VS
  uses: ilammy/msvc-dev-cmd@v1   # 这是别人写的 action,用来设置 MSVC 环境
- uses: ./.github/actions/setup-rust  # 这是自己仓库里的 action

另外,GitHub 还提供了 workflow 之间的复用
一个工作流可以调用另一个工作流(参考文档:https://docs.github.com/en/actions/using-workflows/reusing-workflows)。
GitHub 官方自己也提供了很多这样的 actions,它们都是单独的小仓库,放在这里:
https://github.com/actions/

理解要点

  1. Actions = 可复用的工作单元,相当于函数/模块。
  2. 你可以用别人写好的 action(从 Marketplace 或 GitHub 找)。
  3. 你也可以写自己的 action(通常 JS/TS 写,也可以用 Docker)。
  4. GitHub 官方提供了很多基础的 action,比如:
    • actions/checkout:拉取代码
    • actions/setup-python:安装 Python
    • actions/setup-node:安装 Node.js
    • actions/setup-go:安装 Go
    • actions/setup-java:安装 JDK
      好的,我来帮你整理这一段成理解版:

示例:在 GitHub Actions 中构建和测试 Qt 项目

作者创建了一个简单的 QML 应用(基本上是 Qt Creator 的模板),并为它配置了 GitHub Actions。仓库地址:
https://github.com/MiKom/QtQuickApp
工作流文件路径:.github/workflows/build.yaml
主要内容如下:

name: CI
on: push  # 当有 push 事件发生时触发工作流
jobs:
  build_and_test:
    name: "Build and test"
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]  # 使用 GitHub 提供的 Linux 和 Windows 镜像构建
    runs-on: ${{ matrix.os }}  # 根据矩阵选择运行系统
    steps:
    - name: Install dependencies (linux)
      run: sudo apt install ninja-build
      if: matrix.os == 'ubuntu-latest'  # 条件执行,仅在 Ubuntu 上运行
    - name: Install Ninja (windows)
      run: choco install ninja  # Windows 上安装 Ninja
      if: matrix.os == 'windows-latest'
    - name: Install Qt
      uses: jurplel/install-qt-action@v3
      with:
        version: '6.5.2'  # 安装指定版本的 Qt
    - uses: ilammy/msvc-dev-cmd@v1  # Windows 下配置 MSVC 编译环境
    - uses: actions/checkout@v3  # 拉取源代码
    - name: Build
      run: cmake -S . -B build -G "Ninja Multi-Config" && cmake --build build --config Debug

理解要点

  1. 触发条件
    • on: push 表示每次代码 push 时触发工作流。
  2. 矩阵构建 (Matrix Build)
    • strategy.matrix 定义了操作系统维度:Ubuntu 和 Windows。
    • 使用 ${{ matrix.os }} 自动在不同系统上运行相同的 job。
  3. 条件步骤
    • if: matrix.os == 'ubuntu-latest':只有在 Ubuntu 上安装 Linux 依赖。
    • if: matrix.os == 'windows-latest':只有在 Windows 上安装 Windows 依赖(通过 Chocolatey 安装 Ninja)。
  4. 安装 Qt
    • 使用社区提供的 action:jurplel/install-qt-action@v3
    • 可配置 Qt 版本,例如 '6.5.2'
    • 该 action 会自动设置 Qt 的环境变量,无需手动配置。
  5. MSVC 配置(Windows)
    • ilammy/msvc-dev-cmd@v1:调用 vcvarsall.bat,设置 Windows 编译环境。
  6. 拉取代码
    • actions/checkout@v3 用于将仓库源代码拉到 runner 上。
  7. 构建项目
    • 使用 CMake 和 Ninja 构建:
      cmake -S . -B build -G "Ninja Multi-Config"
      cmake --build build --config Debug
      

总结

  • 这个工作流展示了 跨平台构建 的示例(Linux + Windows)。
  • 利用了 矩阵策略 (matrix strategy),可以在不同环境自动生成 job。
  • 通过 社区提供的 action,轻松安装 Qt 和配置环境。
  • 条件步骤 (if) 可以让不同系统执行不同命令。
  • 构建步骤最后使用 CMake + Ninja 执行编译。
    注意,在这个工作流中,作者使用了 社区提供的 action 来安装 Qt(jurplel/install-qt-action@v3)。
  • 更多信息可参考 GitHub Marketplace 页面:
    https://github.com/marketplace/actions/install-qt
  • 如果你需要为自己的 Qt 项目生成相应的配置,可以使用这个工具:
    https://ddalcino.github.io/aqt-list-server/
    运行该工作流后,你可以在 仓库顶部的 “Actions” 标签页 查看执行结果,包括 workflow 的运行状态和每个 job 的状态。
    总结要点:
  1. 社区 action 可以方便地安装和配置 Qt,无需手动设置环境变量。
  2. 配置生成工具 可以帮助生成适合自己项目的 Qt 安装参数。
  3. 查看执行结果 可以通过 GitHub 的 Actions 页面实时监控 workflow 运行情况。

一个完整的 Qt 项目 GitHub Actions 示例,包含从创建项目到推送 GitHub 并运行 CI 的步骤。

1⃣ 创建一个简单 Qt 项目

假设你使用 Qt Creator 创建一个 Qt Quick 应用程序
MyQtApp/
├── main.cpp
├── main.qml
├── CMakeLists.txt
└── .gitignore

**示例 main.cpp:**
```cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[]) {
  QGuiApplication app(argc, argv);
  QQmlApplicationEngine engine;
  engine.load(QUrl(QStringLiteral("qrc:/MyQtApp/main.qml")));
  if (engine.rootObjects().isEmpty())
    return -1;
  return app.exec();
}

示例 main.qml:

import QtQuick 2.15
import QtQuick.Window 2.15
Window {
    visible: true
    width: 400
    height: 300
    title: "Hello Qt"
    Rectangle {
        anchors.fill: parent
        color: "lightblue"
        Text {
            anchors.centerIn: parent
            text: "Hello GitHub Actions with CMake!"
            font.pointSize: 20
        }
    }
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.21)
project(MyQtApp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 查找 Qt6 模块
find_package(Qt6 COMPONENTS Core Quick Qml REQUIRED)
# Qt 标准项目设置(自动处理头文件路径、MOC、RCC、UIC)
qt_standard_project_setup()
# 可执行文件
qt_add_executable(MyQtApp
    main.cpp
)
# 添加 QML 模块
qt_add_qml_module(MyQtApp
    URI MyQtApp# 属于模块MyQtApp/下面 qrc:/MyQtApp/main.qml
    VERSION 1.0
    QML_FILES main.qml
)
include(GNUInstallDirs)
# 链接 Qt 库(Qt6::Core/Quick/Qml 都包含)
target_link_libraries(MyQtApp
    PRIVATE Qt6::Core
            Qt6::Quick
            Qt6::Qml
)

2⃣ 创建 Git 仓库并推送到 GitHub

  1. 初始化 Git 仓库:
cd MyQtApp
git init
git add .
git commit -m "Initial commit"
  1. 在 GitHub 创建一个新仓库,例如 MyQtApp
  2. 将本地仓库关联到远程:
git remote add origin https://github.com/<your-username>/MyQtApp.git
git branch -M main
git push -u origin main

3⃣ 配置 GitHub Actions Workflow

在项目根目录下创建 .github/workflows/build.yml 文件:

name: CI
on: push # 触发时机,这里设置为每次 push 时触发
jobs:
  build_and_test:
    name: "构建与测试"
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest] # 在 GitHub 提供的 Linux 和 Windows 镜像上构建
    runs-on: ${{ matrix.os }} # 使用矩阵中的操作系统
    steps:
    - name: 安装依赖(Linux)
      run: sudo apt install ninja-build
      if: matrix.os == 'ubuntu-latest' # 条件执行,仅在 Ubuntu 运行器上运行此步骤
    - name: 安装 Ninja(Windows)    # Ninja 在 GitHub 提供的镜像中不可用
      run: choco install ninja         # 所以通过 Chocolatey 安装
      if: matrix.os == 'windows-latest'
    - name: 安装 Qt
      uses: jurplel/install-qt-action@v4
      with:
        version: '6.5.2'  # 安装 Qt 版本
    - uses: ilammy/msvc-dev-cmd@v1 # 该操作相当于调用 vcvarsall.bat,为运行器配置最新 VS x64 环境
    - uses: actions/checkout@v4    # 实际检出源码。GH Actions 可在不需要源码的事件触发,但这里需要
    # 手动调用 CMake 构建项目,也可以使用 Marketplace 上的 CMake Action
    - name: 构建
      # 不需要设置环境变量让 CMake 找到 Qt,因为 install-qt-action 会自动配置
      run: cmake -S . -B build -G "Ninja Multi-Config" && cmake --build build --config Debug

4⃣ 推送 Workflow 到 GitHub

git add .github/workflows/build.yml
git commit -m "Add GitHub Actions CI workflow"
git push

5⃣ 查看 Workflow 运行情况

  1. 打开 GitHub 仓库 → 点击 Actions 标签页
  2. 你会看到 CI workflow 正在运行
  3. 点击 workflow 运行记录,可以查看每个 Job 和 Step 的状态
    • Ubuntu Job
    • Windows Job

总结

添加打包下载

name: CI
on: push # 触发时机,这里设置为每次 push 时触发
jobs:
  build_and_test:
    name: "构建与测试"
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest] # 在 GitHub 提供的 Linux 和 Windows 镜像上构建
    runs-on: ${{ matrix.os }} # 使用矩阵中的操作系统
    steps:
    - name: 安装依赖(Linux)
      run: sudo apt install ninja-build
      if: matrix.os == 'ubuntu-latest' # 条件执行,仅在 Ubuntu 运行器上运行此步骤
    - name: 安装 Ninja(Windows)    # Ninja 在 GitHub 提供的镜像中不可用
      run: choco install ninja         # 所以通过 Chocolatey 安装
      if: matrix.os == 'windows-latest'
    - name: 安装 Qt
      uses: jurplel/install-qt-action@v4
      with:
        version: '6.5.2'  # 安装 Qt 版本
    - uses: ilammy/msvc-dev-cmd@v1 # 该操作相当于调用 vcvarsall.bat,为运行器配置最新 VS x64 环境
    - uses: actions/checkout@v4    # 实际检出源码。GH Actions 可在不需要源码的事件触发,但这里需要
# 这里我们手动调用CMake
    - name: 配置构建
      run: cmake -S . -B build -G "Ninja Multi-Config"
    - name: 构建 Release 版本
      run: cmake --build build --config Release
    - name: 测试(可选)
      run: cmake --build build --target test --config Release
      continue-on-error: true  # 如果没有测试,不会导致构建失败
    # 打包应用程序
    - name: 打包应用程序 (Linux)
      if: matrix.os == 'ubuntu-latest'
      run: |
        mkdir -p MyQtApp-linux
        cp build/Release/MyQtApp MyQtApp-linux/
        # 创建启动脚本
        echo '#!/bin/bash' > MyQtApp-linux/run.sh
        echo 'cd "$(dirname "$0")"' >> MyQtApp-linux/run.sh
        echo './MyQtApp' >> MyQtApp-linux/run.sh
        chmod +x MyQtApp-linux/run.sh
        tar -czf MyQtApp-linux-x64.tar.gz MyQtApp-linux/
    # 打包应用程序(Windows)
    - name: 打包应用程序 (Windows)
      if: matrix.os == 'windows-latest'
      run: |
        mkdir MyQtApp-windows
        cp build/Release/MyQtApp.exe MyQtApp-windows/
        # 使用windeployqt部署Qt依赖
        windeployqt.exe --release --qmldir . MyQtApp-windows/MyQtApp.exe
        # 创建压缩包
        7z a MyQtApp-windows-x64.zip MyQtApp-windows/*
      shell: bash
    # 上传构建产物
    - name: 上传构建产物 (Linux)
      if: matrix.os == 'ubuntu-latest'
      uses: actions/upload-artifact@v4
      with:
        name: MyQtApp-linux-x64
        path: MyQtApp-linux-x64.tar.gz
        retention-days: 30
    - name: 上传构建产物 (Windows)
      if: matrix.os == 'windows-latest'
      uses: actions/upload-artifact@v4
      with:
        name: MyQtApp-windows-x64
        path: MyQtApp-windows-x64.zip
        retention-days: 30
  # 创建GitHub Release(仅在推送标签时)
  release:
    name: "Create Release"
    needs: build_and_test
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/')  # 仅在推送tag时运行
    steps:
    - name: 下载所有构建产物
      uses: actions/download-artifact@v4
    - name: 创建 Release
      uses: softprops/action-gh-release@v2
      with:
        files: |
          MyQtApp-linux-x64/*.tar.gz
          MyQtApp-windows-x64/*.zip
        generate_release_notes: true
        draft: false
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

在这里插入图片描述

上传构建产物的地方有一个链接可以直接下载

https://github.com/xiaqiu-xz/QtQuickApp/actions/runs/17004758498/artifacts/3778803197

  1. GitHub Actions 是闭源的云服务
    • 由于 GitHub 是 SaaS(软件即服务)公司提供的闭源平台,一些人可能不希望完全依赖这个生态系统。
    • 这是对“供应商锁定”(vendor lock-in)的担忧:你用上了 GitHub Actions,就很难迁移到其他平台。
  2. 开源替代方案:Act
    • Act 是 GitHub Actions 的开源本地实现,可以让你在本地运行工作流(workflow),无需依赖 GitHub 云服务。
    • Gitea(一个开源 Git 托管平台)正在集成 Act 的一个 fork,让你在 Gitea 上也能运行类似 GitHub Actions 的工作流。
    • 因为它与 GitHub Actions 源码兼容,如果你的 workflow 使用的是 Gitea 支持的特性子集,那么迁移会比较简单。
  3. GitHub Actions 功能丰富
    • 除了 CI(持续集成),还支持部署、密钥管理、环境变量、缓存、制品存储和共享等功能。
    • 官方文档有详细说明:https://docs.github.com/en/actions
  4. 学习资源
    • 可以参考已经在使用 GitHub Actions 的项目,比如 Slint,看看实际工作流怎么写。
    • 新建 action 时,还可以选择很多模板作为起点。
  5. 总结
    • GitHub Actions 是一个灵活、现代化的 CI 系统,可以满足大部分自动化构建、测试、部署需求。
    • 但缺点是它闭源,会带来一定的供应商锁定风险。
    • Gitea Actions(基于 Act 的实现)可能在未来提供开源替代方案,减轻对 GitHub 的依赖。
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐