GitHub Actions中Windows C++项目CodeQL编译过慢如何解决?
问题描述
我正在GitHub上为个人项目搭建CodeQL分析工作流,需要同时覆盖Windows、Ubuntu、MacOS三个平台的代码检测。由于各操作系统需要独立运行分析流程,我将编译环节拆分为三个并行任务执行,当前工作流配置如下:
name: "CodeQL" on: push: branches: [ main ] pull_request: branches: [ main ] schedule: - cron: '45 22 * * 0' jobs: analyze: name: Analyze runs-on: ${{ matrix.os }} permissions: actions: read contents: read security-events: write strategy: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] language: [ 'cpp' ] steps: - name: Checkout repository uses: actions/checkout@v2 - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - name: Installing extra dependencies and compiling (Ubuntu) if: matrix.os == 'ubuntu-latest' run: | sudo apt install build-essential g++ libboost-all-dev wget unzip doctest-dev exprtk_sha1=ca5c577917646ddba3f71ce6d5dd7d01f351ee80 wget https://github.com/ArashPartow/exprtk/archive/$exprtk_sha1.zip mv $exprtk_sha1.zip exprtk-$exprtk_sha1.zip unzip exprtk-$exprtk_sha1.zip sudo cp exprtk-$exprtk_sha1/exprtk.hpp /usr/include/ rm -rf exprtk-* make - name: Installing extra dependencies and compiling (MacOS) if: matrix.os == 'macos-latest' run: | brew install boost doctest exprtk_sha1=ca5c577917646ddba3f71ce6d5dd7d01f351ee80 wget https://github.com/ArashPartow/exprtk/archive/$exprtk_sha1.zip mv $exprtk_sha1.zip exprtk-$exprtk_sha1.zip unzip exprtk-$exprtk_sha1.zip sudo cp exprtk-$exprtk_sha1/exprtk.hpp /usr/local/include rm -rf exprtk-* make - name: Installing extra dependencies and compiling (Windows) if: matrix.os == 'windows-latest' run: | choco install unzip wget mkdir C:/install cd C:/install wget https://boostorg.jfrog.io/artifactory/main/release/1.79.0/source/boost_1_79_0.zip | Out-Null unzip boost_1_79_0.zip | Out-Null mkdir C:/boost-build mkdir C:/install/boost_1_79_0/boost-build mkdir C:/boost cd - cd C:/install/boost_1_79_0/tools/build .\bootstrap.bat gcc .\b2 --prefix="C:/boost-build" install $Env:PATH+=";C:/boost-build/bin" cd - cd C:/install/boost_1_79_0 b2 --build-dir="C:/install/boost_1_79_0/build" --build-type=complete --prefix="C:/boost" toolset=gcc install cd - cp -r C:/boost/include/boost-1_79/boost C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++ cp C:/boost/lib/* C:/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib $Env:PATH+=";C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++" $Env:PATH+=";C:/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib" $Env:PATH+=";C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++" $Env:PATH+=";C:/mingw810/x86_64-810-posix-seh-rt_v6-rev0/mingw64/opt/lib" rd -r C:/install rd -r C:/boost-build wget https://github.com/doctest/doctest/archive/refs/heads/master.zip | Out-Null unzip master.zip | Out-Null mkdir C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/doctest cp doctest-master/doctest/doctest.h C:/ProgramData/Chocolatey/lib/mingw/tools/install/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/doctest rd -r doctest-master make - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2
该配置目前可正常运行,但存在严重的效率问题:Windows平台的任务耗时超过4小时,原因是每次运行工作流都需要重新下载并编译boost库才能完成项目代码编译。
我已经尝试过使用包管理器安装依赖,但Windows平台下很多依赖库无法通过包管理器获取,耗时问题没有得到改善,还引发了其他问题:例如每次运行都需要定位依赖的安装路径并添加到系统PATH中,由于路径查找难度大,我需要多次重复启动工作流进行调试。请问是否有可行的方法可以加快该流程的运行速度?
可行优化方案
- 优先用工作流缓存复用预编译依赖
把固定版本的boost、doctest等第三方依赖编译完成后,直接通过工作流缓存能力存储,后续运行只要依赖版本、编译器版本不变,直接命中缓存拉取现成的依赖文件,完全跳过下载、编译步骤,Windows任务耗时可以直接从4小时压缩到15分钟以内。
不要把依赖往MinGW的系统目录里拷贝,自己建个固定路径比如C:\dev\deps存所有第三方依赖,每次任务启动直接把这个路径下的include、lib目录加到环境变量里,一次配置完成后不用反复找路径调试。 - 砍掉boost的无效编译工作量
你现在编译boost用了--build-type=complete参数,会编译所有模块的全量构建变体,包括debug、release、静态库、动态库、不同运行时版本的组合,至少90%的产物你的项目根本用不上。把参数改成只编译你项目实际引用的boost模块,比如只用了filesystem、system模块就加--with-filesystem --with-system参数,编译时间直接能砍九成以上。 - 直接使用预编译好的boost包
不用每次从源码编译boost,提前把对应MinGW版本编译好的boost压缩包准备好,跑工作流的时候直接下载解压到固定路径就行,连编译步骤都省了,整个依赖准备过程几十秒就能完成。 - 固定所有依赖的路径配置
不要用相对路径、不要猜包管理器的默认安装路径,所有依赖的安装路径、include路径、lib路径都写死成你自定义的固定值,一次调试通之后就不用反复修改,也不用每次启动工作流排查路径问题。 - 精简CodeQL的构建范围
CodeQL只需要分析你项目本身的代码,不需要扫描第三方依赖,编译的时候只保留你项目需要的单种构建配置(比如只编译debug版或者只编译release版),不需要编译多套构建产物,进一步减少编译耗时。
内容的提问来源于stack exchange,提问作者Gianluca Bianco
相关产品推荐
相关产品推荐

