I am trying to setup a CodeQL analysis workflow for my project on Github. I would like to analyze the code for Windows, Ubuntu and MacOS all together and therefore I decided to split the compile-part into three parallel ways, since I have to run the analysis separately for each OS. So far, I set-up the workflow in this way:
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
It works well, but the problem is that in the Windows part, it employs more than 4 hours to complete, since I have to download and build the boost
library every time, in order to correctly compile the code.
Is there a way to speed-up the process?
I already tried with package managers (even if many libraries are not founded on Windows), but the situation doesn't change, or other complications occur: like the fact that I have to find every time the installation of the dependencies and add them to the system path, but since they are not easy to find, I have to re-launch the workflow many and many times to debug.
CodePudding user response:
If downloading and building boost
is the bottleneck, I think you could get a substantial speedup by caching that dependency, especially since its version or contents aren't changing frequently in your CI flow. I've split up your boost
dependency and project build step into 2 different steps and cached the former below. In this case, you're essentially perma-caching your boost dependency since you have the version and its path hard-coded, so the cache key is arbitrary - I just used its path as a string so it's easy to find and replace if you update your boost
version in the future. After cache hit & load, or cache miss and redownload & rebuild, your workflow continues with the rest of the build steps.
- name: Cache boost
if: matrix.os == 'windows-latest'
id: cache-boost
uses: actions/cache@v3
with:
path: C:/boost/include/boost-1_79/boost
key: 'C:/boost/include/boost-1_79/boost' # this key is arbitrary
- name: Installing boost upon cache miss (Windows)
if: matrix.os == 'windows-latest' && steps.cache-boost.outputs.cache-hit != 'true'
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 -
- name: Other build steps
if: matrix.os == 'windows-latest'
run: |
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
I'm not very knowledgeable about C , so if you have other dependencies you're pulling in that are essentially hardcoded by version or path, you could cache those too.
2 caveats to be aware of is that there's a 10GB limit on cached data and there's a 1-week eviction on the cache. If your cache exceeds that size limit, you'll always get a cache miss and thus the cache-miss step will always execute. In this scenario, I think you might be able to compress your boost
directory before caching it (remember to decompress in your final project build step) to try and get below that size limit. actions/cache
uses its own compression already, though, so ymmv with how much this actually helps (maybe try a different compression tool?). In the absolute worst case you could dump your boost
files into blob storage if you have cloud storage somewhere and pull it down, essentially creating your own cache - the latency between GitHub Actions and Azure tends to be pretty low since a lot of the platform infrastructure is hosted there. If you do this, you don't need to split up your build step per se, you'll just need to modify your build step to instead pull down the data from your storage provider.
Sources:
- GitHub Actions cache action: https://github.com/actions/cache
- Combining if conditions: https://docs.github.com/en/actions/learn-github-actions/expressions#operators