“Cross-Compilation” with GitHub Actions

In the not so distant past continuous integration (CI) hadn’t been a thing. Today, when you look into the open source world, GitHub Actions or similar offerings are ubiquitously used and that with good reason, one of which being that it’s free.

GitHub Actions offer a good selection of OS images out-of-the-box, but sometimes you do want to target another OS or distribution without having to maintain your own runner. That’s where the native support for Docker images comes into play, as long as you want to use the same chip architecture as the host system, otherwise QEMU can help to target other architectures.

Fedora / MUSL with Docker

If the architecture (e.g. x64) matches, but you want to target a different distribution, the easiest way is to use a Docker image, which GitHub Actions natively support for the Linux images.

Here is the snippet we use for building CSFML for MUSL (i.e. Alpine) Linux:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
linux-musl-x64:
  name: Linux MUSL x64
  runs-on: ubuntu-22.04
  container:
    image: alpine:3.20.3
 
  steps:
    - name: Checkout CSFML
      uses: actions/checkout@v4
      with:
        path: CSFML
 
    - name: Build
      shell: sh
      run: |
        cd ./CSFML/tools/nuget
        chmod +x ./docker.linux-musl-x64.sh
        ./docker.linux-musl-x64.sh
 
    - name: Upload Artifact
      uses: actions/upload-artifact@v4
      with:
        name: CSFML-linux-musl-x64
        path: CSFML/tools/nuget/CSFML/runtimes

We use Ubuntu as host system, then specify a Alpine Docker image we want to use, and all the steps are automatically executed within the Docker image. The actual build instructions are defined in the docker.linux-musl-x64.sh shell script.

ARM / ARM64 with QEMU

While newer macOS runners are running ARM64 and could be used as native architecture, it’s not (easily?) possible to run Docker images under macOS. GitHub is experimenting with Linux ARM64 images, but that’s still just in testing. For now your best option is emulation through QEMU.

Luckily you don’t have to do everything yourself and instead can use the existing community action uraimo/run-on-arch-action.

Here is the snippet we use for building the CSFML for Linux ARM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
linux-arm:
  name: Linux ARM
  runs-on: ubuntu-22.04
  steps:
    - name: Checkout CSFML
      uses: actions/checkout@v4
      with:
        path: CSFML
    - name: Build in an ARM container
      uses: uraimo/run-on-arch-action@v2.8.1
      with:
        arch: armv7
        distro: ubuntu22.04
        githubToken: ${{ github.token }}
        dockerRunArgs: |
          --volume "${PWD}/CSFML:/CSFML"
        install: |
          apt-get update -y
          apt-get install -y git libfreetype6-dev xorg-dev libxrandr-dev libxcursor-dev libxi-dev libudev-dev libgl1-mesa-dev libflac-dev libogg-dev libvorbis-dev cmake g++
        run: |
          cd /CSFML/tools/nuget
          chmod +x ./build.linux.sh
          ./build.linux.sh linux-arm

We still use Ubuntu as host system, but have to run the specific steps as part of the run-property. For more details on the Run-On-Arch Action, you best check the GitHub repository.

Leave a Comment

Your email address will not be published. Required fields are marked *

 

This site uses Akismet to reduce spam. Learn how your comment data is processed.