{ buildSystem ? builtins.currentSystem, targetSystem ? buildSystem, gitVersion ? null, release ? false, features ? null, }: let pkgsSrc = import ./nix/pkgs.nix; newBuildTarget = { nixPkgsSystem, rustTarget ? nixPkgsSystem, nativeBuildInputs ? pkgsCross: [], rustFlags ? pkgsCross: [], }: { inherit nixPkgsSystem rustTarget nativeBuildInputs rustFlags; }; # centralize per-target configuration in a single place. buildTargets = { "x86_64-linux" = newBuildTarget { nixPkgsSystem = "x86_64-unknown-linux-musl"; }; "i686-linux" = newBuildTarget { nixPkgsSystem = "i686-unknown-linux-musl"; }; "aarch64-linux" = newBuildTarget { nixPkgsSystem = "aarch64-unknown-linux-musl"; }; # Old Raspberry Pi's (not currently supported due to linking errors with # libsqlite3 and libsodium #"armv6l-linux" = newBuildTarget { # nixPkgsSystem = "armv6l-unknown-linux-musleabihf"; # rustTarget = "arm-unknown-linux-musleabihf"; #}; "x86_64-windows" = newBuildTarget { nixPkgsSystem = "x86_64-w64-mingw32"; rustTarget = "x86_64-pc-windows-gnu"; nativeBuildInputs = pkgsCross: [ pkgsCross.windows.pthreads ]; rustFlags = pkgsCross: [ "-C" "link-arg=-L${pkgsCross.windows.pthreads}/lib" ]; }; }; buildTarget = buildTargets.${targetSystem}; pkgs = import pkgsSrc { system = buildSystem; }; pkgsCross = import pkgsSrc { system = buildSystem; crossSystem.config = buildTarget.nixPkgsSystem; }; rustTarget = buildTarget.rustTarget; toolchain = let fenix = import (pkgs.fetchFromGitHub { owner = "nix-community"; repo = "fenix"; rev = "81ab0b4f7ae9ebb57daa0edf119c4891806e4d3a"; hash = "sha256-bZmI7ytPAYLpyFNgj5xirDkKuAniOkj1xHdv5aIJ5GM="; }) { system = buildSystem; }; mkToolchain = fenixTarget: fenixTarget.toolchainOf { channel = "1.68.2"; sha256 = "sha256-4vetmUhTUsew5FODnjlnQYInzyLNyDwocGa4IvMk3DM="; }; in fenix.combine [ (mkToolchain fenix).rustc (mkToolchain fenix).rustfmt (mkToolchain fenix).cargo (mkToolchain fenix).clippy (mkToolchain fenix.targets.${rustTarget}).rust-std ]; naersk = let naerskSrc = pkgs.fetchFromGitHub { owner = "nix-community"; repo = "naersk"; rev = "d9a33d69a9c421d64c8d925428864e93be895dcc"; hash = "sha256-e136hTT7LqQ2QjOTZQMW+jnsevWwBpMj78u6FRUsH9I="; }; in pkgs.callPackages naerskSrc { cargo = toolchain; rustc = toolchain; }; builtFeatures = if features != null then features else ( [ "garage/bundled-libs" "garage/sled" "garage/lmdb" "garage/k2v" ] ++ ( if release then [ "garage/consul-discovery" "garage/kubernetes-discovery" "garage/metrics" "garage/telemetry-otlp" "garage/sqlite" ] else [ ] ) ); # For some reason the pkgsCross.pkgsStatic build of libsodium doesn't contain # a `.a` file when compiled to a windows target, but rather contains # a `.dll.a` file which libsodium-sys doesn't pick up on. Copying the one to # the be the other seems to work. libsodium = pkgs.runCommand "libsodium-wrapped" { libsodium = pkgsCross.pkgsStatic.libsodium; } '' cp -rL "$libsodium" "$out" chmod -R +w "$out" if [ ! -e "$out"/lib/libsodium.a ] && [ -f "$out"/lib/libsodium.dll.a ]; then cp "$out"/lib/libsodium.dll.a "$out"/lib/libsodium.a fi ''; in rec { inherit pkgs pkgsCross; # Exported separately so it can be used from shell.nix buildEnv = rec { nativeBuildInputs = (buildTarget.nativeBuildInputs pkgsCross) ++ [ toolchain pkgs.protobuf # Required for shell because of rust dependency build scripts which must # run on the build system. pkgs.stdenv.cc ]; SODIUM_LIB_DIR = "${libsodium}/lib"; # Required because ring crate is special. This also seems to have # fixed some issues with the x86_64-windows cross-compile :shrug: TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; CARGO_BUILD_TARGET = rustTarget; CARGO_BUILD_RUSTFLAGS = [ "-C" "target-feature=+crt-static" "-C" "link-arg=-static" # https://github.com/rust-lang/cargo/issues/4133 "-C" "linker=${TARGET_CC}" ] ++ (buildTarget.rustFlags pkgsCross); }; build = naersk.buildPackage (rec { inherit release; src = ./.; strictDeps = true; doCheck = false; cargoBuildOptions = prev: prev++[ "--features=${builtins.concatStringsSep "," builtFeatures}" ]; } // buildEnv); }