mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-09-10 17:16:47 -04:00
5c76e2b0df
* feature: add apple silicon native macOS support - #81 * (macos): Fix crash This fixes a crash when viewing the rear camera * fix(macos): keep interpolated presentation on main thread * fix(macos): supply Retro-WFC payload during setup * perf(windows): compile out flat-memory fallback check * remove duplicate smoke test * test(macos): name and focus host platform tests * fix(macos): validate Retro-WFC payload cache * fix(payload): preserve staged file access failures * Limit flat-page checks to variable-page hosts --------- Co-authored-by: patchzyy <64382339+patchzyy@users.noreply.github.com>
140 lines
9.2 KiB
Bash
Executable File
140 lines
9.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Native macOS build automation: optionally extract -> translate -> compile -> publish .app.
|
|
set -euo pipefail
|
|
|
|
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
default_workspace=$(cd "$script_dir/.." && pwd)
|
|
|
|
fail() { printf 'local-build-macos.command: error: %s\n' "$*" >&2; exit 1; }
|
|
step() { printf 'MKWCBUILD:STEP:%s %s\n' "$1" "$2"; }
|
|
assert_file() { [[ -f "$1" ]] || fail "$2 is missing: $1"; }
|
|
sha256() { shasum -a 256 "$1" | awk '{ print $1 }'; }
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: local-build-macos.command --output-dir DIR [options]
|
|
|
|
--workspace DIR Repository root (default: this script's parent directory)
|
|
--profile {base|retro-rewind|both} Product to build (default: base)
|
|
--output-dir DIR Output .app directory (required; Retro Rewind for both)
|
|
--base-output-dir DIR Base .app directory (required with --profile both)
|
|
--game IMAGE --nodtool PATH Extract and verify a clean PAL RMCP01 disc image first
|
|
--retro-rewind-package-dir DIR RetroRewind6 directory (required for Retro Rewind)
|
|
--retro-wfc-offline-dir DIR Directory containing binary/payload.RMCPD00.bin
|
|
--skip-retro-wfc-payload Build Retro Rewind without the shared Retro-WFC payload
|
|
--force-clean-build Delete local generated and native-build-macos caches
|
|
--parallel N Pin translation and build parallelism
|
|
--cmake PATH --ninja PATH Override build tools
|
|
--dotnet PATH Override dotnet
|
|
--translator-bin PATH Use a self-contained Translator.Cli executable
|
|
EOF
|
|
}
|
|
|
|
workspace="$default_workspace"; profile=base; output_dir=""; base_output_dir=""
|
|
game=""; nodtool=""; retro_root=""; retro_wfc=""; skip_retro_wfc=0; force_clean=0
|
|
parallel=0; cmake_bin=cmake; ninja_bin=ninja; dotnet_bin=dotnet; translator_bin=""
|
|
while (($#)); do
|
|
case "$1" in
|
|
--workspace) workspace=${2:-}; shift 2 ;;
|
|
--profile) profile=${2:-}; shift 2 ;;
|
|
--output-dir) output_dir=${2:-}; shift 2 ;;
|
|
--base-output-dir) base_output_dir=${2:-}; shift 2 ;;
|
|
--game) game=${2:-}; shift 2 ;;
|
|
--nodtool) nodtool=${2:-}; shift 2 ;;
|
|
--retro-rewind-package-dir) retro_root=${2:-}; shift 2 ;;
|
|
--retro-wfc-offline-dir) retro_wfc=${2:-}; shift 2 ;;
|
|
--skip-retro-wfc-payload) skip_retro_wfc=1; shift ;;
|
|
--force-clean-build) force_clean=1; shift ;;
|
|
--parallel) parallel=${2:-}; shift 2 ;;
|
|
--cmake) cmake_bin=${2:-}; shift 2 ;;
|
|
--ninja) ninja_bin=${2:-}; shift 2 ;;
|
|
--dotnet) dotnet_bin=${2:-}; shift 2 ;;
|
|
--translator-bin) translator_bin=${2:-}; shift 2 ;;
|
|
-h|--help) usage; exit 0 ;;
|
|
*) fail "unknown option: $1" ;;
|
|
esac
|
|
done
|
|
|
|
[[ $(uname -s) == Darwin ]] || fail 'this build script is for macOS only'
|
|
[[ $(uname -m) == arm64 ]] || fail 'the current macOS product target is Apple Silicon only'
|
|
workspace=$(cd "$workspace" && pwd)
|
|
[[ -n "$output_dir" ]] || fail '--output-dir is required'
|
|
case "$profile" in base|retro-rewind|both) ;; *) fail '--profile must be base, retro-rewind, or both' ;; esac
|
|
builds_retro=0; [[ "$profile" != base ]] && builds_retro=1
|
|
if [[ "$profile" == both && -z "$base_output_dir" ]]; then fail '--base-output-dir is required with --profile both'; fi
|
|
if [[ "$profile" != both && -n "$base_output_dir" ]]; then fail '--base-output-dir is valid only with --profile both'; fi
|
|
if [[ -n "$game" || -n "$nodtool" ]]; then [[ -n "$game" && -n "$nodtool" ]] || fail '--game and --nodtool must be supplied together'; fi
|
|
if (( builds_retro )); then
|
|
[[ -n "$retro_root" ]] || fail '--retro-rewind-package-dir is required for Retro Rewind'
|
|
[[ -n "$retro_wfc" ]] && (( skip_retro_wfc )) && fail 'choose only one Retro-WFC mode'
|
|
[[ -n "$retro_wfc" || $skip_retro_wfc -eq 1 ]] || fail 'choose a Retro-WFC payload directory or --skip-retro-wfc-payload'
|
|
fi
|
|
for tool in "$cmake_bin" "$ninja_bin" clang clang++ shasum; do command -v "$tool" >/dev/null || fail "required tool not found: $tool"; done
|
|
|
|
project="$workspace/projects/mkwii/recomp.yml"; assets="$workspace/Assets"; generated="$workspace/generated"
|
|
functions="$generated/functions"; metadata="$generated/base_translation_output.json"; manifest_dir="$workspace/build/base"
|
|
manifest="$manifest_dir/mkwii_base_manifest.json"; shards="$generated/build_shards"; native_build="$workspace/native-build-macos"
|
|
assert_file "$project" 'translation project'
|
|
if [[ -n "$game" ]]; then "$script_dir/macos/extract-disc.command" --game "$game" --assets-dir "$assets" --nodtool "$nodtool"; fi
|
|
assert_file "$assets/main.dol" 'extracted main.dol'; assert_file "$assets/StaticR.rel" 'extracted StaticR.rel'
|
|
|
|
if (( force_clean )); then
|
|
step force-clean 'Discarding translation and native build caches'
|
|
rm -rf "$generated" "$manifest_dir" "$native_build"
|
|
fi
|
|
|
|
if [[ -n "$translator_bin" ]]; then
|
|
assert_file "$translator_bin" 'Translator.Cli executable'
|
|
translator() { "$translator_bin" "$@"; }
|
|
else
|
|
command -v "$dotnet_bin" >/dev/null || fail "required tool not found: $dotnet_bin"
|
|
translator_dll="$workspace/translator/src/Translator.Cli/bin/Release/net8.0/Translator.Cli.dll"
|
|
if [[ ! -f "$translator_dll" ]]; then
|
|
step build-translator 'Building the translator'
|
|
"$dotnet_bin" build "$workspace/translator/src/Translator.Cli/Translator.Cli.csproj" -c Release
|
|
fi
|
|
translator() { "$dotnet_bin" "$translator_dll" "$@"; }
|
|
fi
|
|
|
|
entry_point=$(awk '/^translation:/{inside=1} inside && /^[[:space:]]*-[[:space:]]*0[xX][0-9a-fA-F]+[[:space:]]*$/{gsub(/^[[:space:]]*-[[:space:]]*/, ""); print; exit}' "$project")
|
|
[[ -n "$entry_point" ]] || fail 'could not find the translation entry point'
|
|
cpu=$(sysctl -n hw.ncpu); mem_gib=$(( $(sysctl -n hw.memsize) / 1024 / 1024 / 1024 )); (( mem_gib < 1 )) && mem_gib=1
|
|
if (( parallel > 0 )); then translator_threads=$parallel; translated_jobs=$parallel; global_jobs=$parallel
|
|
else translator_threads=$(( cpu < 16 ? cpu : 16 )); translated_jobs=$(( cpu < mem_gib / 2 ? cpu : mem_gib / 2 )); (( translated_jobs < 1 )) && translated_jobs=1; global_jobs=$cpu; fi
|
|
|
|
if (( builds_retro )); then
|
|
retro_root=$(cd "$retro_root" && pwd)
|
|
if [[ ! -f "$retro_root/Binaries/Code.pul" && -f "$retro_root/RetroRewind6/Binaries/Code.pul" ]]; then
|
|
retro_root="$retro_root/RetroRewind6"
|
|
fi
|
|
assert_file "$retro_root/Binaries/Code.pul" 'Retro Rewind Code.pul'
|
|
stage="$workspace/PulsarPacks/completed/RetroRewind/RetroRewind6/Binaries"
|
|
mkdir -p "$stage"
|
|
if [[ ! "$retro_root/Binaries/Code.pul" -ef "$stage/Code.pul" ]]; then
|
|
cp -f "$retro_root/Binaries/Code.pul" "$stage/Code.pul"
|
|
fi
|
|
fi
|
|
|
|
step translate-base 'Translating the user-owned base game'
|
|
rm -rf "$functions" "$metadata" "$manifest_dir"; mkdir -p "$functions" "$manifest_dir"
|
|
translator translate-recursive "$entry_point" --project "$project" --outdir "$functions" --output-metadata "$metadata" --production-source-bundle "$generated/base_translation_sources.bin" --no-function-files --prune-stale --threads "$translator_threads"
|
|
step emit-base-manifest 'Creating the local base translation manifest'
|
|
translator emit-base-manifest --project "$project" --out "$manifest_dir" --functions-dir "$functions" --translation-output-metadata "$metadata" --region P
|
|
if (( builds_retro )); then
|
|
mod_out="$workspace/build/mods/retro_rewind_full_cpp"; args=(translate-mod --project "$project" --profile retro-rewind --base-manifest "$manifest" --base-translation-output-metadata "$metadata" --code-pul "$retro_root/Binaries/Code.pul" --mod-root "$retro_root" --mod-name 'Retro Rewind' --region P --out "$mod_out" --prefer-cached-inputs --emit-cpp --threads "$translator_threads")
|
|
if (( skip_retro_wfc )); then args+=(--skip-retro-wfc); else offline_payload="$retro_wfc/binary/payload.RMCPD00.bin"; assert_file "$offline_payload" 'Offline Retro-WFC payload'; args+=(--retro-wfc-payload "$offline_payload"); fi
|
|
step translate-mod 'Translating Retro Rewind'; translator "${args[@]}"
|
|
fi
|
|
step generate-data-init 'Generating local game data initialization'; translator generate-data-init --project "$project"
|
|
args=(emit-build-shards --project "$project" --base-metadata "$metadata" --base-functions-dir "$functions" --native-source-dir "$workspace/runtime/src" --out "$shards")
|
|
if (( builds_retro )); then args+=(--resolved-profile "$mod_out/resolved_dispatch_profile.json" --retro-cpp-dir "$mod_out/cpp"); fi
|
|
step emit-build-shards 'Preparing native build shards'; translator "${args[@]}"
|
|
|
|
step configure-native 'Configuring the native toolchain'
|
|
"$cmake_bin" -S "$workspace/runtime" -B "$native_build" -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_MAKE_PROGRAM="$ninja_bin" -DMKW_TRANSLATED_COMPILE_JOBS="$translated_jobs"
|
|
targets=(); [[ "$profile" != retro-rewind ]] && targets+=(WiiCompiled); [[ "$profile" != base ]] && targets+=(RetroRewind)
|
|
step compile "Compiling ${targets[*]} locally"; "$cmake_bin" --build "$native_build" --target "${targets[@]}" --parallel "$global_jobs"
|
|
if [[ "$profile" != retro-rewind ]]; then "$script_dir/macos/publish-app.command" --build-dir "$native_build" --product WiiCompiled --output-dir "${base_output_dir:-$output_dir}"; fi
|
|
if (( builds_retro )); then "$script_dir/macos/publish-app.command" --build-dir "$native_build" --product RetroRewind --output-dir "$output_dir"; fi
|
|
printf 'MKWCBUILD:OUTPUT=%s\n' "$output_dir"
|