{ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; flake-utils.url = "github:numtide/flake-utils"; nix-filter.url = "github:numtide/nix-filter"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs = { nixpkgs.follows = "nixpkgs"; }; }; crane = { url = "github:ipetkov/crane"; inputs = { nixpkgs.follows = "nixpkgs"; }; }; advisory-db = { url = "github:rustsec/advisory-db"; flake = false; }; }; outputs = { self, nixpkgs, nix-filter, rust-overlay, crane, advisory-db, flake-utils }: flake-utils.lib.eachDefaultSystem (system: let overlays = [ (import rust-overlay) (final: prev: { nix-filter = nix-filter.lib; rust-toolchain = pkgs.rust-bin.stable.latest.default; rust-dev-toolchain = pkgs.rust-toolchain.override { extensions = [ "rust-src" ]; }; }) ]; pkgs = import nixpkgs { inherit system overlays; }; craneLib = (crane.mkLib pkgs).overrideToolchain pkgs.rust-toolchain; lib = pkgs.lib; stdenv = pkgs.stdenv; commonNativeBuildInputs = with pkgs; [ libiconv libtool libxml2 libxslt llvmPackages.libclang openssl pkg-config xmlsec ]; fixtureFilter = path: _type: builtins.match ".*test_vectors.*" path != null || builtins.match ".*\.h" path != null; sourceAndFixtures = path: type: (fixtureFilter path type) || (craneLib.filterCargoSources path type); src = lib.cleanSourceWith { src = ./.; filter = sourceAndFixtures; }; cargoFile = builtins.fromTOML (builtins.readFile ./Cargo.toml); commonArgs = { pname = "samael"; inherit src; version = cargoFile.package.version; # Need to tell bindgen where to find libclang LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; # Set C flags for Rust's bindgen program. Unlike ordinary C # compilation, bindgen does not invoke $CC directly. Instead it # uses LLVM's libclang. To make sure all necessary flags are # included we need to look in a few places. # See https://web.archive.org/web/20220523141208/https://hoverbear.org/blog/rust-bindgen-in-nix/ BINDGEN_EXTRA_CLANG_ARGS = "${builtins.readFile "${stdenv.cc}/nix-support/libc-crt1-cflags"} \ ${builtins.readFile "${stdenv.cc}/nix-support/libc-cflags"} \ ${builtins.readFile "${stdenv.cc}/nix-support/cc-cflags"} \ ${builtins.readFile "${stdenv.cc}/nix-support/libcxx-cxxflags"} \ -idirafter ${pkgs.libiconv}/include \ ${lib.optionalString stdenv.cc.isClang "-idirafter ${stdenv.cc.cc}/lib/clang/${lib.getVersion stdenv.cc.cc}/include"} \ ${lib.optionalString stdenv.cc.isGNU "-isystem ${stdenv.cc.cc}/include/c++/${lib.getVersion stdenv.cc.cc} -isystem ${stdenv.cc.cc}/include/c++/${lib.getVersion stdenv.cc.cc}/${stdenv.hostPlatform.config} -idirafter ${stdenv.cc.cc}/lib/gcc/${stdenv.hostPlatform.config}/${lib.getVersion stdenv.cc.cc}/include"} \ "; nativeBuildInputs = commonNativeBuildInputs; cargoExtraArgs = "--features xmlsec"; cargoTestExtraArgs = "--features xmlsec"; }; # Build *just* the cargo dependencies, so we can reuse # all of that work (e.g. via cachix) when running in CI cargoArtifacts = craneLib.buildDepsOnly commonArgs; samael = craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); in rec { # `nix build` packages.default = samael; # `nix develop` devShells.default = pkgs.mkShell { # Need to tell bindgen where to find libclang LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; # Set C flags for Rust's bindgen program. Unlike ordinary C # compilation, bindgen does not invoke $CC directly. Instead it # uses LLVM's libclang. To make sure all necessary flags are # included we need to look in a few places. # See https://web.archive.org/web/20220523141208/https://hoverbear.org/blog/rust-bindgen-in-nix/ BINDGEN_EXTRA_CLANG_ARGS = "${builtins.readFile "${stdenv.cc}/nix-support/libc-crt1-cflags"} \ ${builtins.readFile "${stdenv.cc}/nix-support/libc-cflags"} \ ${builtins.readFile "${stdenv.cc}/nix-support/cc-cflags"} \ ${builtins.readFile "${stdenv.cc}/nix-support/libcxx-cxxflags"} \ -idirafter ${pkgs.libiconv}/include \ ${lib.optionalString stdenv.cc.isClang "-idirafter ${stdenv.cc.cc}/lib/clang/${lib.getVersion stdenv.cc.cc}/include"} \ ${lib.optionalString stdenv.cc.isGNU "-isystem ${stdenv.cc.cc}/include/c++/${lib.getVersion stdenv.cc.cc} -isystem ${stdenv.cc.cc}/include/c++/${lib.getVersion stdenv.cc.cc}/${stdenv.hostPlatform.config} -idirafter ${stdenv.cc.cc}/lib/gcc/${stdenv.hostPlatform.config}/${lib.getVersion stdenv.cc.cc}/include"} \ "; buildInputs = with pkgs; [ rust-dev-toolchain nixpkgs-fmt ]; nativeBuildInputs = commonNativeBuildInputs; }; checks = { # Build the crate as part of `nix flake check` for convenience inherit samael; # Run clippy (and deny all warnings) on the crate source, # again, resuing the dependency artifacts from above. # # Note that this is done as a separate derivation so that # we can block the CI if there are issues here, but not # prevent downstream consumers from building our crate by itself. samael-clippy = craneLib.cargoClippy (commonArgs // { inherit cargoArtifacts; cargoClippyExtraArgs = "--all-targets"; #-- --deny warnings }); samael-doc = craneLib.cargoDoc (commonArgs // { inherit cargoArtifacts; }); # Check formatting samael-fmt = craneLib.cargoFmt { inherit src; }; # Audit dependencies samael-audit = craneLib.cargoAudit { inherit src advisory-db; }; # Run tests with cargo-nextest # Consider setting `doCheck = false` on `samael` if you do not want # the tests to run twice samael-nextest = craneLib.cargoNextest (commonArgs // { inherit cargoArtifacts; cargoExtraArgs = ""; cargoNextestExtraArgs = "--features xmlsec"; partitions = 1; partitionType = "count"; }); }; }); }