Skip to main content

Overview

Csound uses GitHub Actions for continuous integration and deployment. The CI/CD pipeline automatically builds, tests, and packages Csound for multiple platforms on every push and pull request.

Workflows

The CI/CD system consists of multiple workflow files in .github/workflows/:

csound_builds.yml

Main build and test workflow for all platforms. Triggers:
  • Push to master or develop branches
  • Pull requests to develop branch
Jobs:
  • Linux builds (apt-get, vcpkg)
  • macOS builds (Homebrew, installer, vcpkg)
  • Windows builds (MSVC 64/32-bit, MinGW)
  • iOS builds (native, cross-compilation)
  • Android builds
  • WebAssembly builds
  • ARM bare-metal builds

csound_wasm.yml

WebAssembly-specific workflow using Nix. Triggers:
  • Pull requests to any branch
  • Push to develop branch
Jobs:
  • Compile WebAssembly binaries
  • Browser bundle build and test
  • ESLint checks
  • Browser unit tests

csound_build_images.yml

Builds Docker images for cross-compilation toolchains.

Platform builds

Linux builds

Ubuntu with apt-get

Builds using system-installed dependencies:
- name: Install Dependencies
  run: |
    sudo apt-get update
    sudo apt-get install cmake libgtest-dev libsndfile1-dev \
      libasound2-dev libjack-dev portaudio19-dev libportmidi-dev \
      libpulse-dev swig liblua5.1-0-dev default-jdk liblo-dev \
      ladspa-sdk dssi-dev bison flex gettext libsamplerate0-dev \
      libpipewire-0.3-dev

- name: Configure build
  run: |
    mkdir build && cd build
    cmake .. -DUSE_MP3=0 -DUSE_DOUBLE=0 -DBUILD_TESTS=1 \
      -DBUILD_STATIC_LIBRARY=1

- name: Build Csound
  run: cd build && make

- name: Run tests
  run: |
    cd build
    make test
    make csdtests

Ubuntu with vcpkg

Builds using vcpkg for dependency management:
- name: Bootstrap VCPKG
  run: ./vcpkg/bootstrap-vcpkg.sh

- name: Configure Build
  run: |
    cmake -B build -S . -DBUILD_TESTS=1 -DUSE_VCPKG=1 \
      -DCUSTOM_CMAKE="./platform/linux/custom.cmake" \
      -DBUILD_PLUGINS=1

- name: Build Csound
  run: cmake --build build --config Release

- name: Run tests
  run: cmake --build build --target test csdtests

macOS builds

Homebrew build

Development build using Homebrew dependencies:
- name: Install dependencies
  run: |
    brew install libogg flac lame libvorbis mpg123 opus \
      libsndfile portaudio libsamplerate liblo portmidi
    brew install bison flex jack googletest

- name: Configure build
  run: |
    cmake -B build \
      -DCUSTOM_CMAKE="./platform/osx/custom-osx.cmake"

- name: Build Csound
  run: cmake --build build --config Debug

- name: Run tests
  run: cmake --build build --target csdtests test

Installer build

Production build with all dependencies included:
- name: Build dependencies
  run: |
    cd platform/osx
    chmod +x build_libsndfile.sh
    ./build_libsndfile.sh
    # Build portmidi, portaudio, libsamplerate, liblo...

- name: Configure Csound
  run: |
    cmake -B build -DCMAKE_BUILD_TYPE="Release" \
      -DUSE_GETTEXT=0 \
      -DCMAKE_PREFIX_PATH="$PWD/platform/osx/libsndfile_build/dependencies;..." \
      -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" \
      -DUSE_MP3=1 -DUSE_STATIC_DEPS=1

- name: Build installer
  run: pkgbuild --identifier com.csound.csound7Environment.csoundLib64 ...
The installer is a universal binary supporting both Intel and Apple Silicon.

Windows builds

MSVC 64-bit

- name: Install dependencies
  run: choco install -y winflexbison3 innosetup

- name: Bootstrap VCPKG
  run: .\vcpkg\bootstrap-vcpkg.bat

- name: Configure build
  run: |
    cmake -B build -S . -DBUILD_TESTS=1 -DUSE_VCPKG=1 \
      -DCUSTOM_CMAKE="./platform/windows/Custom-vs.cmake"

- name: Build Csound
  run: cmake --build build --config Release

- name: Run tests
  run: |
    cmake --build build --target csdtests
    cmake --build build --target RUN_TESTS --config Release

- name: Build installer
  run: iscc /o. installer\windows\csound7_x64_github.iss

MSVC 32-bit

