Even with modern C++, you can easily shoot yourself in the famous foot. Adding static code analysis is a good way of locating some otherwise hard-to-find bugs. Luckily, open-source repositories in GitHub has access to static code analysis tool CodeQL for free, and it even supports C++. There is good documentation available, but here I will explain how to add CodeQL to your C++ project:

First of all, GitHub Advanced Security has to be enabled. (For open-source (public) repositories, it should already be enabled)

To set up the CodeQL workflow, go to the repository Settings, Security&Analysis, click the Code Scanning "Set up"-button (If Code Scanning is not available, make sure GitHub Advanced Security mentioned above is enabled), and finally click CodeQL Analysis "Set up this workflow"-button. This will generate a new file ".github/workflows/codeql-analysis.yml" and open it in online editor.

The default name ("CodeQL") and the "on:"-block can be kept as-is. The "on:"-block will say that analysis should be run on all push to main branch, all pull requests to main branch and at one fixed-random time during week (I got "26 4 * * 3", which means it will run at 04:26 third day of week)

For "jobs: analyze:", name, runs-on and permissions can (must?) be kept as-is. Under "strategy:", make sure language is set to cpp.

And now we are at the actual steps of this workflow. The default workflow wants to check out your git repository, initialize CodeQL, try to autobuild your repository and finally perform the CodeQL analysis. Most likely, this is not enough for your C++ project: You may have dependencies that can be apt-get installed into the Ubuntu image, you may have dependencies that needs to be compiled from source, you may have some specific way of triggering your build and you may have other stuff you do in your build pipeline. Here are how to prepare dependencies and build your project manually:


apt-get install dependencies:

The code scanning image is a bare bone Ubuntu image. Any tools (like git for checking out code, cmake for building or doxygen for generating documentation) or development headers (like libboost-dev) that is in the pre-built Ubuntu repository can be directly installed into the code scanning image with a step like this: 

    - name: Install dependencies
      run: sudo apt-get -y install git cmake doxygen libboost-dev


build dependencies from source (or anything else you would do from commandline) :

The code scanning image is pulled clean each time, and destroyed when the scanning is done. Think of it as a brand new computer, where you need to install or build dependencies before you can build your actual project. It is up to you how you want to organize directories and stuff. I usually just put stuff in user home directory (after all, the image is destroyed immediately after running code analysis..). This example step will change directory to user home directory, clone a public git repository, change directory to it, execute its documented steps for build and install, and finally update the system dynamic linker run-time bindings so your project can find it.

    - name: Install Paho C client
      run: cd && git clone https://github.com/eclipse/paho.mqtt.c.git && cd paho.mqtt.c && cmake -Bbuild -H. -DPAHO_ENABLE_TESTING=OFF -DPAHO_BUILD_STATIC=ON -DPAHO_WITH_SSL=ON -DPAHO_HIGH_PERFORMANCE=ON && sudo cmake --build build/ --target install && sudo ldconfig


Manually build your project:

If the provided autobuild step fails, or you want to have full control of the build step, you can add your own build step. Here is a typical Makefile build step

    - name: Compile project
      run: make && make install


Wrapping everything up. A complete example codeql-analysis.yml file (also available for download)

name: "CodeQL"

    branches: [ main ]
    # The branches below must be a subset of the branches above
    branches: [ main ]
    - cron: '26 4 * * 3'

    name: Analyze
    runs-on: ubuntu-latest
      actions: read
      contents: read
      security-events: write

      fail-fast: false
        language: [ 'cpp' ]

      - name: Initialize CodeQL
        uses: github/codeql-action/init@v1
          languages: ${{ matrix.language }}

      - name: Install dependencies
        run: sudo apt-get install libboost-dev libpoco-dev libwxbase3.0-dev libfmt-dev git cmake doxygen

      - name: Install Paho C client
        run: cd && git clone https://github.com/eclipse/paho.mqtt.c.git && cd paho.mqtt.c && cmake -Bbuild -H. -DPAHO_ENABLE_TESTING=OFF -DPAHO_BUILD_STATIC=ON -DPAHO_WITH_SSL=ON -DPAHO_HIGH_PERFORMANCE=ON && sudo cmake --build build/ --target install && sudo ldconfig

      - name: Install Paho C++ client
        run: cd && git clone https://github.com/eclipse/paho.mqtt.cpp.git && cd paho.mqtt.cpp && cmake -Bbuild -H. -DPAHO_WITH_SSL=ON -DPAHO_BUILD_DOCUMENTATION=TRUE && sudo cmake --build build/ --target install && sudo ldconfig

      - name: Checkout repository
        uses: actions/checkout@v2

      - name: Compile project
        run: make && make install

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v1


Finding the CodeQL logs

After having committed the workflow, you will find workflow logs under your Git repository Actions|Workflows|CodeQL. You can also see CodeQL alerts under Git repository Security|Code Scanning Alerts|Code Scanning Alerts|View Alerts.