diff --git a/flake.lock b/flake.lock index 2c7be871..59ff5c67 100644 --- a/flake.lock +++ b/flake.lock @@ -1,28 +1,17 @@ { "nodes": { - "cargo2nix": { - "inputs": { - "flake-compat": [ - "flake-compat" - ], - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ], - "rust-overlay": "rust-overlay" - }, + "crane": { "locked": { - "lastModified": 1705129117, - "narHash": "sha256-LgdDHibvimzYhxBK3kxCk2gAL7k4Hyigl5KI0X9cijA=", - "owner": "cargo2nix", - "repo": "cargo2nix", - "rev": "ae19a9e1f8f0880c088ea155ab66cee1fa001f59", + "lastModified": 1737689766, + "narHash": "sha256-ivVXYaYlShxYoKfSo5+y5930qMKKJ8CLcAoIBPQfJ6s=", + "owner": "ipetkov", + "repo": "crane", + "rev": "6fe74265bbb6d016d663b1091f015e2976c4a527", "type": "github" }, "original": { - "owner": "cargo2nix", - "repo": "cargo2nix", - "rev": "ae19a9e1f8f0880c088ea155ab66cee1fa001f59", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, @@ -42,12 +31,15 @@ } }, "flake-utils": { + "inputs": { + "systems": "systems" + }, "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", "owner": "numtide", "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { @@ -74,34 +66,45 @@ }, "root": { "inputs": { - "cargo2nix": "cargo2nix", + "crane": "crane", "flake-compat": "flake-compat", - "flake-utils": [ - "cargo2nix", - "flake-utils" - ], - "nixpkgs": "nixpkgs" + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" } }, "rust-overlay": { "inputs": { "nixpkgs": [ - "cargo2nix", "nixpkgs" ] }, "locked": { - "lastModified": 1736649126, - "narHash": "sha256-XCw5sv/ePsroqiF3lJM6Y2X9EhPdHeE47gr3Q8b0UQw=", + "lastModified": 1738376888, + "narHash": "sha256-S6ErHxkSm0iA7ZMsjjDaASWxbELYcdfv8BhOkkj1rHw=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "162ab0edc2936508470199b2e8e6c444a2535019", + "rev": "83284068670d5ae4a43641c4afb150f3446be70d", "type": "github" }, "original": { "owner": "oxalica", "repo": "rust-overlay", - "rev": "162ab0edc2936508470199b2e8e6c444a2535019", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", "type": "github" } } diff --git a/flake.nix b/flake.nix index b1cb7dbb..4f046bbd 100644 --- a/flake.nix +++ b/flake.nix @@ -8,29 +8,14 @@ inputs.flake-compat.url = "github:nix-community/flake-compat"; - inputs.cargo2nix = { - # As of 2022-10-18: two small patches over unstable branch, one for clippy and one to fix feature detection - #url = "github:Alexis211/cargo2nix/a7a61179b66054904ef6a195d8da736eaaa06c36"; + inputs.flake-utils.url = "github:numtide/flake-utils"; - # As of 2023-04-25: - # - my two patches were merged into unstable (one for clippy and one to "fix" feature detection) - # - rustc v1.66 - # url = "github:cargo2nix/cargo2nix/8fb57a670f7993bfc24099c33eb9c5abb51f29a2"; + inputs.crane.url = "github:ipetkov/crane"; - # Mainline cargo2nix as of of 2025-01-12 (branch release-0.11.0) - url = "github:cargo2nix/cargo2nix/ae19a9e1f8f0880c088ea155ab66cee1fa001f59"; + inputs.rust-overlay.url = "github:oxalica/rust-overlay"; + inputs.rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; - # Rust overlay as of 2025-01-12 - inputs.rust-overlay.url = - "github:oxalica/rust-overlay/162ab0edc2936508470199b2e8e6c444a2535019"; - - inputs.nixpkgs.follows = "nixpkgs"; - inputs.flake-compat.follows = "flake-compat"; - }; - - inputs.flake-utils.follows = "cargo2nix/flake-utils"; - - outputs = { self, nixpkgs, cargo2nix, flake-utils, ... }: + outputs = { self, nixpkgs, flake-utils, crane, rust-overlay, ... }: let git_version = self.lastModifiedDate; compile = import ./nix/compile.nix; @@ -42,52 +27,48 @@ { packages = let - packageFor = target: (compile { - inherit system git_version target; - pkgsSrc = nixpkgs; - cargo2nixOverlay = cargo2nix.overlays.default; - release = true; - }).workspace.garage { compileMode = "build"; }; + packageFor = target: release: (compile { + inherit system git_version target nixpkgs crane rust-overlay release; + }).garage; in { # default = native release build - default = packageFor null; + default = packageFor null true; # other = cross-compiled, statically-linked builds - amd64 = packageFor "x86_64-unknown-linux-musl"; - i386 = packageFor "i686-unknown-linux-musl"; - arm64 = packageFor "aarch64-unknown-linux-musl"; - arm = packageFor "armv6l-unknown-linux-musl"; + amd64 = packageFor "x86_64-unknown-linux-musl" true; + i386 = packageFor "i686-unknown-linux-musl" true; + arm64 = packageFor "aarch64-unknown-linux-musl" true; + arm = packageFor "armv6l-unknown-linux-musl" true; + # non-optimized packages + dev = packageFor null false; + dev-amd64 = packageFor "x86_64-unknown-linux-musl" false; + dev-i386 = packageFor "i686-unknown-linux-musl" false; + dev-arm64 = packageFor "aarch64-unknown-linux-musl" false; + dev-arm = packageFor "armv6l-unknown-linux-musl" false; }; # ---- developpment shell, for making native builds only ---- devShells = let - shellWithPackages = (packages: (compile { - inherit system git_version; - pkgsSrc = nixpkgs; - cargo2nixOverlay = cargo2nix.overlays.default; - }).workspaceShell { inherit packages; }); + targets = compile { + inherit system git_version nixpkgs crane rust-overlay; + }; in { - default = shellWithPackages - (with pkgs; [ - rustfmt - clang - mold - ]); + default = targets.devShell; # import the full shell using `nix develop .#full` - full = shellWithPackages (with pkgs; [ - rustfmt - rust-analyzer - clang - mold - # ---- extra packages for dev tasks ---- - cargo-audit - cargo-outdated - cargo-machete - nixpkgs-fmt - ]); + full = pkgs.mkShell { + buildInputs = with pkgs; [ + targets.toolchain + # ---- extra packages for dev tasks ---- + rust-analyzer + cargo-audit + cargo-outdated + cargo-machete + nixpkgs-fmt + ]; + }; }; }); } diff --git a/nix/compile.nix b/nix/compile.nix index 9630b5dd..7520a271 100644 --- a/nix/compile.nix +++ b/nix/compile.nix @@ -1,83 +1,52 @@ -{ system, target ? null, pkgsSrc, cargo2nixOverlay -, release ? false, git_version ? null, features ? null, }: +{ + /* build inputs */ + nixpkgs, + crane, + rust-overlay, + + /* parameters */ + system, + git_version ? "unknown", + target ? null, + release ? false, + features ? null, +}: let log = v: builtins.trace v v; - pkgs = if target != null then - import pkgsSrc { + pkgs = + import nixpkgs { inherit system; - crossSystem = { - config = target; - isStatic = true; - }; - overlays = [ cargo2nixOverlay ]; - } - else - import pkgsSrc { - inherit system; - overlays = [ cargo2nixOverlay ]; + overlays = [ (import rust-overlay) ]; }; - toolchainOptions = { - rustVersion = "1.78.0"; - extraRustComponents = [ "clippy" ]; + inherit (pkgs) lib; + + toolchain = pkgs.symlinkJoin { + name = "garage-rust-toolchain-1.78"; + paths = [ + (pkgs.rust-bin.stable."1.78.0".default.override { + targets = [ + "arm-unknown-linux-musleabihf" + "aarch64-unknown-linux-musl" + "i686-unknown-linux-musl" + "x86_64-unknown-linux-musl" + ]; + extensions = [ + "rust-src" + "rustfmt" + ]; + }) + pkgs.clang + pkgs.mold + pkgs.protobuf + ]; }; - /* Cargo2nix provides many overrides by default, you can take inspiration from them: - https://github.com/cargo2nix/cargo2nix/blob/master/overlay/overrides.nix + craneLib = (crane.mkLib pkgs).overrideToolchain toolchain; - You can have a complete list of the available options by looking at the overriden object, mkcrate: - https://github.com/cargo2nix/cargo2nix/blob/master/overlay/mkcrate.nix - */ - packageOverrides = pkgs: - pkgs.rustBuilder.overrides.all ++ [ - /* [1] We need to alter Nix hardening to make static binaries: PIE, - Position Independent Executables seems to be supported only on amd64. Having - this flag set either 1. make our executables crash or 2. compile as dynamic on some platforms. - Here, we deactivate it. Later (find `codegenOpts`), we reactivate it for supported targets - (only amd64 curently) through the `-static-pie` flag. - PIE is a feature used by ASLR, which helps mitigate security issues. - Learn more about Nix Hardening at: https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/cc-wrapper/add-hardening.sh - - [2] We want to inject the git version while keeping the build deterministic. - As we do not want to consider the .git folder as part of the input source, - we ask the user (the CI often) to pass the value to Nix. - - [3] We don't want libsodium-sys and zstd-sys to try to use pkgconfig to build against a system library. - However the features to do so get activated for some reason (due to a bug in cargo2nix?), - so disable them manually here. - */ - (pkgs.rustBuilder.rustLib.makeOverride { - name = "garage"; - overrideAttrs = drv: - (if git_version != null then { - # [2] - preConfigure = '' - ${drv.preConfigure or ""} - export GIT_VERSION="${git_version}" - ''; - } else - { }) // { - # [1] - hardeningDisable = [ "pie" ]; - }; - }) - - (pkgs.rustBuilder.rustLib.makeOverride { - name = "libsodium-sys"; - overrideArgs = old: { - features = [ ]; # [3] - }; - }) - - (pkgs.rustBuilder.rustLib.makeOverride { - name = "zstd-sys"; - overrideArgs = old: { - features = [ ]; # [3] - }; - }) - ]; + src = craneLib.cleanCargoSource ../.; /* We ship some parts of the code disabled by default by putting them behind a flag. It speeds up the compilation (when the feature is not required) and released crates have less dependency by default (less attack surface, disk space, etc.). @@ -87,16 +56,16 @@ let rootFeatures = if features != null then features else - ([ "garage/bundled-libs" "garage/lmdb" "garage/sqlite" "garage/k2v" ] ++ (if release then [ - "garage/consul-discovery" - "garage/kubernetes-discovery" - "garage/metrics" - "garage/telemetry-otlp" - "garage/syslog" + ([ "bundled-libs" "lmdb" "sqlite" "k2v" ] ++ (if release then [ + "consul-discovery" + "kubernetes-discovery" + "metrics" + "telemetry-otlp" + "syslog" ] else [ ])); - packageFun = import ../Cargo.nix; + featuresStr = lib.concatStringsSep "," rootFeatures; /* We compile fully static binaries with musl to simplify deployment on most systems. When possible, we reactivate PIE hardening (see above). @@ -107,8 +76,7 @@ let For more information on static builds, please refer to Rust's RFC 1721. https://rust-lang.github.io/rfcs/1721-crt-static.html#specifying-dynamicstatic-c-runtime-linkage */ - - codegenOpts = { + codegenOptsMap = { "armv6l-unknown-linux-musleabihf" = [ "target-feature=+crt-static" "link-arg=-static" @@ -131,8 +99,51 @@ let else target; -in pkgs.rustBuilder.makePackageSet ({ - inherit release packageFun packageOverrides codegenOpts rootFeatures; - target = rustTarget; - workspaceSrc = pkgs.lib.cleanSource ../.; -} // toolchainOptions) + codegenOpts = if target != null then codegenOptsMap.${target} else [ + "link-args=-fuse-ld=mold" + ]; + + commonArgs = + { + inherit src; + pname = "garage"; + version = git_version; + + strictDeps = true; + cargoExtraArgs = "--features ${featuresStr}"; + + GIT_VERSION = git_version; + + CARGO_PROFILE = if release then "release" else "dev"; + CARGO_BUILD_RUSTFLAGS = + lib.concatStringsSep + " " + (builtins.map (flag: "-C ${flag}") codegenOpts); + } + // + (if rustTarget != null then { + CARGO_BUILD_TARGET = rustTarget; + } else {}); + +in rec { + inherit toolchain; + + devShell = pkgs.mkShell { + buildInputs = [ + toolchain + ]; + }; + + garage-deps = craneLib.buildDepsOnly commonArgs; + + garage = craneLib.buildPackage (commonArgs // { + cargoArtifacts = garage-deps; + doCheck = false; + }); + + garage-test = craneLib.cargoTest (commonArgs // { + cargoTestExtraArgs = "--workspace"; + cargoArtifacts = garage; + CARGO_PROFILE = "test"; + }); +}