Similar to 64-bit but with -A Win32 flag:
- name: Configure build
  run: |
    cmake -B build -S . -A Win32 -DBUILD_TESTS=1 \
      -DUSE_VCPKG=1 \
      -DCUSTOM_CMAKE="./platform/windows/Custom-vs-x86.cmake"

MinGW cross-compilation

Builds Windows binaries on Linux using MinGW:
- name: Install dependencies
  run: |
    sudo apt-get install mingw-w64-x86-64-dev gcc-mingw-w64 \
      g++-mingw-w64 mingw-w64-tools wine

- name: Use posix mingw
  run: |
    sudo update-alternatives --set x86_64-w64-mingw32-gcc \
      /usr/bin/x86_64-w64-mingw32-gcc-posix

- name: Configure Build
  run: |
    cmake -B build -S . -DBUILD_TESTS=1 -DUSE_VCPKG=1 \
      -DCUSTOM_CMAKE="./platform/mingw64-linux/Custom.cmake" \
      -DCMAKE_SYSTEM_NAME=MinGW

- name: Build Csound
  run: cmake --build build --config Release

iOS builds

Native iOS build

Builds on macOS using Xcode:
- name: Install dependencies
  run: brew install bison flex

- name: Build libsndfile xcframework
  working-directory: iOS
  run: |
    chmod +x build_libsndfile.sh
    ./build_libsndfile.sh

- name: Build Csound iOS xcframework
  working-directory: iOS
  run: ./build.sh

iOS cross-compilation

Cross-compiles iOS binaries on Linux using Docker:
- name: Configure Build
  run: |
    docker run --rm \
      -v "${{ github.workspace }}:${{ github.workspace }}" \
      --workdir "${{ github.workspace }}" \
      ghcr.io/${{ github.repository_owner }}/csound-ioscross:v1 \
      /bin/sh -lc '
        $(eval /ioscross/arm64/ioscross_conf.sh)
        cmake -B build/arm64 -S . -DUSE_VCPKG=1 \
          -DCUSTOM_CMAKE=./platform/ioscross/custom-ios.cmake \
          -DIOS=1 -DCMAKE_OSX_ARCHITECTURES=arm64
      '

Android builds

NDK build (macOS)

- name: Download NDK
  working-directory: Android
  run: sh downloadNDK.sh

- name: Download Dependencies
  working-directory: Android
  run: |
    export NDK_MODULE_PATH=$PWD/modules
    sh downloadDependencies.sh

- name: Build CsoundAndroid
  working-directory: Android
  run: |
    export ANDROID_NDK_ROOT="$PWD/AndroidNDK.app/Contents/NDK"
    cd CsoundAndroid
    sh build.sh

vcpkg cross-compilation

Builds for multiple Android architectures:
- name: Configure Build
  run: |
    docker run --rm ... \
      /bin/sh -lc '
        for ARCH in arm arm64 x86 x64; do
          cmake -B build/$ARCH -S . -DUSE_VCPKG=1 \
            -DCUSTOM_CMAKE=./platform/android/custom-android.cmake \
            -DCMAKE_SYSTEM_NAME=Android \
            -DCMAKE_TARGET_ARCHITECTURE=${ARCH}
        done
      '

WebAssembly builds

Emscripten build

- name: Set up Emscripten
  uses: mymindstorm/setup-emsdk@v14
  with:
    version: 3.1.64
    actions-cache-folder: emsdk-cache

- name: Configure Build
  run: |
    cmake -B build -S . -DUSE_VCPKG=1 \
      -DCUSTOM_CMAKE="./platform/wasm/Custom-wasm.cmake" \
      -DCMAKE_SYSTEM_NAME=Emscripten \
      -DEMSDK=$EMSDK -DEMSDK_NODE=$EMSDK_NODE

- name: Build Csound
  run: cmake --build build --config Release

Nix-based WebAssembly

Alternative WebAssembly build using Nix:
- uses: cachix/install-nix-action@v25
- uses: cachix/cachix-action@v15
  with:
    name: csound
    authToken: ${{ secrets.CACHIX_TOKEN }}

- name: Compile wasm binaries
  run: cd wasm && yarn build

- name: Run browser tests
  run: |
    cd wasm/browser
    yarn && yarn build:prod
    yarn test:ci

ARM bare-metal build

Builds for embedded ARM Cortex-M7:
- name: Install dependencies
  run: |
    brew update
    brew install --cask gcc-arm-embedded
    brew install bison flex

- name: Configure build
  run: |
    cmake -B build \
      -DCMAKE_INSTALL_PREFIX="$PWD/Daisy" \
      -DCUSTOM_CMAKE="$PWD/Daisy/Custom.cmake" \
      -DCMAKE_TOOLCHAIN_FILE="$PWD/Daisy/crosscompile.cmake"

