Build and test a multiplatform C++ project with GitHub Actions

Hai Luong - Aug 26 - - Dev Community

In this tutorial, I will give you the instruction how I set up CI/CD to build and test my C++ multiplatform game engine named NeoSekaiEngine with GitHub Actions.

Note: The original post is at LinkedIn: Link here

Oh wait! What is NeoSekaiEngine?

NeoSekaiEngine is my 2D game engine built base on what I know about game development. This game engine is written in C++ and can run on Windows, Linux and Web platform.

Here the link for the repository if you are interested. Link

Let get started

First at all, set thing up by creating a file named build_test.yaml in the folder .github/workflows

Checkout the code

In the build_test.yaml file, we configure it to clone the source code first.

name: Build and Test Engine
run-name: ${{ github.ref }} on ${{ github.repository }} is being built and tested out Github actions
on: [ push ]
jobs:
  Build-Engine:
    runs-on: ubuntu-latest
    steps:
      - run: echo "The job was automatically triggered by a ${{ github.event_name }} event."
      - name: Check out the repository code
        uses: actions/checkout@v4
      - run: echo "The ${{ github.repository }} repository has been cloned to the runner."
      - name: Check repository
        run: ls ${{ github.workspace }}

Enter fullscreen mode Exit fullscreen mode

Let see what inside here

  • name: The name of the workflow.
  • run-name: The name for workflow runs generated from the workflow.
  • on: It defines which event can causes workflow runs. In this file, workflow run when you push your code.
  • jobs: This sections is defined the jobs of the workflow.
  • runs-on: The platform the the workflow runs on.
  • steps: The instructions to executing the job

And here is the result.

Summary for checking out the code

Build Engine jobs for checking out the code

Install the dependencies

Because at that moment, I built for single platform(Ubuntu). Let's install dependencies.

name: Build and Test Engine
run-name: ${{ github.ref }} on ${{ github.repository }} is being built and tested out Github actions
on: [ push ]
jobs:
  Build-Engine:
    runs-on: ubuntu-latest
    steps:
      - run: echo "The job was automatically triggered by a ${{ github.event_name }} event."
      - name: Check out the repository code
        uses: actions/checkout@v4
      - name: setup library
        run: /bin/bash ./scripts/pre-installer/linux/debian/preinstaller.sh 
Enter fullscreen mode Exit fullscreen mode

And here is the result.

Summary for installing dependencies

Build Engine job for installing dependencies

Build and run test

It seemed like everything good. Let build and run test.

name: Build and Test Engine
run-name: ${{ github.ref }} on ${{ github.repository }} is being built and tested out Github actions
on: [ push ]
jobs:
  Build-Engine:
    runs-on: ubuntu-latest
    steps:
      - run: echo "The job was automatically triggered by a ${{ github.event_name }} event."
      - name: Check out the repository code
        uses: actions/checkout@v4
      - name: setup library
        run: /bin/bash ./scripts/pre-installer/linux/debian/preinstaller.sh
      - name: build project with test for static lib
        run: cmake -S ./ -B ./build -DRUN_TEST=1 -DBUILD_SHARED_LIBS=0 && cmake --build ./build 
      - name: run test
        run: build/out/engine_test --gtest_output="xml:build/test-results.xml"
Enter fullscreen mode Exit fullscreen mode

Here is the result.

Summary of building and testing

Build Engine job for building and testing

Create artifacts

After running test, we need something to get the result and storing into artifacts is a good idea. By using actions/upload-artifact@v4, you can store file in artifacts.

name: Build and Test Engine
run-name: ${{ github.ref }} on ${{ github.repository }} is being built and tested out Github actions
on: [ push ]
jobs:
  Build-Engine:
    runs-on: ubuntu-latest
    steps:
      - run: echo "The job was automatically triggered by a ${{ github.event_name }} event."
      - name: Check out the repository code
        uses: actions/checkout@v4
      - name: setup library
        run: /bin/bash ./scripts/pre-installer/linux/debian/preinstaller.sh
      - name: build project with test for static lib
        run: cmake -S ./ -B ./build -DRUN_TEST=1 -DBUILD_SHARED_LIBS=0 && cmake --build ./build 
      - name: run test
        run: build/out/engine_test --gtest_output="xml:build/test-results.xml"
      - name: Upload test result
        uses: actions/upload-artifact@v4
        with:
          name: test-results-ubuntu-static.xml
          path: build/test-results.xml
Enter fullscreen mode Exit fullscreen mode

And here is the result

Build Engine job for creating artifacts

Run workflows for multiplatform

After completing a workflow for a single platform, let make it for multiple one.

name: Build and Test Engine
run-name: ${{ github.ref }} on ${{ github.repository }} is being built and tested out Github actions
on: [ push ]
jobs:
  Build-Engine:
    strategy:
      fail-fast: false
      matrix:
        build_shared: [0, 1]
        os: [ubuntu-latest, windows-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - run: echo "The job was automatically triggered by a ${{ github.event_name }} event."
      - name: Check out the repository code
        uses: actions/checkout@v4
      - name: setup library
        if: ${{ matrix.os != 'windows-latest' }}
        run: /bin/bash ./scripts/pre-installer/linux/debian/preinstaller.sh
      - name: build project with test for BUILD_SHARED_LIBS=${{ matrix.build_shared }}
        run: cmake -S ./ -B ./build -DRUN_TEST=1 -DBUILD_SHARED_LIBS=${{ matrix.build_shared }} && cmake --build ./build 
      - name: run test
        if: ${{ matrix.os != 'windows-latest' }}
        run: build/out/engine_test --gtest_output="xml:build/test-results.xml"
      - name: run test
        if: ${{ matrix.os == 'windows-latest' }}
        run: .\build\out\Debug\engine_test.exe --gtest_output="xml:build/test-results.xml"
      - name: Upload test result
        if: ${{ matrix.build_shared == 0 }}
        uses: actions/upload-artifact@v4
        with:
          name: test-results-${{matrix.os}}-static.xml
          path: build/test-results.xml

      - name: Upload test result
        if: ${{ matrix.build_shared == 1 }}
        uses: actions/upload-artifact@v4
        with:
          name: test-results-${{matrix.os}}-shared.xml
          path: build/test-results.xml
Enter fullscreen mode Exit fullscreen mode

Here we can see something new named matrix. This is a strategy on GitHub Actions that helps you use variables in a single job definition to automatically create multiple job runs that are based on the combinations of the variables.

Here is the result

Summary of building for multiplatform

Inconclusion

Here is all the instructions how I built and test my multiplatform project using GitHub Actions. Hope you learn something from it.

See you in next article.

.
Terabox Video Player