diff --git a/src/build/compiler.rs b/src/build/compiler.rs index 3db58db..7177206 100644 --- a/src/build/compiler.rs +++ b/src/build/compiler.rs @@ -396,6 +396,27 @@ async fn compile_in_docker( cmd.arg("-e").arg(format!("CFLAGS_x86_64_pc_windows_msvc={cflags}")); cmd.arg("-e").arg(format!("CXXFLAGS_x86_64_pc_windows_msvc={cflags}")); } + Some("linux-arm64") | Some("linux-aarch64") => { + // aarch64 Linux cross-compile from an x86_64 host. Point cc-rs at + // the GNU cross toolchain so user-project native C/C++ deps build + // for aarch64 instead of the host. perry's own final link also uses + // aarch64-linux-gnu-gcc (see perry link/platform_cmd.rs), so the + // build container must provide the `gcc-aarch64-linux-gnu` package. + for cc_var in &["CC_aarch64_unknown_linux_gnu", "CC_aarch64-unknown-linux-gnu"] { + cmd.arg("-e").arg(format!("{cc_var}=aarch64-linux-gnu-gcc")); + } + for cxx_var in &["CXX_aarch64_unknown_linux_gnu", "CXX_aarch64-unknown-linux-gnu"] { + cmd.arg("-e").arg(format!("{cxx_var}=aarch64-linux-gnu-g++")); + } + for ar_var in &["AR_aarch64_unknown_linux_gnu", "AR_aarch64-unknown-linux-gnu"] { + cmd.arg("-e").arg(format!("{ar_var}=aarch64-linux-gnu-ar")); + } + // cargo's own linker var for the aarch64 leg (build-deps / proc-macro + // stay on host; only the target leg is redirected). + cmd.arg("-e").arg( + "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc", + ); + } _ => {} } diff --git a/src/build/pipeline.rs b/src/build/pipeline.rs index 8f3a034..26a2aef 100644 --- a/src/build/pipeline.rs +++ b/src/build/pipeline.rs @@ -79,6 +79,9 @@ async fn run_pipeline( BuildTarget::Ios => Some("ios"), BuildTarget::Macos => Some("macos"), BuildTarget::Tvos => Some("tvos"), + // aarch64 Linux is a cross-compile even on a Linux host, so it must + // pass an explicit --target (unlike native x86_64 Linux below). + BuildTarget::LinuxArm64 => Some("linux-arm64"), BuildTarget::Linux => None, // native compilation on Linux host }; // For ios-game-loop: swap the runtime with the game-loop variant @@ -140,7 +143,7 @@ async fn run_pipeline( } match target { - BuildTarget::Linux => { + BuildTarget::Linux | BuildTarget::LinuxArm64 => { run_linux_pipeline(request, cancelled, progress, tmpdir, &actual_binary, &project_dir) .await } @@ -722,6 +725,7 @@ fn copy_artifact( #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum BuildTarget { Linux, + LinuxArm64, Android, Windows, Ios, @@ -737,6 +741,9 @@ fn determine_target(targets: &[String]) -> BuildTarget { "ios" => return BuildTarget::Ios, "macos" => return BuildTarget::Macos, "tvos" => return BuildTarget::Tvos, + // aarch64 Linux: cross-compiled (the builder host is x86_64) and + // packaged the same as x86_64 Linux — the binary is just aarch64. + "linux-arm64" | "linux-aarch64" => return BuildTarget::LinuxArm64, _ => {} } } diff --git a/src/worker.rs b/src/worker.rs index 6f47ec9..46fc49a 100644 --- a/src/worker.rs +++ b/src/worker.rs @@ -543,7 +543,7 @@ async fn connect_and_run(config: &WorkerConfig) -> Result<(), String> { // Send worker_hello let perry_version = get_perry_version(&config.perry_binary); let hello = WorkerMessage::WorkerHello { - capabilities: vec!["linux".into(), "android".into(), "windows".into(), "ios".into(), "macos".into(), "tvos".into()], + capabilities: vec!["linux".into(), "linux-arm64".into(), "android".into(), "windows".into(), "ios".into(), "macos".into(), "tvos".into(), "watchos".into()], name: config.worker_name.clone().unwrap_or_else(|| { hostname::get() .map(|h| h.to_string_lossy().to_string()) @@ -823,6 +823,7 @@ async fn handle_build( // re-queued for signing — the unsigned .app was returned as a // "final" artifact and never reached TestFlight. "tvos" => "ios-precompiled", + "watchos" => "ios-precompiled", "macos" => "macos-precompiled", other => other, }; @@ -862,6 +863,8 @@ async fn handle_build( "windows" => Some("windows"), "ios" => Some("ios"), "macos" => Some("macos"), + "tvos" => Some("tvos"), + "watchos" => Some("watchos"), _ => None, }, "artifacts": [{"name": artifact_name, "size": size, "sha256": sha256}]