- name: Build Csound
  run: cmake --build build --config Release

Testing in CI

Unit tests

Run on Linux, macOS, and Windows:
- name: Run tests
  run: make test  # or: cmake --build build --target test

Integration tests

Run CSD tests on all platforms:
- name: Run integration tests
  run: make csdtests  # or: cmake --build build --target csdtests

WebAssembly browser tests

- name: Run unit tests with Chrome
  run: |
    cd wasm/browser
    nix-shell --pure
    yarn test:ci

- name: Publish Test Report
  uses: mikepenz/action-junit-report@v4
  with:
    report_paths: "**/tests/*.junit.xml"

Artifact generation

Upload artifacts

CI builds create artifacts for distribution:
- uses: actions/upload-artifact@v4
  with:
    name: Csound_x64-${{env.CSOUND_VERSION}}-windows-installer
    path: ./Csound7-windows_x86_64-*.exe

Artifact types

  • Windows: .exe installers, .dll binaries
  • macOS: .pkg installer with universal binary
  • iOS: XCFramework zip
  • Android: AAR packages
  • ARM: Bare-metal libraries and examples
  • WebAssembly: JavaScript bundles

Release process

Version management

update_version:
  runs-on: ubuntu-latest
  outputs:
    version: ${{ steps.tag.outputs.new_tag }}
  steps:
    - uses: anothrNick/github-tag-action@1.36.0
      env:
        PRERELEASE: true
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        DRY_RUN: true

Publish release

Publishes artifacts when a PR has the release label:
publish_artifacts:
  if: |
    github.ref == 'refs/heads/develop' && 
    needs.update_version.outputs.release == 'true'
  needs:
    - update_version
    - windows_build
    - macos_build_installer
    - iOS_build
    - android-release
  steps:
    - name: Download artifacts
      uses: actions/download-artifact@v4
      # ...
    
    - name: Create Release
      uses: softprops/action-gh-release@v2
      with:
        tag_name: ${{ env.CSOUND_VERSION }}
        generate_release_notes: true
        files: |
          csound-windows-*.zip
          csound-macos-*.zip
          csound-ios-*.zip
          csound-android-*.zip

Caching

vcpkg caching

vcpkg binary cache is stored in GitHub Actions cache:
env:
  VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"

- name: Export GitHub Actions cache environment variables
  uses: actions/github-script@v6
  with:
    script: |
      core.exportVariable('ACTIONS_CACHE_URL', 
        process.env.ACTIONS_CACHE_URL || '');
      core.exportVariable('ACTIONS_RUNTIME_TOKEN', 
        process.env.ACTIONS_RUNTIME_TOKEN || '');

Emscripten caching

- uses: mymindstorm/setup-emsdk@v14
  with:
    version: 3.1.64
    actions-cache-folder: emsdk-cache

Nix caching

- uses: cachix/cachix-action@v15
  with:
    name: csound
    authToken: ${{ secrets.CACHIX_TOKEN }}

Concurrency control

Prevents multiple builds from the same ref:
concurrency:
  group: ${{ github.ref }}

Docker images

Cross-compilation toolchain images:
  • csound-android - Android NDK and toolchain
  • csound-ioscross - iOS cross-compilation tools
  • csound-osxcross - macOS cross-compilation tools
These images are built by csound_build_images.yml and hosted on GitHub Container Registry.

Workflow optimization

Parallel jobs

Jobs run in parallel where possible:
jobs:
  linux_build:
    # ...
  macos_build:
    # ...
  windows_build:
    # ...

Conditional execution

Some jobs only run on develop:
if: github.ref == 'refs/heads/develop'

Job dependencies

Some jobs depend on others:
publish_artifacts:
  needs:
    - update_version
    - windows_build
    - macos_build_installer

Debugging CI failures

View logs

Check the Actions tab on GitHub for detailed logs.

Run locally

Use act to run GitHub Actions locally:
act -j linux_build

Enable debug logging

Add --verbose or -v flags to commands in the workflow.

SSH into runner

Use action-tmate for interactive debugging (not enabled by default).

Best practices

Fast feedback

  • Run quick tests first (Linux builds)
  • Run expensive tests in parallel (installers)
  • Cache dependencies aggressively

Reliability

  • Pin action versions: uses: actions/checkout@v5
  • Use matrix builds for multiple configurations
  • Set appropriate timeouts

Security

  • Use secrets for tokens: ${{ secrets.GITHUB_TOKEN }}
  • Minimize permissions
  • Validate inputs

Maintainability

  • Keep workflows DRY (Don’t Repeat Yourself)
  • Use reusable workflows and composite actions
  • Document complex logic