GitHub上vcpkg相关CI流程过慢,寻求优化方案
优化C++项目GitHub自托管CI流程:解决vcpkg缓存失效与耗时过长问题
一、先解决vcpkg二进制缓存失效的核心问题
你的配置里手动设置VCPKG_BINARY_SOURCES和环境变量,与lukka/run-vcpkg@v11的内置缓存逻辑冲突,这大概率是缓存未生效的原因。lukka的action已封装GitHub缓存集成,无需手动配置冗余步骤,调整如下:
替换原vcpkg相关步骤
删除原有的「Export GitHub Actions cache environment variables」「Set vcpkg binary sources」「Install vcpkg」「Install dependencies from vcpkg.json」四个步骤,替换为:
- name: Run vcpkg with binary caching uses: lukka/run-vcpkg@v11 with: vcpkgArguments: '--triplet x64-linux' # 用自托管runner本地固定路径存储vcpkg,避免每次重新下载安装 vcpkgDirectory: '/opt/vcpkg' vcpkgJsonPath: '${{ github.workspace }}/vcpkg.json' # 基于vcpkg.json内容和triplet生成缓存key,确保依赖变更才更新缓存 cacheKey: ${{ hashFiles('vcpkg.json') }}-x64-linux # 明确启用二进制缓存 binaryCaching: true
额外检查点
- 确保自托管runner有权限访问GitHub Actions缓存:检查runner网络配置,确认能正常连接GitHub缓存服务
- 锁定vcpkg依赖版本:
vcpkg.json里的依赖若使用>=x.y.z这类浮动版本,每次拉取的依赖版本不同会导致缓存失效,改为固定版本号 - 统一triplet:所有CI任务必须使用完全一致的triplet(如
x64-linux),缓存key与triplet强绑定
二、CMake配置耗时优化
你每次用${github.run_id}生成全新build目录,导致CMake每次都要重新检测环境、生成配置,完全没有复用性。调整方案:
复用CMake build目录
用配置文件的哈希值作为build目录后缀,只要CMakeLists.txt和vcpkg.json未修改,就复用之前的build目录:
- name: Configure CMake run: | # 基于配置文件哈希生成稳定的build目录名 BUILD_HASH=$(echo "${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}" | cut -c1-10) BUILD_DIR="${{ vars.SHARED_BUILD_DIR }}/build-${BUILD_HASH}" mkdir -p $BUILD_DIR cmake -B $BUILD_DIR \ -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DENABLE_CUDA=ON \ -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc # 缓存CMake配置和编译中间产物 cache: path: | ${{ vars.SHARED_BUILD_DIR }}/build-* key: cmake-${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}-x64-linux
启用ccache加速编译
在自托管runner上安装ccache,然后在CMake配置时启用,缓存编译产物:
- name: Configure CMake with ccache run: | BUILD_HASH=$(echo "${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}" | cut -c1-10) BUILD_DIR="${{ vars.SHARED_BUILD_DIR }}/build-${BUILD_HASH}" mkdir -p $BUILD_DIR cmake -B $BUILD_DIR \ -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DENABLE_CUDA=ON \ -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache env: CCACHE_DIR: "${{ vars.SHARED_BUILD_DIR }}/ccache" cache: path: | ${{ vars.SHARED_BUILD_DIR }}/build-* ${{ vars.SHARED_BUILD_DIR }}/ccache key: cmake-${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}-x64-linux
三、解决自托管runner排队问题
- 增加runner数量:直接部署多台自托管runner,并行处理3-4个任务,彻底解决排队等待问题
- 预安装基础环境:在自托管runner上提前安装好CMake、vcpkg、CUDA等基础工具,避免CI每次都重新安装(如把CMake装在
/opt/cmake,vcpkg装在/opt/vcpkg)
四、其他细节优化
- 并行测试:给
ctest加--parallel $(nproc)参数,利用runner的多核并行执行测试用例 - 条件触发步骤:用
if判断配置文件是否变更,跳过不必要的步骤,比如:- name: Run vcpkg with binary caching uses: lukka/run-vcpkg@v11 if: hashFiles('vcpkg.json') != steps.cache-vcpkg.outputs.cache-hit # ... 其他参数 - 清理磁盘空间:定期清理自托管runner的临时文件和旧缓存,避免磁盘IO瓶颈导致的性能下降
修改后的完整build.yml示例
name: Build and Test on: workflow_call: jobs: build: runs-on: self-hosted steps: - uses: actions/checkout@v3 - name: Setup CMake uses: jwlawson/actions-setup-cmake@v1.14 with: cmake-version: '3.27.1' cache: true - name: Run vcpkg with binary caching uses: lukka/run-vcpkg@v11 with: vcpkgArguments: '--triplet x64-linux' vcpkgDirectory: '/opt/vcpkg' vcpkgJsonPath: '${{ github.workspace }}/vcpkg.json' cacheKey: ${{ hashFiles('vcpkg.json') }}-x64-linux binaryCaching: true - name: Configure CMake with ccache run: | BUILD_HASH=$(echo "${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}" | cut -c1-10) BUILD_DIR="${{ vars.SHARED_BUILD_DIR }}/build-${BUILD_HASH}" mkdir -p $BUILD_DIR cmake -B $BUILD_DIR \ -DCMAKE_TOOLCHAIN_FILE=/opt/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DENABLE_CUDA=ON \ -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc \ -DCMAKE_C_COMPILER_LAUNCHER=ccache \ -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache env: CCACHE_DIR: "${{ vars.SHARED_BUILD_DIR }}/ccache" cache: path: | ${{ vars.SHARED_BUILD_DIR }}/build-* ${{ vars.SHARED_BUILD_DIR }}/ccache key: cmake-${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}-x64-linux - name: Build run: | BUILD_HASH=$(echo "${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}" | cut -c1-10) BUILD_DIR="${{ vars.SHARED_BUILD_DIR }}/build-${BUILD_HASH}" cmake --build $BUILD_DIR --parallel $(nproc) - name: Test run: | BUILD_HASH=$(echo "${{ hashFiles('CMakeLists.txt', 'vcpkg.json') }}" | cut -c1-10) BUILD_DIR="${{ vars.SHARED_BUILD_DIR }}/build-${BUILD_HASH}" ctest -C Release --output-on-failure --test-dir $BUILD_DIR --parallel $(nproc)
内容的提问来源于stack exchange,提问作者Ayman
相关产品推荐
相关产品推荐

