Files
Cagire/scripts/build-all.sh
2026-03-05 22:14:28 +01:00

474 lines
12 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
export MACOSX_DEPLOYMENT_TARGET="12.0"
cd "$(git rev-parse --show-toplevel)"
PLUGIN_NAME="cagire-plugins"
LIB_NAME="cagire_plugins" # cargo converts hyphens to underscores
OUT="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_desktop_native() {
local platform="$1"
local tf
tf=$(target_flag "$platform")
# shellcheck disable=SC2086
cargo bundle --release --features desktop --bin cagire-desktop $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"
# macOS .app bundle
if [[ "$os" == "macos" ]]; then
local app_src="$rd/bundle/osx/Cagire.app"
if [[ ! -d "$app_src" ]]; then
echo " ERROR: .app bundle not found at $app_src"
echo " Did 'cargo bundle' succeed?"
return 1
fi
local app_dst="$OUT/Cagire-${arch}.app"
rm -rf "$app_dst"
cp -R "$app_src" "$app_dst"
echo " Cagire.app -> $app_dst"
scripts/make-dmg.sh "$app_dst" "$OUT"
fi
fi
# NSIS installer for Windows targets
if [[ "$os" == "windows" ]] && command -v makensis &>/dev/null; then
echo " Building NSIS installer..."
local version
version=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)"/\1/')
local abs_root
abs_root=$(pwd)
makensis -DVERSION="$version" \
-DCLI_EXE="$abs_root/$rd/cagire.exe" \
-DDESKTOP_EXE="$abs_root/$rd/cagire-desktop.exe" \
-DICON="$abs_root/assets/Cagire.ico" \
-DOUTDIR="$abs_root/$OUT" \
nsis/cagire.nsi
echo " Installer -> $OUT/cagire-${version}-windows-x86_64-setup.exe"
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="target/bundled"
# 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
if ! is_cross_target "$platform"; then
echo " -> bundling cagire-desktop .app"
bundle_desktop_native "$platform"
fi
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/"