WIP: multi-platform builds pipeline
This commit is contained in:
5
.cargo/config.toml
Normal file
5
.cargo/config.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
[alias]
|
||||
xtask = "run --package xtask --release --"
|
||||
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
rustflags = ["-C", "link-args=-lstdc++ -lws2_32 -liphlpapi -lwinmm"]
|
||||
248
.github/workflows/ci.yml
vendored
248
.github/workflows/ci.yml
vendored
@@ -1,9 +1,8 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags: ['v*']
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
@@ -15,26 +14,20 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: x86_64-unknown-linux-gnu
|
||||
artifact: cagire-linux-x86_64
|
||||
- os: macos-15-intel
|
||||
target: x86_64-apple-darwin
|
||||
artifact: cagire-macos-x86_64
|
||||
- os: macos-14
|
||||
target: aarch64-apple-darwin
|
||||
artifact: cagire-macos-aarch64
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
artifact: cagire-windows-x86_64
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
timeout-minutes: 20
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -45,6 +38,7 @@ jobs:
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
components: clippy
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
@@ -57,13 +51,10 @@ jobs:
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential cmake pkg-config libasound2-dev libclang-dev libjack-dev \
|
||||
libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libgl1-mesa-dev
|
||||
cargo install cargo-bundle
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew list cmake &>/dev/null || brew install cmake
|
||||
cargo install cargo-bundle
|
||||
run: brew list cmake &>/dev/null || brew install cmake
|
||||
|
||||
- name: Install dependencies (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
@@ -77,229 +68,8 @@ jobs:
|
||||
- name: Build desktop
|
||||
run: cargo build --release --features desktop --bin cagire-desktop --target ${{ matrix.target }}
|
||||
|
||||
- name: Bundle desktop app
|
||||
if: runner.os != 'Windows'
|
||||
run: cargo bundle --release --features desktop --bin cagire-desktop --target ${{ matrix.target }}
|
||||
- name: Test
|
||||
run: cargo test --target ${{ matrix.target }}
|
||||
|
||||
- name: Bundle CLAP plugin
|
||||
run: cargo xtask bundle cagire-plugins --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Zip macOS app bundle
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cd target/${{ matrix.target }}/release/bundle/osx
|
||||
zip -r Cagire.app.zip Cagire.app
|
||||
|
||||
- name: Upload artifact (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: target/${{ matrix.target }}/release/cagire
|
||||
|
||||
- name: Upload artifact (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: target/${{ matrix.target }}/release/cagire.exe
|
||||
|
||||
- name: Upload desktop artifact (Linux deb)
|
||||
if: runner.os == 'Linux'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
|
||||
- name: Upload desktop artifact (macOS app bundle)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/bundle/osx/Cagire.app.zip
|
||||
|
||||
- name: Upload desktop artifact (Windows exe)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/cagire-desktop.exe
|
||||
|
||||
- name: Upload CLAP artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-clap
|
||||
path: target/bundled/cagire-plugins.clap
|
||||
|
||||
- name: Upload VST3 artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-vst3
|
||||
path: target/bundled/cagire-plugins.vst3
|
||||
|
||||
universal-macos:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: macos-14
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Download macOS artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: cagire-macos-*
|
||||
path: artifacts
|
||||
|
||||
- name: Create universal CLI binary
|
||||
run: |
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64/cagire \
|
||||
artifacts/cagire-macos-aarch64/cagire \
|
||||
-output cagire
|
||||
chmod +x cagire
|
||||
lipo -info cagire
|
||||
|
||||
- name: Create universal app bundle
|
||||
run: |
|
||||
cd artifacts/cagire-macos-aarch64-desktop
|
||||
unzip Cagire.app.zip
|
||||
cd ../cagire-macos-x86_64-desktop
|
||||
unzip Cagire.app.zip
|
||||
cd ../..
|
||||
cp -R artifacts/cagire-macos-aarch64-desktop/Cagire.app Cagire.app
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64-desktop/Cagire.app/Contents/MacOS/cagire-desktop \
|
||||
artifacts/cagire-macos-aarch64-desktop/Cagire.app/Contents/MacOS/cagire-desktop \
|
||||
-output Cagire.app/Contents/MacOS/cagire-desktop
|
||||
lipo -info Cagire.app/Contents/MacOS/cagire-desktop
|
||||
zip -r Cagire.app.zip Cagire.app
|
||||
|
||||
- name: Create universal CLAP plugin
|
||||
run: |
|
||||
mkdir -p cagire-plugins.clap/Contents/MacOS
|
||||
cp artifacts/cagire-macos-aarch64-clap/cagire-plugins.clap/Contents/Info.plist \
|
||||
cagire-plugins.clap/Contents/ 2>/dev/null || true
|
||||
cp artifacts/cagire-macos-aarch64-clap/cagire-plugins.clap/Contents/PkgInfo \
|
||||
cagire-plugins.clap/Contents/ 2>/dev/null || true
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64-clap/cagire-plugins.clap/Contents/MacOS/cagire-plugins \
|
||||
artifacts/cagire-macos-aarch64-clap/cagire-plugins.clap/Contents/MacOS/cagire-plugins \
|
||||
-output cagire-plugins.clap/Contents/MacOS/cagire-plugins
|
||||
lipo -info cagire-plugins.clap/Contents/MacOS/cagire-plugins
|
||||
|
||||
- name: Create universal VST3 plugin
|
||||
run: |
|
||||
mkdir -p cagire-plugins.vst3/Contents/MacOS
|
||||
cp -R artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/Info.plist \
|
||||
cagire-plugins.vst3/Contents/ 2>/dev/null || true
|
||||
cp artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/PkgInfo \
|
||||
cagire-plugins.vst3/Contents/ 2>/dev/null || true
|
||||
cp -R artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/Resources \
|
||||
cagire-plugins.vst3/Contents/ 2>/dev/null || true
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64-vst3/cagire-plugins.vst3/Contents/MacOS/cagire-plugins \
|
||||
artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/MacOS/cagire-plugins \
|
||||
-output cagire-plugins.vst3/Contents/MacOS/cagire-plugins
|
||||
lipo -info cagire-plugins.vst3/Contents/MacOS/cagire-plugins
|
||||
|
||||
- name: Build .pkg installer
|
||||
run: |
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
mkdir -p pkg-root/Applications pkg-root/usr/local/bin
|
||||
cp -R Cagire.app pkg-root/Applications/
|
||||
cp cagire pkg-root/usr/local/bin/
|
||||
pkgbuild --analyze --root pkg-root component.plist
|
||||
plutil -replace BundleIsRelocatable -bool NO component.plist
|
||||
pkgbuild --root pkg-root --identifier com.sova.cagire \
|
||||
--version "$VERSION" --install-location / \
|
||||
--component-plist component.plist \
|
||||
"Cagire-${VERSION}-universal.pkg"
|
||||
|
||||
- name: Upload universal CLI
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal
|
||||
path: cagire
|
||||
|
||||
- name: Upload universal app bundle
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-desktop
|
||||
path: Cagire.app.zip
|
||||
|
||||
- name: Upload universal CLAP plugin
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-clap
|
||||
path: cagire-plugins.clap
|
||||
|
||||
- name: Upload universal VST3 plugin
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-vst3
|
||||
path: cagire-plugins.vst3
|
||||
|
||||
- name: Upload .pkg installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-pkg
|
||||
path: Cagire-*-universal.pkg
|
||||
|
||||
release:
|
||||
needs: [build, universal-macos]
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Prepare release files
|
||||
run: |
|
||||
mkdir -p release
|
||||
for dir in artifacts/*/; do
|
||||
name=$(basename "$dir")
|
||||
if [[ "$name" == "cagire-macos-universal-pkg" ]]; then
|
||||
cp "$dir"/*.pkg release/
|
||||
elif [[ "$name" == "cagire-macos-universal-desktop" ]]; then
|
||||
cp "$dir/Cagire.app.zip" "release/cagire-macos-universal-desktop.app.zip"
|
||||
elif [[ "$name" == "cagire-macos-universal" ]]; then
|
||||
cp "$dir/cagire" "release/cagire-macos-universal"
|
||||
elif [[ "$name" == "cagire-macos-universal-clap" ]]; then
|
||||
cd "$dir" && zip -r "../../release/cagire-macos-universal-clap.zip" cagire-plugins.clap && cd ../..
|
||||
elif [[ "$name" == "cagire-macos-universal-vst3" ]]; then
|
||||
cd "$dir" && zip -r "../../release/cagire-macos-universal-vst3.zip" cagire-plugins.vst3 && cd ../..
|
||||
elif [[ "$name" == *-clap ]]; then
|
||||
base="${name%-clap}"
|
||||
cd "$dir" && zip -r "../../release/${base}-clap.zip" cagire-plugins.clap && cd ../..
|
||||
elif [[ "$name" == *-vst3 ]]; then
|
||||
base="${name%-vst3}"
|
||||
cd "$dir" && zip -r "../../release/${base}-vst3.zip" cagire-plugins.vst3 && cd ../..
|
||||
elif [[ "$name" == *-desktop ]]; then
|
||||
base="${name%-desktop}"
|
||||
if ls "$dir"/*.deb 1>/dev/null 2>&1; then
|
||||
cp "$dir"/*.deb "release/${base}-desktop.deb"
|
||||
elif [ -f "$dir/Cagire.app.zip" ]; then
|
||||
cp "$dir/Cagire.app.zip" "release/${base}-desktop.app.zip"
|
||||
elif [ -f "$dir/cagire-desktop.exe" ]; then
|
||||
cp "$dir/cagire-desktop.exe" "release/${base}-desktop.exe"
|
||||
fi
|
||||
else
|
||||
if [ -f "$dir/cagire.exe" ]; then
|
||||
cp "$dir/cagire.exe" "release/${name}.exe"
|
||||
elif [ -f "$dir/cagire" ]; then
|
||||
cp "$dir/cagire" "release/${name}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: release/*
|
||||
generate_release_notes: true
|
||||
- name: Clippy
|
||||
run: cargo clippy --target ${{ matrix.target }} -- -D warnings
|
||||
|
||||
368
.github/workflows/release.yml
vendored
Normal file
368
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: ubuntu-latest
|
||||
target: x86_64-unknown-linux-gnu
|
||||
artifact: cagire-linux-x86_64
|
||||
- os: macos-15-intel
|
||||
target: x86_64-apple-darwin
|
||||
artifact: cagire-macos-x86_64
|
||||
- os: macos-14
|
||||
target: aarch64-apple-darwin
|
||||
artifact: cagire-macos-aarch64
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
artifact: cagire-windows-x86_64
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: ${{ matrix.target }}
|
||||
|
||||
- name: Install cargo-binstall
|
||||
uses: cargo-bins/cargo-binstall@main
|
||||
|
||||
- name: Install dependencies (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential cmake pkg-config libasound2-dev libclang-dev libjack-dev \
|
||||
libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev libxkbcommon-dev libssl-dev libgl1-mesa-dev
|
||||
cargo binstall -y cargo-bundle
|
||||
|
||||
- name: Install dependencies (macOS)
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew list cmake &>/dev/null || brew install cmake
|
||||
cargo binstall -y cargo-bundle
|
||||
|
||||
- name: Install dependencies (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
choco install cmake --installargs 'ADD_CMAKE_TO_PATH=System'
|
||||
echo "C:\Program Files\CMake\bin" >> $env:GITHUB_PATH
|
||||
|
||||
- name: Build
|
||||
run: cargo build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Build desktop
|
||||
run: cargo build --release --features desktop --bin cagire-desktop --target ${{ matrix.target }}
|
||||
|
||||
- name: Bundle desktop app
|
||||
if: runner.os != 'Windows'
|
||||
run: cargo bundle --release --features desktop --bin cagire-desktop --target ${{ matrix.target }}
|
||||
|
||||
- name: Build AppImages (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
mkdir -p target/releases
|
||||
scripts/make-appimage.sh target/${{ matrix.target }}/release/cagire x86_64 target/releases
|
||||
scripts/make-appimage.sh target/${{ matrix.target }}/release/cagire-desktop x86_64 target/releases
|
||||
|
||||
- name: Upload AppImage artifacts (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-appimage
|
||||
path: target/releases/*.AppImage
|
||||
|
||||
- name: Bundle CLAP plugin
|
||||
run: cargo xtask bundle cagire-plugins --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Zip macOS app bundle
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
cd target/${{ matrix.target }}/release/bundle/osx
|
||||
zip -r Cagire.app.zip Cagire.app
|
||||
|
||||
- name: Upload artifact (Unix)
|
||||
if: runner.os != 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: target/${{ matrix.target }}/release/cagire
|
||||
|
||||
- name: Upload artifact (Windows)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: target/${{ matrix.target }}/release/cagire.exe
|
||||
|
||||
- name: Upload desktop artifact (Linux deb)
|
||||
if: runner.os == 'Linux'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/bundle/deb/*.deb
|
||||
|
||||
- name: Upload desktop artifact (macOS app bundle)
|
||||
if: runner.os == 'macOS'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/bundle/osx/Cagire.app.zip
|
||||
|
||||
- name: Upload desktop artifact (Windows exe)
|
||||
if: runner.os == 'Windows'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/cagire-desktop.exe
|
||||
|
||||
- name: Upload CLAP artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-clap
|
||||
path: target/bundled/cagire-plugins.clap
|
||||
|
||||
- name: Upload VST3 artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-vst3
|
||||
path: target/bundled/cagire-plugins.vst3
|
||||
|
||||
build-cross:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target: aarch64-unknown-linux-gnu
|
||||
artifact: cagire-linux-aarch64
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Cache Rust dependencies
|
||||
uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
key: ${{ matrix.target }}
|
||||
|
||||
- name: Install cross
|
||||
run: cargo install cross --git https://github.com/cross-rs/cross
|
||||
|
||||
- name: Build
|
||||
run: cross build --release --target ${{ matrix.target }}
|
||||
|
||||
- name: Build desktop
|
||||
run: cross build --release --features desktop --bin cagire-desktop --target ${{ matrix.target }}
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: target/${{ matrix.target }}/release/cagire
|
||||
|
||||
- name: Upload desktop artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}-desktop
|
||||
path: target/${{ matrix.target }}/release/cagire-desktop
|
||||
|
||||
universal-macos:
|
||||
needs: build
|
||||
runs-on: macos-14
|
||||
timeout-minutes: 10
|
||||
|
||||
steps:
|
||||
- name: Download macOS artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: cagire-macos-*
|
||||
path: artifacts
|
||||
|
||||
- name: Create universal CLI binary
|
||||
run: |
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64/cagire \
|
||||
artifacts/cagire-macos-aarch64/cagire \
|
||||
-output cagire
|
||||
chmod +x cagire
|
||||
lipo -info cagire
|
||||
|
||||
- name: Create universal app bundle
|
||||
run: |
|
||||
cd artifacts/cagire-macos-aarch64-desktop
|
||||
unzip Cagire.app.zip
|
||||
cd ../cagire-macos-x86_64-desktop
|
||||
unzip Cagire.app.zip
|
||||
cd ../..
|
||||
cp -R artifacts/cagire-macos-aarch64-desktop/Cagire.app Cagire.app
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64-desktop/Cagire.app/Contents/MacOS/cagire-desktop \
|
||||
artifacts/cagire-macos-aarch64-desktop/Cagire.app/Contents/MacOS/cagire-desktop \
|
||||
-output Cagire.app/Contents/MacOS/cagire-desktop
|
||||
lipo -info Cagire.app/Contents/MacOS/cagire-desktop
|
||||
zip -r Cagire.app.zip Cagire.app
|
||||
|
||||
- name: Create universal CLAP plugin
|
||||
run: |
|
||||
mkdir -p cagire-plugins.clap/Contents/MacOS
|
||||
cp artifacts/cagire-macos-aarch64-clap/cagire-plugins.clap/Contents/Info.plist \
|
||||
cagire-plugins.clap/Contents/ 2>/dev/null || true
|
||||
cp artifacts/cagire-macos-aarch64-clap/cagire-plugins.clap/Contents/PkgInfo \
|
||||
cagire-plugins.clap/Contents/ 2>/dev/null || true
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64-clap/cagire-plugins.clap/Contents/MacOS/cagire-plugins \
|
||||
artifacts/cagire-macos-aarch64-clap/cagire-plugins.clap/Contents/MacOS/cagire-plugins \
|
||||
-output cagire-plugins.clap/Contents/MacOS/cagire-plugins
|
||||
lipo -info cagire-plugins.clap/Contents/MacOS/cagire-plugins
|
||||
|
||||
- name: Create universal VST3 plugin
|
||||
run: |
|
||||
mkdir -p cagire-plugins.vst3/Contents/MacOS
|
||||
cp -R artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/Info.plist \
|
||||
cagire-plugins.vst3/Contents/ 2>/dev/null || true
|
||||
cp artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/PkgInfo \
|
||||
cagire-plugins.vst3/Contents/ 2>/dev/null || true
|
||||
cp -R artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/Resources \
|
||||
cagire-plugins.vst3/Contents/ 2>/dev/null || true
|
||||
lipo -create \
|
||||
artifacts/cagire-macos-x86_64-vst3/cagire-plugins.vst3/Contents/MacOS/cagire-plugins \
|
||||
artifacts/cagire-macos-aarch64-vst3/cagire-plugins.vst3/Contents/MacOS/cagire-plugins \
|
||||
-output cagire-plugins.vst3/Contents/MacOS/cagire-plugins
|
||||
lipo -info cagire-plugins.vst3/Contents/MacOS/cagire-plugins
|
||||
|
||||
- name: Build .pkg installer
|
||||
run: |
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
mkdir -p pkg-root/Applications pkg-root/usr/local/bin
|
||||
cp -R Cagire.app pkg-root/Applications/
|
||||
cp cagire pkg-root/usr/local/bin/
|
||||
pkgbuild --analyze --root pkg-root component.plist
|
||||
plutil -replace BundleIsRelocatable -bool NO component.plist
|
||||
pkgbuild --root pkg-root --identifier com.sova.cagire \
|
||||
--version "$VERSION" --install-location / \
|
||||
--component-plist component.plist \
|
||||
"Cagire-${VERSION}-universal.pkg"
|
||||
|
||||
- name: Upload universal CLI
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal
|
||||
path: cagire
|
||||
|
||||
- name: Upload universal app bundle
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-desktop
|
||||
path: Cagire.app.zip
|
||||
|
||||
- name: Upload universal CLAP plugin
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-clap
|
||||
path: cagire-plugins.clap
|
||||
|
||||
- name: Upload universal VST3 plugin
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-vst3
|
||||
path: cagire-plugins.vst3
|
||||
|
||||
- name: Upload .pkg installer
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cagire-macos-universal-pkg
|
||||
path: Cagire-*-universal.pkg
|
||||
|
||||
release:
|
||||
needs: [build, build-cross, universal-macos]
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Prepare release files
|
||||
run: |
|
||||
mkdir -p release
|
||||
for dir in artifacts/*/; do
|
||||
name=$(basename "$dir")
|
||||
if [[ "$name" == "cagire-macos-universal-pkg" ]]; then
|
||||
cp "$dir"/*.pkg release/
|
||||
elif [[ "$name" == "cagire-macos-universal-desktop" ]]; then
|
||||
cp "$dir/Cagire.app.zip" "release/cagire-macos-universal-desktop.app.zip"
|
||||
elif [[ "$name" == "cagire-macos-universal" ]]; then
|
||||
cp "$dir/cagire" "release/cagire-macos-universal"
|
||||
elif [[ "$name" == "cagire-macos-universal-clap" ]]; then
|
||||
cd "$dir" && zip -r "../../release/cagire-macos-universal-clap.zip" cagire-plugins.clap && cd ../..
|
||||
elif [[ "$name" == "cagire-macos-universal-vst3" ]]; then
|
||||
cd "$dir" && zip -r "../../release/cagire-macos-universal-vst3.zip" cagire-plugins.vst3 && cd ../..
|
||||
elif [[ "$name" == *-clap ]]; then
|
||||
base="${name%-clap}"
|
||||
cd "$dir" && zip -r "../../release/${base}-clap.zip" cagire-plugins.clap && cd ../..
|
||||
elif [[ "$name" == *-vst3 ]]; then
|
||||
base="${name%-vst3}"
|
||||
cd "$dir" && zip -r "../../release/${base}-vst3.zip" cagire-plugins.vst3 && cd ../..
|
||||
elif [[ "$name" == *-appimage ]]; then
|
||||
cp "$dir"/*.AppImage release/
|
||||
elif [[ "$name" == *-desktop ]]; then
|
||||
base="${name%-desktop}"
|
||||
if ls "$dir"/*.deb 1>/dev/null 2>&1; then
|
||||
cp "$dir"/*.deb "release/${base}-desktop.deb"
|
||||
elif [ -f "$dir/Cagire.app.zip" ]; then
|
||||
cp "$dir/Cagire.app.zip" "release/${base}-desktop.app.zip"
|
||||
elif [ -f "$dir/cagire-desktop.exe" ]; then
|
||||
cp "$dir/cagire-desktop.exe" "release/${base}-desktop.exe"
|
||||
fi
|
||||
else
|
||||
if [ -f "$dir/cagire.exe" ]; then
|
||||
cp "$dir/cagire.exe" "release/${name}.exe"
|
||||
elif [ -f "$dir/cagire" ]; then
|
||||
cp "$dir/cagire" "release/${name}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: release/*
|
||||
generate_release_notes: true
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,10 +1,11 @@
|
||||
/target
|
||||
/.cache
|
||||
Cargo.lock
|
||||
*.prof
|
||||
.DS_Store
|
||||
|
||||
# Cargo config
|
||||
.cargo/config.toml
|
||||
# Local cargo overrides (doux path patch)
|
||||
.cargo/config.local.toml
|
||||
|
||||
# Claude
|
||||
.claude/
|
||||
|
||||
96
BUILDING.md
96
BUILDING.md
@@ -1,5 +1,15 @@
|
||||
# Building Cagire
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/Bubobubobubobubo/cagire
|
||||
cd cagire
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
The `doux` audio engine is fetched automatically from git. No local path setup needed.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**Rust** (stable toolchain): https://rustup.rs
|
||||
@@ -68,6 +78,14 @@ Desktop (egui window):
|
||||
cargo build --release --features desktop --bin cagire-desktop
|
||||
```
|
||||
|
||||
Plugins (CLAP/VST3):
|
||||
|
||||
```bash
|
||||
cargo xtask bundle cagire-plugins --release
|
||||
```
|
||||
|
||||
The xtask alias is defined in `.cargo/config.toml` (committed). Plugin bundles are output to `target/bundled/`.
|
||||
|
||||
## Run
|
||||
|
||||
Terminal (default):
|
||||
@@ -89,3 +107,81 @@ cargo run --release --features desktop --bin cagire-desktop
|
||||
| `-i, --input <device>` | Input audio device |
|
||||
| `-c, --channels <n>` | Output channel count |
|
||||
| `-b, --buffer <size>` | Audio buffer size |
|
||||
|
||||
## Cross-Compilation
|
||||
|
||||
[cross](https://github.com/cross-rs/cross) uses Docker to build for other platforms without installing their toolchains locally. It works on any OS that runs Docker.
|
||||
|
||||
### Targets
|
||||
|
||||
| Target | Method | Binaries |
|
||||
|--------|--------|----------|
|
||||
| aarch64-apple-darwin | Native (macOS ARM only) | `cagire`, `cagire-desktop` |
|
||||
| x86_64-apple-darwin | Native (macOS only) | `cagire`, `cagire-desktop` |
|
||||
| x86_64-unknown-linux-gnu | `cross build` | `cagire`, `cagire-desktop` |
|
||||
| aarch64-unknown-linux-gnu (RPi 64-bit) | `cross build` | `cagire`, `cagire-desktop` |
|
||||
| x86_64-pc-windows-gnu | `cross build` | `cagire`, `cagire-desktop` |
|
||||
|
||||
macOS targets can only be built on macOS — Apple does not support cross-compilation to macOS from other platforms. Linux and Windows targets can be cross-compiled from any OS. The aarch64-unknown-linux-gnu target covers Raspberry Pi (64-bit OS).
|
||||
|
||||
### Windows ABI
|
||||
|
||||
CI produces `x86_64-pc-windows-msvc` binaries (native Windows build, better compatibility). Local cross-compilation from non-Windows hosts produces `x86_64-pc-windows-gnu` binaries (MinGW via Docker). Both work; MSVC is preferred for releases.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. **Docker**: https://docs.docker.com/get-docker/
|
||||
2. **cross**: `cargo install cross --git https://github.com/cross-rs/cross`
|
||||
3. On macOS, add the Intel target: `rustup target add x86_64-apple-darwin`
|
||||
|
||||
Docker must be running before invoking `cross` or `scripts/build-all.sh`.
|
||||
|
||||
### Building Individual Targets
|
||||
|
||||
```bash
|
||||
# Linux x86_64
|
||||
cross build --release --target x86_64-unknown-linux-gnu
|
||||
cross build --release --features desktop --bin cagire-desktop --target x86_64-unknown-linux-gnu
|
||||
|
||||
# Linux aarch64
|
||||
cross build --release --target aarch64-unknown-linux-gnu
|
||||
cross build --release --features desktop --bin cagire-desktop --target aarch64-unknown-linux-gnu
|
||||
|
||||
# Windows x86_64
|
||||
cross build --release --target x86_64-pc-windows-gnu
|
||||
cross build --release --features desktop --bin cagire-desktop --target x86_64-pc-windows-gnu
|
||||
```
|
||||
|
||||
### Building All Targets (macOS only)
|
||||
|
||||
```bash
|
||||
# Interactive (prompts for platform/target selection):
|
||||
scripts/build-all.sh
|
||||
|
||||
# Non-interactive:
|
||||
scripts/build-all.sh --platforms macos-arm64,linux-x86_64 --targets cli,desktop --yes
|
||||
scripts/build-all.sh --all --yes
|
||||
```
|
||||
|
||||
Builds selected targets, producing binaries in `target/releases/`.
|
||||
|
||||
Platform aliases: `macos-arm64`, `macos-x86_64`, `linux-x86_64`, `linux-aarch64`, `windows-x86_64`.
|
||||
Target aliases: `cli`, `desktop`, `plugins`.
|
||||
|
||||
### Linux AppImage Packaging
|
||||
|
||||
Linux releases ship as AppImages — self-contained executables that bundle all shared library dependencies (ALSA, JACK, X11, OpenGL). No runtime dependencies required.
|
||||
|
||||
After building a Linux target, produce an AppImage with:
|
||||
|
||||
```bash
|
||||
scripts/make-appimage.sh target/x86_64-unknown-linux-gnu/release/cagire x86_64 target/releases
|
||||
```
|
||||
|
||||
`scripts/build-all.sh` does this automatically for every Linux target selected. The CI pipeline produces AppImages for the x86_64 Linux build. Cross-arch AppImage building (e.g. aarch64 on x86_64) is not supported — run on a matching host or in CI.
|
||||
|
||||
### Notes
|
||||
|
||||
- Custom Dockerfiles in `cross/` install the native libraries Cagire depends on (ALSA, JACK, X11, cmake, libclang, etc.). `Cross.toml` maps each target to its Dockerfile.
|
||||
- The first build per target downloads Docker base images and installs packages. Subsequent builds use cached layers.
|
||||
- Cross-architecture Docker builds (e.g. aarch64 on x86_64 or vice versa) run under QEMU emulation and are significantly slower.
|
||||
|
||||
@@ -51,7 +51,7 @@ cagire-forth = { path = "crates/forth" }
|
||||
cagire-markdown = { path = "crates/markdown" }
|
||||
cagire-project = { path = "crates/project" }
|
||||
cagire-ratatui = { path = "crates/ratatui" }
|
||||
doux = { path = "/Users/bubo/doux", features = ["native", "soundfont"] }
|
||||
doux = { git = "https://github.com/sova-org/doux", features = ["native", "soundfont"] }
|
||||
rusty_link = "0.4"
|
||||
ratatui = "0.30"
|
||||
crossterm = "0.29"
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
[build]
|
||||
volumes = ["/Users/bubo/doux:/Users/bubo/doux"]
|
||||
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
dockerfile = "./cross/aarch64-linux.Dockerfile"
|
||||
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
dockerfile = "./cross/x86_64-linux.Dockerfile"
|
||||
|
||||
[target.x86_64-pc-windows-gnu]
|
||||
dockerfile = "./cross/x86_64-windows.Dockerfile"
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 72 KiB |
7
assets/cagire.desktop
Normal file
7
assets/cagire.desktop
Normal file
@@ -0,0 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Cagire
|
||||
Comment=Forth-based music sequencer
|
||||
Exec=cagire
|
||||
Icon=cagire
|
||||
Categories=Audio;Music;AudioVideo;
|
||||
9
build.rs
9
build.rs
@@ -1,6 +1,15 @@
|
||||
//! Build script — embeds Windows application resources (icon, metadata).
|
||||
|
||||
fn main() {
|
||||
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
|
||||
|
||||
if target_os == "windows" {
|
||||
// rusty_link's build.rs only links stdc++ on linux — add it for windows too
|
||||
println!("cargo:rustc-link-lib=stdc++");
|
||||
println!("cargo:rustc-link-lib=ws2_32");
|
||||
println!("cargo:rustc-link-lib=iphlpapi");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let mut res = winres::WindowsResource::new();
|
||||
|
||||
@@ -11,4 +11,4 @@ description = "TUI components for cagire sequencer"
|
||||
rand = "0.8"
|
||||
ratatui = "0.30"
|
||||
regex = "1"
|
||||
tui-textarea = { git = "https://github.com/phsym/tui-textarea", branch = "main", features = ["search"] }
|
||||
tui-textarea = { git = "https://github.com/phsym/tui-textarea", rev = "e2ec4d3", features = ["search"] }
|
||||
|
||||
14
cross/x86_64-linux.Dockerfile
Normal file
14
cross/x86_64-linux.Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
cmake \
|
||||
libclang-dev \
|
||||
libasound2-dev \
|
||||
libjack-dev \
|
||||
libxcb-render0-dev \
|
||||
libxcb-shape0-dev \
|
||||
libxcb-xfixes0-dev \
|
||||
libxkbcommon-dev \
|
||||
libgl1-mesa-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
13
cross/x86_64-windows.Dockerfile
Normal file
13
cross/x86_64-windows.Dockerfile
Normal file
@@ -0,0 +1,13 @@
|
||||
FROM ghcr.io/cross-rs/x86_64-pc-windows-gnu:main
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
cmake \
|
||||
clang \
|
||||
libclang-dev \
|
||||
mingw-w64-tools \
|
||||
mingw-w64-x86-64-dev \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& ln -sf windows.h /usr/x86_64-w64-mingw32/include/Windows.h \
|
||||
&& ln -sf winsock2.h /usr/x86_64-w64-mingw32/include/WinSock2.h \
|
||||
&& ln -sf ws2tcpip.h /usr/x86_64-w64-mingw32/include/WS2tcpip.h
|
||||
@@ -14,7 +14,7 @@ cagire = { path = "../..", default-features = false, features = ["block-renderer
|
||||
cagire-forth = { path = "../../crates/forth" }
|
||||
cagire-project = { path = "../../crates/project" }
|
||||
cagire-ratatui = { path = "../../crates/ratatui" }
|
||||
doux = { path = "/Users/bubo/doux", features = ["native", "soundfont"] }
|
||||
doux = { git = "https://github.com/sova-org/doux", features = ["native", "soundfont"] }
|
||||
nih_plug = { git = "https://github.com/robbert-vdh/nih-plug", features = ["standalone"] }
|
||||
nih_plug_egui = { git = "https://github.com/robbert-vdh/nih-plug" }
|
||||
egui_ratatui = "2.1"
|
||||
|
||||
428
scripts/build-all.sh
Executable file
428
scripts/build-all.sh
Executable file
@@ -0,0 +1,428 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
cd "$(git rev-parse --show-toplevel)"
|
||||
|
||||
PLUGIN_NAME="cagire-plugins"
|
||||
LIB_NAME="cagire_plugins" # cargo converts hyphens to underscores
|
||||
OUT="target/releases"
|
||||
|
||||
PLATFORMS=(
|
||||
"aarch64-apple-darwin"
|
||||
"x86_64-apple-darwin"
|
||||
"x86_64-unknown-linux-gnu"
|
||||
"aarch64-unknown-linux-gnu"
|
||||
"x86_64-pc-windows-gnu"
|
||||
)
|
||||
|
||||
PLATFORM_LABELS=(
|
||||
"macOS aarch64 (native)"
|
||||
"macOS x86_64 (native)"
|
||||
"Linux x86_64 (cross)"
|
||||
"Linux aarch64 (cross)"
|
||||
"Windows x86_64 (cross)"
|
||||
)
|
||||
|
||||
PLATFORM_ALIASES=(
|
||||
"macos-arm64"
|
||||
"macos-x86_64"
|
||||
"linux-x86_64"
|
||||
"linux-aarch64"
|
||||
"windows-x86_64"
|
||||
)
|
||||
|
||||
# --- CLI argument parsing ---
|
||||
|
||||
cli_platforms=""
|
||||
cli_targets=""
|
||||
cli_yes=false
|
||||
cli_all=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--platforms) cli_platforms="$2"; shift 2 ;;
|
||||
--targets) cli_targets="$2"; shift 2 ;;
|
||||
--yes) cli_yes=true; shift ;;
|
||||
--all) cli_all=true; shift ;;
|
||||
-h|--help)
|
||||
echo "Usage: $0 [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --platforms <list> Comma-separated: macos-arm64,macos-x86_64,linux-x86_64,linux-aarch64,windows-x86_64"
|
||||
echo " --targets <list> Comma-separated: cli,desktop,plugins"
|
||||
echo " --all Build all platforms and targets"
|
||||
echo " --yes Skip confirmation prompt"
|
||||
echo ""
|
||||
echo "Without options, runs interactively."
|
||||
exit 0
|
||||
;;
|
||||
*) echo "Unknown option: $1"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
resolve_platform_alias() {
|
||||
local alias="$1"
|
||||
for i in "${!PLATFORM_ALIASES[@]}"; do
|
||||
if [[ "${PLATFORM_ALIASES[$i]}" == "$alias" ]]; then
|
||||
echo "$i"
|
||||
return
|
||||
fi
|
||||
done
|
||||
echo "Unknown platform: $alias" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- Helpers ---
|
||||
|
||||
prompt_platforms() {
|
||||
echo "Select platform (0=all, comma-separated):"
|
||||
echo " 0) All"
|
||||
for i in "${!PLATFORMS[@]}"; do
|
||||
echo " $((i+1))) ${PLATFORM_LABELS[$i]}"
|
||||
done
|
||||
read -rp "> " choice
|
||||
|
||||
if [[ "$choice" == "0" || -z "$choice" ]]; then
|
||||
selected_platforms=("${PLATFORMS[@]}")
|
||||
selected_labels=("${PLATFORM_LABELS[@]}")
|
||||
else
|
||||
IFS=',' read -ra indices <<< "$choice"
|
||||
selected_platforms=()
|
||||
selected_labels=()
|
||||
for idx in "${indices[@]}"; do
|
||||
idx="${idx// /}"
|
||||
idx=$((idx - 1))
|
||||
if (( idx < 0 || idx >= ${#PLATFORMS[@]} )); then
|
||||
echo "Invalid platform index: $((idx+1))"
|
||||
exit 1
|
||||
fi
|
||||
selected_platforms+=("${PLATFORMS[$idx]}")
|
||||
selected_labels+=("${PLATFORM_LABELS[$idx]}")
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
prompt_targets() {
|
||||
echo ""
|
||||
echo "Select targets (0=all, comma-separated):"
|
||||
echo " 0) All"
|
||||
echo " 1) cagire"
|
||||
echo " 2) cagire-desktop"
|
||||
echo " 3) cagire-plugins (CLAP/VST3)"
|
||||
read -rp "> " choice
|
||||
|
||||
build_cagire=false
|
||||
build_desktop=false
|
||||
build_plugins=false
|
||||
|
||||
if [[ "$choice" == "0" || -z "$choice" ]]; then
|
||||
build_cagire=true
|
||||
build_desktop=true
|
||||
build_plugins=true
|
||||
else
|
||||
IFS=',' read -ra targets <<< "$choice"
|
||||
for t in "${targets[@]}"; do
|
||||
t="${t// /}"
|
||||
case "$t" in
|
||||
1) build_cagire=true ;;
|
||||
2) build_desktop=true ;;
|
||||
3) build_plugins=true ;;
|
||||
*) echo "Invalid target: $t"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
confirm_summary() {
|
||||
echo ""
|
||||
echo "=== Build Summary ==="
|
||||
echo ""
|
||||
echo "Platforms:"
|
||||
for label in "${selected_labels[@]}"; do
|
||||
echo " - $label"
|
||||
done
|
||||
echo ""
|
||||
echo "Targets:"
|
||||
$build_cagire && echo " - cagire"
|
||||
$build_desktop && echo " - cagire-desktop"
|
||||
$build_plugins && echo " - cagire-plugins (CLAP/VST3)"
|
||||
echo ""
|
||||
read -rp "Proceed? [Y/n] " yn
|
||||
case "${yn,,}" in
|
||||
n|no) echo "Aborted."; exit 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
platform_os() {
|
||||
case "$1" in
|
||||
*windows*) echo "windows" ;;
|
||||
*linux*) echo "linux" ;;
|
||||
*apple*) echo "macos" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
platform_arch() {
|
||||
case "$1" in
|
||||
aarch64*) echo "aarch64" ;;
|
||||
x86_64*) echo "x86_64" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
platform_suffix() {
|
||||
case "$1" in
|
||||
*windows*) echo ".exe" ;;
|
||||
*) echo "" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_cross_target() {
|
||||
case "$1" in
|
||||
*linux*|*windows*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
native_target() {
|
||||
[[ "$1" == "aarch64-apple-darwin" ]]
|
||||
}
|
||||
|
||||
release_dir() {
|
||||
if native_target "$1"; then
|
||||
echo "target/release"
|
||||
else
|
||||
echo "target/$1/release"
|
||||
fi
|
||||
}
|
||||
|
||||
target_flag() {
|
||||
if native_target "$1"; then
|
||||
echo ""
|
||||
else
|
||||
echo "--target $1"
|
||||
fi
|
||||
}
|
||||
|
||||
builder_for() {
|
||||
if is_cross_target "$1"; then
|
||||
echo "cross"
|
||||
else
|
||||
echo "cargo"
|
||||
fi
|
||||
}
|
||||
|
||||
build_binary() {
|
||||
local platform="$1"
|
||||
shift
|
||||
local builder
|
||||
builder=$(builder_for "$platform")
|
||||
local tf
|
||||
tf=$(target_flag "$platform")
|
||||
# shellcheck disable=SC2086
|
||||
$builder build --release $tf "$@"
|
||||
}
|
||||
|
||||
bundle_plugins_native() {
|
||||
local platform="$1"
|
||||
local tf
|
||||
tf=$(target_flag "$platform")
|
||||
# shellcheck disable=SC2086
|
||||
cargo xtask bundle "$PLUGIN_NAME" --release $tf
|
||||
}
|
||||
|
||||
bundle_plugins_cross() {
|
||||
local platform="$1"
|
||||
local rd
|
||||
rd=$(release_dir "$platform")
|
||||
local os
|
||||
os=$(platform_os "$platform")
|
||||
local arch
|
||||
arch=$(platform_arch "$platform")
|
||||
|
||||
# Build the cdylib with cross
|
||||
# shellcheck disable=SC2046
|
||||
build_binary "$platform" -p "$PLUGIN_NAME"
|
||||
|
||||
# Determine source library file
|
||||
local src_lib
|
||||
case "$os" in
|
||||
linux) src_lib="$rd/lib${LIB_NAME}.so" ;;
|
||||
windows) src_lib="$rd/${LIB_NAME}.dll" ;;
|
||||
esac
|
||||
|
||||
if [[ ! -f "$src_lib" ]]; then
|
||||
echo " ERROR: Expected library not found: $src_lib"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Assemble CLAP bundle (flat file)
|
||||
local clap_out="$OUT/${PLUGIN_NAME}-${os}-${arch}.clap"
|
||||
cp "$src_lib" "$clap_out"
|
||||
echo " CLAP -> $clap_out"
|
||||
|
||||
# Assemble VST3 bundle (directory tree)
|
||||
local vst3_dir="$OUT/${PLUGIN_NAME}-${os}-${arch}.vst3"
|
||||
local vst3_contents
|
||||
case "$os" in
|
||||
linux)
|
||||
vst3_contents="$vst3_dir/Contents/${arch}-linux"
|
||||
mkdir -p "$vst3_contents"
|
||||
cp "$src_lib" "$vst3_contents/${PLUGIN_NAME}.so"
|
||||
;;
|
||||
windows)
|
||||
vst3_contents="$vst3_dir/Contents/${arch}-win"
|
||||
mkdir -p "$vst3_contents"
|
||||
cp "$src_lib" "$vst3_contents/${PLUGIN_NAME}.vst3"
|
||||
;;
|
||||
esac
|
||||
echo " VST3 -> $vst3_dir/"
|
||||
}
|
||||
|
||||
copy_artifacts() {
|
||||
local platform="$1"
|
||||
local rd
|
||||
rd=$(release_dir "$platform")
|
||||
local os
|
||||
os=$(platform_os "$platform")
|
||||
local arch
|
||||
arch=$(platform_arch "$platform")
|
||||
local suffix
|
||||
suffix=$(platform_suffix "$platform")
|
||||
|
||||
if $build_cagire; then
|
||||
local src="$rd/cagire${suffix}"
|
||||
local dst="$OUT/cagire-${os}-${arch}${suffix}"
|
||||
cp "$src" "$dst"
|
||||
echo " cagire -> $dst"
|
||||
fi
|
||||
|
||||
if $build_desktop; then
|
||||
local src="$rd/cagire-desktop${suffix}"
|
||||
local dst="$OUT/cagire-desktop-${os}-${arch}${suffix}"
|
||||
cp "$src" "$dst"
|
||||
echo " cagire-desktop -> $dst"
|
||||
fi
|
||||
|
||||
# AppImage for Linux targets
|
||||
if [[ "$os" == "linux" ]]; then
|
||||
if $build_cagire; then
|
||||
scripts/make-appimage.sh "$rd/cagire" "$arch" "$OUT"
|
||||
fi
|
||||
if $build_desktop; then
|
||||
scripts/make-appimage.sh "$rd/cagire-desktop" "$arch" "$OUT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Plugin artifacts for native targets (cross handled in bundle_plugins_cross)
|
||||
if $build_plugins && ! is_cross_target "$platform"; then
|
||||
local bundle_dir="$rd/bundle"
|
||||
|
||||
# CLAP
|
||||
local clap_src="$bundle_dir/${PLUGIN_NAME}.clap"
|
||||
if [[ -e "$clap_src" ]]; then
|
||||
local clap_dst="$OUT/${PLUGIN_NAME}-${os}-${arch}.clap"
|
||||
cp -r "$clap_src" "$clap_dst"
|
||||
echo " CLAP -> $clap_dst"
|
||||
fi
|
||||
|
||||
# VST3
|
||||
local vst3_src="$bundle_dir/${PLUGIN_NAME}.vst3"
|
||||
if [[ -d "$vst3_src" ]]; then
|
||||
local vst3_dst="$OUT/${PLUGIN_NAME}-${os}-${arch}.vst3"
|
||||
rm -rf "$vst3_dst"
|
||||
cp -r "$vst3_src" "$vst3_dst"
|
||||
echo " VST3 -> $vst3_dst/"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Main ---
|
||||
|
||||
if $cli_all; then
|
||||
selected_platforms=("${PLATFORMS[@]}")
|
||||
selected_labels=("${PLATFORM_LABELS[@]}")
|
||||
build_cagire=true
|
||||
build_desktop=true
|
||||
build_plugins=true
|
||||
elif [[ -n "$cli_platforms" || -n "$cli_targets" ]]; then
|
||||
# Resolve platforms from CLI
|
||||
if [[ -n "$cli_platforms" ]]; then
|
||||
selected_platforms=()
|
||||
selected_labels=()
|
||||
IFS=',' read -ra aliases <<< "$cli_platforms"
|
||||
for alias in "${aliases[@]}"; do
|
||||
alias="${alias// /}"
|
||||
idx=$(resolve_platform_alias "$alias")
|
||||
selected_platforms+=("${PLATFORMS[$idx]}")
|
||||
selected_labels+=("${PLATFORM_LABELS[$idx]}")
|
||||
done
|
||||
else
|
||||
selected_platforms=("${PLATFORMS[@]}")
|
||||
selected_labels=("${PLATFORM_LABELS[@]}")
|
||||
fi
|
||||
|
||||
# Resolve targets from CLI
|
||||
build_cagire=false
|
||||
build_desktop=false
|
||||
build_plugins=false
|
||||
if [[ -n "$cli_targets" ]]; then
|
||||
IFS=',' read -ra tgts <<< "$cli_targets"
|
||||
for t in "${tgts[@]}"; do
|
||||
t="${t// /}"
|
||||
case "$t" in
|
||||
cli) build_cagire=true ;;
|
||||
desktop) build_desktop=true ;;
|
||||
plugins) build_plugins=true ;;
|
||||
*) echo "Unknown target: $t (expected: cli, desktop, plugins)"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
else
|
||||
build_cagire=true
|
||||
build_desktop=true
|
||||
build_plugins=true
|
||||
fi
|
||||
else
|
||||
prompt_platforms
|
||||
prompt_targets
|
||||
fi
|
||||
|
||||
if ! $cli_yes && [[ -z "$cli_platforms" ]] && ! $cli_all; then
|
||||
confirm_summary
|
||||
fi
|
||||
|
||||
mkdir -p "$OUT"
|
||||
|
||||
step=0
|
||||
total=${#selected_platforms[@]}
|
||||
|
||||
for platform in "${selected_platforms[@]}"; do
|
||||
step=$((step + 1))
|
||||
echo ""
|
||||
echo "=== [$step/$total] $platform ==="
|
||||
|
||||
if $build_cagire; then
|
||||
echo " -> cagire"
|
||||
build_binary "$platform"
|
||||
fi
|
||||
|
||||
if $build_desktop; then
|
||||
echo " -> cagire-desktop"
|
||||
build_binary "$platform" --features desktop --bin cagire-desktop
|
||||
fi
|
||||
|
||||
if $build_plugins; then
|
||||
echo " -> cagire-plugins"
|
||||
if is_cross_target "$platform"; then
|
||||
bundle_plugins_cross "$platform"
|
||||
else
|
||||
bundle_plugins_native "$platform"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " Copying artifacts..."
|
||||
copy_artifacts "$platform"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "=== Done ==="
|
||||
echo ""
|
||||
ls -lhR "$OUT/"
|
||||
136
scripts/make-appimage.sh
Executable file
136
scripts/make-appimage.sh
Executable file
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Usage: scripts/make-appimage.sh <binary-path> <arch> <output-dir>
|
||||
# Produces an AppImage from a Linux binary using linuxdeploy.
|
||||
|
||||
if [[ $# -ne 3 ]]; then
|
||||
echo "Usage: $0 <binary-path> <arch> <output-dir>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BINARY="$1"
|
||||
ARCH="$2"
|
||||
OUTDIR="$3"
|
||||
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
CACHE_DIR="$REPO_ROOT/.cache"
|
||||
APP_NAME="$(basename "$BINARY")"
|
||||
APPDIR="$(mktemp -d)/AppDir"
|
||||
|
||||
LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${ARCH}.AppImage"
|
||||
LINUXDEPLOY="$CACHE_DIR/linuxdeploy-${ARCH}.AppImage"
|
||||
RUNTIME_URL="https://github.com/AppImage/type2-runtime/releases/download/continuous/runtime-${ARCH}"
|
||||
RUNTIME="$CACHE_DIR/runtime-${ARCH}"
|
||||
|
||||
# Map arch to linuxdeploy's expected values
|
||||
case "$ARCH" in
|
||||
x86_64) export LDAI_ARCH="x86_64" ;;
|
||||
aarch64) export LDAI_ARCH="aarch64" ;;
|
||||
*) echo "Unsupported arch: $ARCH"; exit 1 ;;
|
||||
esac
|
||||
|
||||
download_tools() {
|
||||
mkdir -p "$CACHE_DIR"
|
||||
if [[ ! -f "$LINUXDEPLOY" ]]; then
|
||||
echo " Downloading linuxdeploy for $ARCH..."
|
||||
curl -fSL "$LINUXDEPLOY_URL" -o "$LINUXDEPLOY"
|
||||
chmod +x "$LINUXDEPLOY"
|
||||
fi
|
||||
if [[ ! -f "$RUNTIME" ]]; then
|
||||
echo " Downloading AppImage runtime for $ARCH..."
|
||||
curl -fSL "$RUNTIME_URL" -o "$RUNTIME"
|
||||
fi
|
||||
}
|
||||
|
||||
build_appdir() {
|
||||
mkdir -p "$APPDIR/usr/bin"
|
||||
cp "$BINARY" "$APPDIR/usr/bin/cagire"
|
||||
chmod +x "$APPDIR/usr/bin/cagire"
|
||||
|
||||
mkdir -p "$APPDIR/usr/share/icons/hicolor/512x512/apps"
|
||||
cp "$REPO_ROOT/assets/Cagire.png" "$APPDIR/usr/share/icons/hicolor/512x512/apps/cagire.png"
|
||||
|
||||
cp "$REPO_ROOT/assets/cagire.desktop" "$APPDIR/cagire.desktop"
|
||||
}
|
||||
|
||||
run_linuxdeploy_native() {
|
||||
export ARCH="$LDAI_ARCH"
|
||||
export LDAI_RUNTIME_FILE="$RUNTIME"
|
||||
"$LINUXDEPLOY" \
|
||||
--appimage-extract-and-run \
|
||||
--appdir "$APPDIR" \
|
||||
--desktop-file "$APPDIR/cagire.desktop" \
|
||||
--icon-file "$APPDIR/usr/share/icons/hicolor/512x512/apps/cagire.png" \
|
||||
--output appimage
|
||||
}
|
||||
|
||||
run_linuxdeploy_docker() {
|
||||
local platform
|
||||
case "$ARCH" in
|
||||
x86_64) platform="linux/amd64" ;;
|
||||
aarch64) platform="linux/arm64" ;;
|
||||
esac
|
||||
|
||||
local image_tag="cagire-appimage-${ARCH}"
|
||||
|
||||
echo " Building Docker image $image_tag ($platform)..."
|
||||
docker build --platform "$platform" -q -t "$image_tag" - <<'DOCKERFILE'
|
||||
FROM ubuntu:22.04
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
file \
|
||||
libasound2 \
|
||||
libjack0 \
|
||||
libxcb-render0 \
|
||||
libxcb-shape0 \
|
||||
libxcb-xfixes0 \
|
||||
libxkbcommon0 \
|
||||
libgl1 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
DOCKERFILE
|
||||
|
||||
echo " Running linuxdeploy inside Docker ($image_tag)..."
|
||||
docker run --rm --platform "$platform" \
|
||||
-v "$REPO_ROOT:/project" \
|
||||
-v "$APPDIR:/appdir" \
|
||||
-v "$CACHE_DIR:/cache" \
|
||||
-e ARCH="$LDAI_ARCH" \
|
||||
-e LDAI_RUNTIME_FILE="/cache/runtime-${ARCH}" \
|
||||
-w /project \
|
||||
"$image_tag" \
|
||||
bash -c "
|
||||
chmod +x /cache/linuxdeploy-${ARCH}.AppImage && \
|
||||
/cache/linuxdeploy-${ARCH}.AppImage \
|
||||
--appimage-extract-and-run \
|
||||
--appdir /appdir \
|
||||
--desktop-file /appdir/cagire.desktop \
|
||||
--icon-file /appdir/usr/share/icons/hicolor/512x512/apps/cagire.png \
|
||||
--output appimage
|
||||
"
|
||||
}
|
||||
|
||||
HOST_ARCH="$(uname -m)"
|
||||
|
||||
download_tools
|
||||
build_appdir
|
||||
|
||||
echo " Building AppImage for cagire ($ARCH)..."
|
||||
|
||||
if [[ "$HOST_ARCH" == "$ARCH" ]] && [[ "$(uname -s)" == "Linux" ]]; then
|
||||
run_linuxdeploy_native
|
||||
else
|
||||
run_linuxdeploy_docker
|
||||
fi
|
||||
|
||||
mkdir -p "$OUTDIR"
|
||||
|
||||
# linuxdeploy outputs to cwd; find and move the AppImage
|
||||
APPIMAGE=$(ls -1t ./*.AppImage 2>/dev/null | head -1 || true)
|
||||
if [[ -z "$APPIMAGE" ]]; then
|
||||
echo " ERROR: No AppImage produced"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FINAL_NAME="${APP_NAME}-linux-${ARCH}.AppImage"
|
||||
mv "$APPIMAGE" "$OUTDIR/$FINAL_NAME"
|
||||
echo " AppImage -> $OUTDIR/$FINAL_NAME"
|
||||
Reference in New Issue
Block a user