Add AU (AudioUnit) plugin format support #27
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build | |
| on: | |
| push: | |
| branches: [master, main] | |
| tags: ['v*'] | |
| pull_request: | |
| workflow_dispatch: | |
| # Cancel superseded PR builds. Leave branch/tag builds alone so releases | |
| # don't get killed by a follow-up commit. | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| build: | |
| name: ${{ matrix.name }} | |
| runs-on: ${{ matrix.runs-on }} | |
| defaults: | |
| run: | |
| shell: ${{ matrix.shell }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # JACK standalone is Linux-only on purpose: | |
| # * Windows: practically no end users run a JACK server | |
| # (most use ASIO/WASAPI through their DAW directly), and | |
| # enabling it would require pulling jack2 through MSYS2. | |
| # * macOS: same situation — JACK is rare on Mac desktops, | |
| # and Homebrew jack is not installed by default. | |
| # LV2 and VST2 are the plugin formats people actually load | |
| # into Reaper/Bitwig/Ardour/etc., and those build everywhere. | |
| - name: linux-x86_64 | |
| runs-on: ubuntu-24.04 | |
| shell: bash | |
| lib-ext: .so | |
| jack: 'true' | |
| jack-ext: '' | |
| - name: linux-aarch64 | |
| # Free arm64 Linux runner (4 vCPU on public repos since | |
| # Jan 2025). The native compile is straightforward because | |
| # the build now has a non-x86 path that produces a single | |
| # scalar DSPCore_Generic with no VCL / no -mavxN flags. | |
| runs-on: ubuntu-24.04-arm | |
| shell: bash | |
| lib-ext: .so | |
| jack: 'true' | |
| jack-ext: '' | |
| - name: macos-x86_64 | |
| # macos-15-intel is the only free Intel runner since GitHub | |
| # retired macos-13 in December 2025. Apple is discontinuing | |
| # x86_64 macOS support entirely after macos-15 retires in | |
| # Fall 2027 — at that point this matrix row should be removed. | |
| runs-on: macos-15-intel | |
| shell: bash | |
| lib-ext: .dylib | |
| jack: 'false' | |
| jack-ext: '' | |
| - name: macos-aarch64 | |
| # Apple Silicon. macos-15 is the default Apple Silicon label | |
| # and is free for public repos. Same scalar build as Linux | |
| # aarch64 — DSPCore_Generic only, no SSE/AVX dispatch. | |
| runs-on: macos-15 | |
| shell: bash | |
| lib-ext: .dylib | |
| jack: 'false' | |
| jack-ext: '' | |
| - name: windows-x86_64 | |
| runs-on: windows-latest | |
| # MSYS2 MinGW64 is the standard environment for building | |
| # DPF plugins on Windows. setup-msys2 (below) provisions it. | |
| shell: 'msys2 {0}' | |
| lib-ext: .dll | |
| jack: 'false' | |
| jack-ext: .exe | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| # --- Per-OS dependency setup --- | |
| - name: Install dependencies (Linux) | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| pkg-config libgl-dev libx11-dev libjack-jackd2-dev lilv-utils | |
| - name: Install dependencies (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| # Xcode CLI tools and the macOS SDK are pre-installed. | |
| # DPF on macOS uses Cocoa and CoreAudio — no JACK or X11. | |
| true | |
| - name: Install dependencies (Windows / MSYS2) | |
| if: runner.os == 'Windows' | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: MINGW64 | |
| update: true | |
| install: >- | |
| base-devel | |
| mingw-w64-x86_64-gcc | |
| mingw-w64-x86_64-pkgconf | |
| zip | |
| - name: Set up ccache | |
| uses: hendrikmuhs/ccache-action@v1.2 | |
| with: | |
| key: ${{ matrix.name }}-${{ github.ref }} | |
| restore-keys: ${{ matrix.name }}- | |
| # --- Build --- | |
| - name: Patch bundled DPF and build | |
| working-directory: plugin/dpf | |
| run: | | |
| export PATH="/usr/lib/ccache:$PATH" | |
| make patch | |
| # nproc works on Linux and MSYS2; macOS needs sysctl. | |
| if command -v nproc >/dev/null 2>&1; then | |
| JOBS=$(nproc) | |
| else | |
| JOBS=$(sysctl -n hw.ncpu) | |
| fi | |
| make -j"$JOBS" JACK=${{ matrix.jack }} LV2=true VST2=true VST3=true CLAP=true AU=true | |
| # --- Stage artifacts into a portable on-disk layout --- | |
| - name: Stage artifacts (Unix layout) | |
| if: runner.os != 'Windows' | |
| # GNU coreutils' `install -D` auto-creates the destination's | |
| # parent directories; BSD install on macOS doesn't have -D and | |
| # then can't write its temp file into a non-existent directory | |
| # (you get a cryptic "install: .../INS@XXXXX: No such file or | |
| # directory" failure). Use `mkdir -p` + plain `cp` instead — | |
| # `cp` preserves modes, and the build emits sensible permissions | |
| # already, so we don't need an explicit chmod. | |
| # | |
| # The Makefile emits VST2 as a bare DigiDrie-vst.so on Linux and | |
| # as a DigiDrie.vst/ bundle on macOS (matching upstream DPF), so | |
| # the VST2 staging step differs by OS. LV2 is a directory bundle | |
| # on both, copied recursively. | |
| run: | | |
| STAGE="staging/DigiDrie-${{ matrix.name }}" | |
| mkdir -p "$STAGE/bin" "$STAGE/lib/vst" "$STAGE/lib/vst3" \ | |
| "$STAGE/lib/lv2" "$STAGE/lib/clap" "$STAGE/share/magnetophon" | |
| if [ "${{ matrix.jack }}" = "true" ]; then | |
| cp "plugin/dpf/bin/DigiDrie${{ matrix.jack-ext }}" "$STAGE/bin/" | |
| fi | |
| # VST2 is a bundle dir on macOS, single .so on Linux. CLAP is the | |
| # same shape: bundle dir on macOS, single .clap on Linux. VST3 is | |
| # always a bundle directory on every platform (the binary's parent | |
| # path varies by OS — Contents/<arch>-linux/, Contents/MacOS/, etc. | |
| # — but the .vst3 top-level is always a directory). AU is | |
| # macOS-only and always a .component bundle directory. | |
| if [ "$RUNNER_OS" = "macOS" ]; then | |
| mkdir -p "$STAGE/lib/au" | |
| cp -r plugin/dpf/bin/DigiDrie.vst "$STAGE/lib/vst/" | |
| cp -r plugin/dpf/bin/DigiDrie.clap "$STAGE/lib/clap/" | |
| cp -r plugin/dpf/bin/DigiDrie.component "$STAGE/lib/au/" | |
| else | |
| cp "plugin/dpf/bin/DigiDrie-vst${{ matrix.lib-ext }}" "$STAGE/lib/vst/" | |
| cp plugin/dpf/bin/DigiDrie.clap "$STAGE/lib/clap/" | |
| fi | |
| cp -r plugin/dpf/bin/DigiDrie.vst3 "$STAGE/lib/vst3/" | |
| cp -r plugin/dpf/bin/DigiDrie.lv2 "$STAGE/lib/lv2/" | |
| cp README.md LICENSE.txt "$STAGE/" | |
| cp -r plugin/dpf/style "$STAGE/share/magnetophon/" | |
| # --- macOS: ad-hoc codesign the VST2 bundle --- | |
| # | |
| # The Makefile builds DigiDrie.vst with the correct Contents/MacOS, | |
| # Info.plist, PkgInfo, and Resources/empty.lproj layout already; we | |
| # just need an ad-hoc signature so Gatekeeper and hosts with | |
| # hardened-runtime checks accept the bundle. Users still need | |
| # `xattr -dr com.apple.quarantine` after downloading because the | |
| # signature is ad-hoc (not Developer ID), but without any signature | |
| # the bundle would be rejected outright on recent macOS regardless. | |
| - name: Codesign VST2 + VST3 + CLAP + AU bundles (macOS) | |
| if: runner.os == 'macOS' | |
| run: | | |
| STAGE="staging/DigiDrie-${{ matrix.name }}" | |
| for bundle in "$STAGE/lib/vst/DigiDrie.vst" \ | |
| "$STAGE/lib/vst3/DigiDrie.vst3" \ | |
| "$STAGE/lib/clap/DigiDrie.clap" \ | |
| "$STAGE/lib/au/DigiDrie.component"; do | |
| codesign --force --sign - "$bundle" | |
| test -f "$bundle/Contents/MacOS/DigiDrie" | |
| codesign --verify --strict --verbose=2 "$bundle" | |
| done | |
| - name: Stage artifacts (Windows layout) | |
| if: runner.os == 'Windows' | |
| # Windows users expect a flat directory rather than FHS-style | |
| # bin/lib/share. Put plugin and resources next to each other. | |
| # No JACK standalone — see the matrix comment above. | |
| run: | | |
| STAGE="staging/DigiDrie-${{ matrix.name }}" | |
| mkdir -p "$STAGE" | |
| cp plugin/dpf/bin/DigiDrie-vst.dll "$STAGE/" | |
| cp plugin/dpf/bin/DigiDrie.clap "$STAGE/" | |
| cp -r plugin/dpf/bin/DigiDrie.vst3 "$STAGE/" | |
| cp -r plugin/dpf/bin/DigiDrie.lv2 "$STAGE/" | |
| cp README.md LICENSE.txt "$STAGE/" | |
| cp -r plugin/dpf/style "$STAGE/" | |
| # --- Sanity check the LV2 bundle (Linux only; lilv is most | |
| # readily available there and the bundle format is OS-agnostic). --- | |
| - name: Verify LV2 bundle is discoverable | |
| if: runner.os == 'Linux' | |
| run: | | |
| STAGE="$PWD/staging/DigiDrie-${{ matrix.name }}" | |
| LV2_PATH="$STAGE/lib/lv2" lv2ls | |
| LV2_PATH="$STAGE/lib/lv2" \ | |
| lv2info https://github.com/magnetophon/DigiDrie | head -20 | |
| # --- Upload artifacts --- | |
| # | |
| # Upload the unpacked staging directory rather than a pre-built | |
| # archive. `actions/upload-artifact@v4` always wraps its payload in a | |
| # zip when served via the web UI / `gh run download` — so uploading a | |
| # .tar.gz would force people to extract twice (zip → tar.gz → dir), | |
| # and uploading a .zip would force a zip-of-zip. Uploading the | |
| # directory makes that wrap-zip act as the archive itself, so CI | |
| # consumers get a single archive containing the FHS-style layout | |
| # directly. | |
| # | |
| # Trade-off: upload-artifact normalises file permissions to 644/755 | |
| # (files / dirs), which strips +x from the JACK standalone binary on | |
| # Linux. The plugin shared libraries (.so/.dylib/.dll) and the macOS | |
| # .vst bundle binary at Contents/MacOS/<name> don't need +x — dlopen | |
| # on glibc and dyld on macOS both load loadable bundles by content, | |
| # not by mode. So only `bin/DigiDrie` is affected. The release job | |
| # restores +x on `bin/*` before tagged-release re-archiving; CI users | |
| # poking at the standalone for testing can `chmod +x bin/DigiDrie` | |
| # themselves after extracting. | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: DigiDrie-${{ matrix.name }} | |
| path: staging/DigiDrie-${{ matrix.name }}/ | |
| if-no-files-found: error | |
| release: | |
| name: release | |
| needs: build | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| # No merge-multiple: each artifact stays in its own subdir | |
| # (artifacts/DigiDrie-linux-x86_64/, artifacts/DigiDrie-macos-aarch64/, | |
| # etc.) so we can re-archive each one separately. | |
| # Build job uploads the unpacked staging directory, so we re-archive | |
| # here in the platform-conventional format for the GitHub release | |
| # page: tar.gz on Unix (preserves perms via the chmod step below), | |
| # zip on Windows. Picking the format from the artifact name keeps | |
| # this loop matrix-free — adding a new matrix row only requires the | |
| # name to contain "windows" if it should ship a zip. | |
| - name: Re-archive for release | |
| run: | | |
| mkdir -p release | |
| for dir in artifacts/DigiDrie-*/; do | |
| base=$(basename "$dir") # e.g. DigiDrie-linux-x86_64 | |
| suffix=${base#DigiDrie-} # e.g. linux-x86_64 | |
| out="DigiDrie-${GITHUB_REF_NAME}-${suffix}" | |
| # upload-artifact strips file modes; restore +x on any | |
| # standalone binary in bin/. The .vst bundle binary on macOS | |
| # (lib/vst/*.vst/Contents/MacOS/*) doesn't need +x — dyld | |
| # loads it via dlopen — but chmod-ing it is harmless and | |
| # arguably more correct, so do that too. | |
| if [ -d "$dir/bin" ]; then | |
| find "$dir/bin" -type f -exec chmod +x {} + | |
| fi | |
| find "$dir" -path '*.vst/Contents/MacOS/*' -type f \ | |
| -exec chmod +x {} + 2>/dev/null || true | |
| case "$base" in | |
| *windows*) | |
| (cd artifacts && zip -qr "../release/${out}.zip" "$base") | |
| ;; | |
| *) | |
| tar -czf "release/${out}.tar.gz" -C artifacts "$base" | |
| ;; | |
| esac | |
| done | |
| ls -la release/ | |
| - name: Publish release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: release/DigiDrie-* | |
| draft: false | |
| generate_release_notes: true |