diff --git a/architecture/build.md b/architecture/build.md index 972f847bb9..4c8cb855e3 100644 --- a/architecture/build.md +++ b/architecture/build.md @@ -77,6 +77,23 @@ continue to opt in with `bundled-z3`. ## Linux Runtime Environments +### macOS-hosted ARM64 musl CLI builds + +On Apple Silicon macOS, `nix develop .#crossShells.aarch64-darwin.aarch64-linux.musl` provides a +Darwin-hosted toolchain for building Linux ARM64 musl binaries. Its `cargo` +shim dispatches `cargo build` through `cargo-zigbuild` with the +`aarch64-unknown-linux-musl` target, so a plain CLI build produces +`target/aarch64-unknown-linux-musl//openshell`. The resulting static +ELF binary is intended for a Linux guest VM; this shell is not a Linux runtime +environment and does not replace `devShells.aarch64-linux.musl`, which remains +the native Linux shell used in ARM64 Linux CI. + +`nix develop .#crossShells.aarch64-darwin.aarch64-linux.gnu` provides the +corresponding gateway shell. Its Cargo shim uses Zig's glibc 2.28 target while +Cargo writes artifacts beneath `target/aarch64-unknown-linux-gnu/`. It supplies +a Nix-built static ARM64 Z3 library, matching the default-feature gateway CI +build without enabling `bundled-z3`. + OpenShell uses different Linux libc environments for different host artifacts. The standalone `openshell` CLI is built as a static musl binary so it can run on a wide range of Linux distributions without depending on the host's glibc. Host diff --git a/flake.nix b/flake.nix index e361fd1597..6827084509 100644 --- a/flake.nix +++ b/flake.nix @@ -37,7 +37,8 @@ rust-overlay, ... }: - flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] ( + let + perSystem = flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" ] ( system: let pkgs = import nixpkgs { @@ -100,6 +101,14 @@ ++ commonDevShellPackages; }; } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin { + cross-aarch64-linux-musl = import ./nix/devShells/cross-aarch64-linux-musl.nix { + inherit pkgs rust-overlay commonDevShellPackages; + }; + cross-aarch64-linux-gnu = import ./nix/devShells/cross-aarch64-linux-gnu.nix { + inherit pkgs rust-overlay commonDevShellPackages; + }; + } // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { glibc-2-28 = import ./nix/devShells/glibc-2-28.nix { inherit pkgs rust-overlay commonDevShellPackages; @@ -111,5 +120,13 @@ formatter = treefmtEval.config.build.wrapper; } - ); + ); + in + perSystem + // { + # Cross-shell names describe the Linux target, rather than the Darwin + # execution platform that runs their toolchains. + crossShells.aarch64-darwin.aarch64-linux.musl = perSystem.devShells.aarch64-darwin.cross-aarch64-linux-musl; + crossShells.aarch64-darwin.aarch64-linux.gnu = perSystem.devShells.aarch64-darwin.cross-aarch64-linux-gnu; + }; } diff --git a/nix/devShells/cross-aarch64-linux-gnu.nix b/nix/devShells/cross-aarch64-linux-gnu.nix new file mode 100644 index 0000000000..fa17922921 --- /dev/null +++ b/nix/devShells/cross-aarch64-linux-gnu.nix @@ -0,0 +1,22 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +{ + pkgs, + rust-overlay, + commonDevShellPackages, +}: + +let + crossPkgs = pkgs.pkgsCross.aarch64-multiplatform; + z3-static = crossPkgs.callPackage ../pkgs/z3-static.nix { }; +in +import ./cross-rust.nix { + inherit pkgs rust-overlay commonDevShellPackages; + rustTarget = "aarch64-unknown-linux-gnu"; + zigTarget = "aarch64-unknown-linux-gnu.2.28"; + extraPackages = [ z3-static ]; + # CI builds the gateway against a Nix-provided static Z3. Keep the same + # default-feature behavior while supplying the ARM64 Linux target library. + shellAttributes.Z3_LIBRARY_PATH_OVERRIDE = "${z3-static}/lib"; +} diff --git a/nix/devShells/cross-aarch64-linux-musl.nix b/nix/devShells/cross-aarch64-linux-musl.nix new file mode 100644 index 0000000000..f1f4699b86 --- /dev/null +++ b/nix/devShells/cross-aarch64-linux-musl.nix @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +{ + pkgs, + rust-overlay, + commonDevShellPackages, +}: + +import ./cross-rust.nix { + inherit pkgs rust-overlay commonDevShellPackages; + rustTarget = "aarch64-unknown-linux-musl"; +} diff --git a/nix/devShells/cross-rust.nix b/nix/devShells/cross-rust.nix new file mode 100644 index 0000000000..fce4d2017e --- /dev/null +++ b/nix/devShells/cross-rust.nix @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +{ + pkgs, + rust-overlay, + commonDevShellPackages, + rustTarget, + zigTarget ? rustTarget, + extraPackages ? [ ], + shellAttributes ? { }, +}: + +let + rust-bin = rust-overlay.lib.mkRustBin { } pkgs; + rustToolchain = (rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml).override { + enableLibsecret = false; + targets = [ rustTarget ]; + }; + cargo = pkgs.writeShellScriptBin "cargo" '' + if [[ $# -gt 0 && $1 == build ]]; then + shift + # Keep the real Cargo ahead of this shim so cargo-zigbuild can invoke it + # without recursively dispatching back into this script. + export PATH=${rustToolchain}/bin:${pkgs.cargo-zigbuild}/bin:${pkgs.zig}/bin:$PATH + exec ${pkgs.cargo-zigbuild}/bin/cargo-zigbuild zigbuild --target ${zigTarget} "$@" + fi + + exec ${rustToolchain}/bin/cargo "$@" + ''; +in +pkgs.mkShell ( + { + packages = [ + cargo + rustToolchain + pkgs.cargo-zigbuild + pkgs.zig + ] + ++ extraPackages + ++ commonDevShellPackages; + } + // shellAttributes +)