From 551fe3b3494bb36119d88370ed0281eac107c53e Mon Sep 17 00:00:00 2001 From: Michal Rus Date: Wed, 22 Oct 2025 12:59:08 +0200 Subject: [PATCH] Add a Nix flake with a devshell, and package builds Resolves https://github.com/blockfrost/blockfrost-ops/issues/2023 --- .envrc | 3 + .gitignore | 8 + Cargo.lock | 2 +- flake.lock | 210 ++++++++++++++++++++++++++ flake.nix | 118 +++++++++++++++ modules/genesis_bootstrapper/build.rs | 2 +- modules/parameters_state/build.rs | 2 +- modules/rest_blockfrost/src/utils.rs | 32 +++- nix/devshells.nix | 76 ++++++++++ nix/internal/darwin.nix | 9 ++ nix/internal/linux.nix | 6 + nix/internal/unix.nix | 202 +++++++++++++++++++++++++ nix/internal/windows.nix | 63 ++++++++ 13 files changed, 728 insertions(+), 5 deletions(-) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/devshells.nix create mode 100644 nix/internal/darwin.nix create mode 100644 nix/internal/linux.nix create mode 100644 nix/internal/unix.nix create mode 100644 nix/internal/windows.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..af3b9a0d --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +use flake + +source_env_if_exists .envrc.local diff --git a/.gitignore b/.gitignore index 54f6dcfb..5e91248b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,10 @@ target README.html + +# Nix +result +result-* + +# direnv +.direnv/ +.envrc.local diff --git a/Cargo.lock b/Cargo.lock index 39d2c47b..f5e3237a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1509,7 +1509,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.107", ] [[package]] diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..0e3ba8e9 --- /dev/null +++ b/flake.lock @@ -0,0 +1,210 @@ +{ + "nodes": { + "advisory-db": { + "flake": false, + "locked": { + "lastModified": 1759506957, + "narHash": "sha256-czXIV7Yxo4MlBnItk0h6nomIcgUbq0qmOa8a7/fzKjI=", + "owner": "rustsec", + "repo": "advisory-db", + "rev": "ce9208c0021cd8a6b66ff4b345171e8eedd0441c", + "type": "github" + }, + "original": { + "owner": "rustsec", + "repo": "advisory-db", + "type": "github" + } + }, + "cardano-playground": { + "flake": false, + "locked": { + "lastModified": 1753409121, + "narHash": "sha256-TrpWmHFHjgrU5TopI0CdoPSGmJPcAXzfTOAmUX86Gp8=", + "owner": "input-output-hk", + "repo": "cardano-playground", + "rev": "56ebfef5595c43014029b039ade01b0ef06233e0", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-playground", + "rev": "56ebfef5595c43014029b039ade01b0ef06233e0", + "type": "github" + } + }, + "crane": { + "locked": { + "lastModified": 1758215636, + "narHash": "sha256-8nkzkPbdxze8CxWhKWlcLbJEU1vfLM/nVqRlTy17V54=", + "owner": "ipetkov", + "repo": "crane", + "rev": "a669fe77a8b0cd6f11419d89ea45a16691ca5121", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "devshell": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1741473158, + "narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=", + "owner": "numtide", + "repo": "devshell", + "rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1758264155, + "narHash": "sha256-sgg1sd/pYO9C7ccY9tAvR392CDscx8sqXrHkxspjIH0=", + "owner": "nix-community", + "repo": "fenix", + "rev": "a7d9df0179fcc48259a68b358768024f8e5a6372", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1749398372, + "narHash": "sha256-tYBdgS56eXYaWVW3fsnPQ/nFlgWi/Z2Ymhyu21zVM98=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9305fe4e5c2a6fcf5ba6a3ff155720fbe4076569", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1751211869, + "narHash": "sha256-1Cu92i1KSPbhPCKxoiVG5qnoRiKTgR5CcGSRyLpOd7Y=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "b43c397f6c213918d6cfe6e3550abfe79b5d1c51", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-25.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1748740939, + "narHash": "sha256-rQaysilft1aVMwF14xIdGS3sj1yHlI6oKQNBRTF40cc=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "656a64127e9d791a334452c6b6606d17539476e2", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "advisory-db": "advisory-db", + "cardano-playground": "cardano-playground", + "crane": "crane", + "devshell": "devshell", + "fenix": "fenix", + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "sanchonet": "sanchonet", + "treefmt-nix": "treefmt-nix" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1758224093, + "narHash": "sha256-buZMH6NgzSLowTda+aArct5ISsMR/S888EdFaqUvbog=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "958a8d06e3e5ba7dca7cc23b0639335071d65f2a", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "sanchonet": { + "flake": false, + "locked": { + "lastModified": 1756256403, + "narHash": "sha256-kCoDLuvArSw6o5aPLuBjSZy1z4ByAcQRxNIX/x9aH9M=", + "owner": "Hornan7", + "repo": "SanchoNet-Tutorials", + "rev": "c4518aba61287c07aa70f4c2a8250aae0e4be57a", + "type": "github" + }, + "original": { + "owner": "Hornan7", + "repo": "SanchoNet-Tutorials", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1750931469, + "narHash": "sha256-0IEdQB1nS+uViQw4k3VGUXntjkDp7aAlqcxdewb/hAc=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "ac8e6f32e11e9c7f153823abc3ab007f2a65d3e1", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..c9a82a2f --- /dev/null +++ b/flake.nix @@ -0,0 +1,118 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + flake-parts.url = "github:hercules-ci/flake-parts"; + treefmt-nix.url = "github:numtide/treefmt-nix"; + treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; + crane.url = "github:ipetkov/crane"; + fenix.url = "github:nix-community/fenix"; + fenix.inputs.nixpkgs.follows = "nixpkgs"; + devshell.url = "github:numtide/devshell"; + devshell.inputs.nixpkgs.follows = "nixpkgs"; + cardano-playground.url = "github:input-output-hk/cardano-playground/56ebfef5595c43014029b039ade01b0ef06233e0"; + cardano-playground.flake = false; # otherwise, +9k dependencies in flake.lock… + sanchonet.url = "github:Hornan7/SanchoNet-Tutorials"; + sanchonet.flake = false; + advisory-db.url = "github:rustsec/advisory-db"; + advisory-db.flake = false; + }; + + outputs = inputs: let + inherit (inputs.nixpkgs) lib; + in + inputs.flake-parts.lib.mkFlake {inherit inputs;} ({config, ...}: { + imports = [ + inputs.devshell.flakeModule + inputs.treefmt-nix.flakeModule + ]; + + systems = [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + "x86_64-darwin" + ]; + perSystem = {system, ...}: let + internal = inputs.self.internal.${system}; + in { + packages = + { + default = internal.acropolis-process-omnibus; + inherit (internal) acropolis-process-omnibus acropolis-process-replayer; + } + // (lib.optionalAttrs (system == "x86_64-linux") { + acropolis-process-omnibus-x86_64-windows = inputs.self.internal.x86_64-windows.acropolis-process-omnibus; + acropolis-process-replayer-x86_64-windows = inputs.self.internal.x86_64-windows.acropolis-process-replayer; + }); + + devshells.default = import ./nix/devshells.nix {inherit inputs;}; + + checks = internal.cargoChecks // internal.nixChecks; + + treefmt = + /* + { pkgs, ...} + */ + _: { + projectRootFile = "flake.nix"; + programs = { + alejandra.enable = true; # Nix + # TODO: enable them one by one (large commits, mostly whitespace): + #prettier.enable = true; + #rustfmt.enable = true; + #rustfmt.package = internal.rustfmt; + #yamlfmt.enable = pkgs.system != "x86_64-darwin"; # a treefmt-nix+yamlfmt bug on Intel Macs + #taplo.enable = true; # TOML + #shfmt.enable = true; + }; + # settings.formatter.rustfmt.options = [ + # "--config-path" + # (builtins.path { + # name = "rustfmt.toml"; + # path = ./rustfmt.toml; + # }) + # ]; + }; + }; + + flake = { + internal = + lib.genAttrs config.systems ( + targetSystem: import ./nix/internal/unix.nix {inherit inputs targetSystem;} + ) + // lib.genAttrs ["x86_64-windows"] ( + targetSystem: import ./nix/internal/windows.nix {inherit inputs targetSystem;} + ); + + hydraJobs = let + crossSystems = ["x86_64-windows"]; + allJobs = { + acropolis-process-omnibus = lib.genAttrs (config.systems ++ crossSystems) ( + targetSystem: inputs.self.internal.${targetSystem}.acropolis-process-omnibus + ); + acropolis-process-replayer = lib.genAttrs (config.systems ++ crossSystems) ( + targetSystem: inputs.self.internal.${targetSystem}.acropolis-process-replayer + ); + devshell = lib.genAttrs config.systems ( + targetSystem: inputs.self.devShells.${targetSystem}.default + ); + inherit (inputs.self) checks; + }; + in + allJobs + // { + required = inputs.nixpkgs.legacyPackages.x86_64-linux.releaseTools.aggregate { + name = "github-required"; + meta.description = "All jobs required to pass CI"; + constituents = lib.collect lib.isDerivation allJobs; + }; + }; + + nixConfig = { + extra-substituters = ["https://cache.iog.io"]; + extra-trusted-public-keys = ["hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ="]; + allow-import-from-derivation = "true"; + }; + }; + }); +} diff --git a/modules/genesis_bootstrapper/build.rs b/modules/genesis_bootstrapper/build.rs index 52886ce5..165e4d7e 100644 --- a/modules/genesis_bootstrapper/build.rs +++ b/modules/genesis_bootstrapper/build.rs @@ -15,7 +15,7 @@ async fn fetch_bytes(client: &reqwest::Client, url: &str) -> Result> { if let Ok(path) = env::var("ACROPOLIS_OFFLINE_MIRROR") { if let Ok(file) = File::open(&path) { if let Ok(map) = from_reader::<_, HashMap>(file) { - if let Some(path) = map.get(url) { + if let Some(path) = map.get(url.trim()) { if let Ok(bytes) = fs::read(&Path::new(path).to_path_buf()) { return Ok(bytes); } diff --git a/modules/parameters_state/build.rs b/modules/parameters_state/build.rs index a380b618..d5a4f8e5 100644 --- a/modules/parameters_state/build.rs +++ b/modules/parameters_state/build.rs @@ -15,7 +15,7 @@ fn fetch_text(url: &str) -> Result> { if !path.is_empty() { if let Ok(file) = File::open(path) { if let Ok(map) = from_reader::<_, HashMap>(file) { - if let Some(path_str) = map.get(url) { + if let Some(path_str) = map.get(url.trim()) { if let Ok(s) = fs::read_to_string(&Path::new(path_str).to_path_buf()) { return Ok(s); } diff --git a/modules/rest_blockfrost/src/utils.rs b/modules/rest_blockfrost/src/utils.rs index 66580dc8..348e380c 100644 --- a/modules/rest_blockfrost/src/utils.rs +++ b/modules/rest_blockfrost/src/utils.rs @@ -87,11 +87,37 @@ fn invalid_size_desc(e: T) -> String { mod tests { use super::*; + // XXX: it’s best to leave Internet interactions to integration tests, not unit tests, so let’s provide: + async fn offline_fetch_pool_metadata_as_bytes( + url: String, + timeout: Duration, + ) -> Result> { + if let Ok(path) = std::env::var("ACROPOLIS_OFFLINE_MIRROR") { + if let Ok(file) = std::fs::File::open(&path) { + if let Ok(map) = + serde_json::from_reader::<_, std::collections::HashMap>(file) + { + if let Some(path_str) = map.get(url.trim()) { + if let Ok(bytes) = + std::fs::read(&std::path::Path::new(path_str).to_path_buf()) + { + return Ok(bytes); + } + } + } + } + } + // Fallback to network: + fetch_pool_metadata_as_bytes(url, timeout).await + } + #[tokio::test] async fn test_fetch_pool_metadata() { let url = "https://raw.githubusercontent.com/Octalus/cardano/master/p.json"; let pool_metadata = - fetch_pool_metadata_as_bytes(url.to_string(), Duration::from_secs(3)).await.unwrap(); + offline_fetch_pool_metadata_as_bytes(url.to_string(), Duration::from_secs(3)) + .await + .unwrap(); let pool_metadata = PoolMetadataJson::try_from(pool_metadata).expect("failed to convert"); @@ -109,7 +135,9 @@ mod tests { let expected_hash_as_arr = hex::decode(expected_hash).expect("should be able to decode {}"); let pool_metadata = - fetch_pool_metadata_as_bytes(url.to_string(), Duration::from_secs(3)).await.unwrap(); + offline_fetch_pool_metadata_as_bytes(url.to_string(), Duration::from_secs(3)) + .await + .unwrap(); assert_eq!( verify_pool_metadata_hash(&pool_metadata, &expected_hash_as_arr), diff --git a/nix/devshells.nix b/nix/devshells.nix new file mode 100644 index 00000000..4dfc98e5 --- /dev/null +++ b/nix/devshells.nix @@ -0,0 +1,76 @@ +{inputs}: { + config, + pkgs, + ... +}: let + inherit (pkgs) lib; + internal = inputs.self.internal.${pkgs.system}; +in { + name = "acropolis-devshell"; + + imports = [ + "${inputs.devshell}/extra/language/c.nix" + "${inputs.devshell}/extra/language/rust.nix" + ]; + + commands = [ + {package = inputs.self.formatter.${pkgs.system};} + { + name = "cargo"; + package = internal.rustPackages.cargo; + } + {package = pkgs.cargo-nextest;} + {package = internal.rustPackages.rust-analyzer;} + ]; + + devshell.packages = + [ + pkgs.gnum4 + pkgs.gnumake + pkgs.unixtools.xxd + internal.rustPackages.clippy + ] + ++ lib.optionals pkgs.stdenv.isLinux [ + pkgs.pkg-config + ] + ++ lib.optionals pkgs.stdenv.isDarwin [ + pkgs.libiconv + ]; + + language.c = { + compiler = + if pkgs.stdenv.isLinux + then pkgs.gcc + else pkgs.clang; + includes = internal.commonArgs.buildInputs; + }; + + language.rust = { + packageSet = internal.rustPackages; + tools = ["cargo" "rustfmt"]; # The rest is provided above. + enableDefaultToolchain = true; + }; + + env = + lib.optionals pkgs.stdenv.isDarwin [ + { + name = "LIBCLANG_PATH"; + value = internal.commonArgs.LIBCLANG_PATH; + } + ] + ++ lib.optionals pkgs.stdenv.isLinux [ + # Embed `openssl` in `RPATH`: + { + name = "RUSTFLAGS"; + eval = ''"-C link-arg=-Wl,-rpath,$(pkg-config --variable=libdir openssl)"''; + } + ]; + + devshell.motd = '' + + {202}🔨 Welcome to ${config.name}{reset} + $(menu) + + You can now run ‘{bold}cargo run{reset}’. + ''; +} diff --git a/nix/internal/darwin.nix b/nix/internal/darwin.nix new file mode 100644 index 00000000..a1a1c9a3 --- /dev/null +++ b/nix/internal/darwin.nix @@ -0,0 +1,9 @@ +{ + targetSystem, + unix, + ... +}: +assert builtins.elem targetSystem [ + "x86_64-darwin" + "aarch64-darwin" +]; unix diff --git a/nix/internal/linux.nix b/nix/internal/linux.nix new file mode 100644 index 00000000..820142a7 --- /dev/null +++ b/nix/internal/linux.nix @@ -0,0 +1,6 @@ +{ + targetSystem, + unix, + ... +}: +assert builtins.elem targetSystem ["x86_64-linux" "aarch64-linux"]; unix diff --git a/nix/internal/unix.nix b/nix/internal/unix.nix new file mode 100644 index 00000000..23059496 --- /dev/null +++ b/nix/internal/unix.nix @@ -0,0 +1,202 @@ +{ + inputs, + targetSystem, +}: +assert builtins.elem targetSystem ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"]; let + buildSystem = targetSystem; + pkgs = inputs.nixpkgs.legacyPackages.${buildSystem}; + inherit (pkgs) lib; + extendForTarget = unix: + ( + if pkgs.stdenv.isLinux + then import ./linux.nix + else if pkgs.stdenv.isDarwin + then import ./darwin.nix + else throw "can’t happen" + ) {inherit inputs targetSystem unix;}; +in + extendForTarget rec { + rustPackages = inputs.fenix.packages.${pkgs.system}.stable; + + craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rustPackages.toolchain; + + src = lib.cleanSourceWith { + src = lib.cleanSource ../../.; + filter = path: type: + craneLib.filterCargoSources path type + || lib.hasSuffix ".cbor" path + || lib.hasSuffix ".json" path; + name = "source"; + }; + + packageVersions = { + omnibus = craneLib.crateNameFromCargoToml {cargoToml = builtins.path {path = src + "/processes/omnibus/Cargo.toml";};}; + replayer = craneLib.crateNameFromCargoToml {cargoToml = builtins.path {path = src + "/processes/replayer/Cargo.toml";};}; + }; + + commonArgs = + { + pname = "acropolis"; + inherit (packageVersions.omnibus) version; + inherit src; + strictDeps = true; + nativeBuildInputs = + [pkgs.gnum4] + ++ lib.optionals pkgs.stdenv.isLinux [ + pkgs.pkg-config + ]; + buildInputs = + lib.optionals pkgs.stdenv.isLinux [ + pkgs.openssl + ] + ++ lib.optionals pkgs.stdenv.isDarwin [ + pkgs.libiconv + pkgs.darwin.apple_sdk_12_3.frameworks.SystemConfiguration + pkgs.darwin.apple_sdk_12_3.frameworks.Security + pkgs.darwin.apple_sdk_12_3.frameworks.CoreFoundation + ]; + } + // lib.optionalAttrs pkgs.stdenv.isLinux { + # The linker bundled with Fenix has wrong interpreter path, and it fails with ENOENT, so: + RUSTFLAGS = "-Clink-arg=-fuse-ld=bfd"; + } + // lib.optionalAttrs pkgs.stdenv.isDarwin { + # for bindgen, used by libproc, used by metrics_process + LIBCLANG_PATH = "${lib.getLib pkgs.llvmPackages.libclang}/lib"; + }; + + # For better caching: + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + + packageName = (craneLib.crateNameFromCargoToml {cargoToml = src + "/Cargo.toml";}).pname; + + GIT_REVISION = inputs.self.rev or "dirty"; + + ACROPOLIS_OFFLINE_MIRROR = pkgs.writeText "offline-mirror.json" (builtins.toJSON { + "https://book.world.dev.cardano.org/environments/mainnet/byron-genesis.json" = cardano-node-configs + "/mainnet/byron-genesis.json"; + "https://book.world.dev.cardano.org/environments/mainnet/shelley-genesis.json" = cardano-node-configs + "/mainnet/shelley-genesis.json"; + "https://book.world.dev.cardano.org/environments/mainnet/alonzo-genesis.json" = cardano-node-configs + "/mainnet/alonzo-genesis.json"; + "https://book.world.dev.cardano.org/environments/mainnet/conway-genesis.json" = cardano-node-configs + "/mainnet/conway-genesis.json"; + "https://raw.githubusercontent.com/Hornan7/SanchoNet-Tutorials/refs/heads/main/genesis/byron-genesis.json" = inputs.sanchonet + "/genesis/byron-genesis.json"; + "https://raw.githubusercontent.com/Hornan7/SanchoNet-Tutorials/refs/heads/main/genesis/shelley-genesis.json" = inputs.sanchonet + "/genesis/shelley-genesis.json"; + "https://raw.githubusercontent.com/Hornan7/SanchoNet-Tutorials/refs/heads/main/genesis/alonzo-genesis.json" = inputs.sanchonet + "/genesis/alonzo-genesis.json"; + "https://raw.githubusercontent.com/Hornan7/SanchoNet-Tutorials/refs/heads/main/genesis/conway-genesis.json" = inputs.sanchonet + "/genesis/conway-genesis.json"; + "https://raw.githubusercontent.com/Octalus/cardano/master/p.json" = pkgs.fetchurl { + url = "https://raw.githubusercontent.com/Octalus/cardano/master/p.json"; + hash = "sha256-fTBfIH3RA3yEEWUGb5zGusKoEjypYelOb7OKdVdYiFg="; + }; + "https://880w.short.gy/clrsp.json" = pkgs.fetchurl { + url = "https://880w.short.gy/clrsp.json"; + hash = "sha256-bKOsYxccsOHqHmT+hvw7OxFopTj1PYr10a3ohW6KUKU="; + }; + }); + + cardano-node-configs = builtins.path { + name = "cardano-playground-configs"; + path = inputs.cardano-playground + "/static/book.play.dev.cardano.org/environments"; + }; + + workspace = craneLib.buildPackage (commonArgs + // { + inherit cargoArtifacts GIT_REVISION ACROPOLIS_OFFLINE_MIRROR; + ACROPOLIS_OMNIBUS_DEFAULT_CONFIG = builtins.path {path = src + "/processes/omnibus/omnibus.toml";}; + ACROPOLIS_REPLAYER_DEFAULT_CONFIG = builtins.path {path = src + "/processes/replayer/replayer.toml";}; + doCheck = false; # we run tests with `cargo-nextest` below + }); + + acropolis-process-omnibus = pkgs.stdenv.mkDerivation { + inherit (packageVersions.omnibus) pname version; + buildCommand = ''mkdir -p $out/bin && cp ${workspace}/bin/acropolis_process_omnibus $out/bin/''; + meta.description = "A kit of micro-service parts, written in Rust, which allows flexible construction of clients, services and APIs for the Cardano ecosystem"; + }; + + acropolis-process-replayer = pkgs.stdenv.mkDerivation { + inherit (packageVersions.replayer) pname version; + buildCommand = ''mkdir -p $out/bin && cp ${workspace}/bin/acropolis_process_replayer $out/bin/''; + meta.description = "Acropolis replayer process, allowing to debug any module"; + }; + + # We use a newer `rustfmt`: + inherit (inputs.fenix.packages.${pkgs.system}.stable) rustfmt; + + cargoChecks = { + cargo-clippy = craneLib.cargoClippy (commonArgs + // { + inherit cargoArtifacts GIT_REVISION ACROPOLIS_OFFLINE_MIRROR; + # Maybe also add `--deny clippy::pedantic`? + cargoClippyExtraArgs = "--all-targets --all-features -- --deny warnings"; + }); + + cargo-doc = craneLib.cargoDoc (commonArgs + // { + inherit cargoArtifacts GIT_REVISION ACROPOLIS_OFFLINE_MIRROR; + RUSTDOCFLAGS = "-D warnings"; + }); + + cargo-audit = craneLib.cargoAudit { + inherit src; + inherit (inputs) advisory-db; + }; + + cargo-deny = craneLib.cargoDeny { + inherit src; + }; + + cargo-test = craneLib.cargoNextest (commonArgs + // { + inherit cargoArtifacts GIT_REVISION ACROPOLIS_OFFLINE_MIRROR; + }); + }; + + nixChecks = { + nix-statix = + pkgs.runCommandNoCC "nix-statix" { + buildInputs = [pkgs.statix]; + } '' + touch $out + cd ${inputs.self} + exec statix check . + ''; + + nix-deadnix = + pkgs.runCommandNoCC "nix-deadnix" { + buildInputs = [pkgs.deadnix]; + } '' + touch $out + cd ${inputs.self} + exec deadnix --fail . + ''; + + nix-nil = + pkgs.runCommandNoCC "nix-nil" { + buildInputs = [pkgs.nil]; + } '' + ec=0 + touch $out + cd ${inputs.self} + find . -type f -iname '*.nix' | while IFS= read -r file; do + nil diagnostics "$file" || ec=1 + done + exit $ec + ''; + + # From `nixd`: + nix-nixf = + pkgs.runCommandNoCC "nix-nil" { + buildInputs = [pkgs.nixf pkgs.jq]; + } '' + ec=0 + touch $out + cd ${inputs.self} + find . -type f -iname '*.nix' | while IFS= read -r file; do + errors=$(nixf-tidy --variable-lookup --pretty-print <"$file" | jq -c '.[]' | sed -r "s#^#$file: #") + if [ -n "$errors" ] ; then + cat <<<"$errors" + echo + ec=1 + fi + done + exit $ec + ''; + }; + } diff --git a/nix/internal/windows.nix b/nix/internal/windows.nix new file mode 100644 index 00000000..82328d8b --- /dev/null +++ b/nix/internal/windows.nix @@ -0,0 +1,63 @@ +{ + inputs, + targetSystem, +}: +assert builtins.elem targetSystem ["x86_64-windows"]; let + buildSystem = "x86_64-linux"; + pkgs = inputs.nixpkgs.legacyPackages.${buildSystem}; +in rec { + toolchain = with inputs.fenix.packages.${buildSystem}; + combine [ + minimal.rustc + minimal.cargo + targets.x86_64-pc-windows-gnu.latest.rust-std + ]; + + craneLib = (inputs.crane.mkLib pkgs).overrideToolchain toolchain; + + inherit (inputs.self.internal.${buildSystem}) src packageVersions GIT_REVISION ACROPOLIS_OFFLINE_MIRROR; + + pkgsCross = pkgs.pkgsCross.mingwW64; + + commonArgs = { + pname = "acropolis"; + inherit (packageVersions.omnibus) version; + inherit src; + strictDeps = true; + + CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu"; + TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; + + OPENSSL_DIR = "${pkgs.openssl.dev}"; + OPENSSL_LIB_DIR = "${pkgs.openssl.out}/lib"; + OPENSSL_INCLUDE_DIR = "${pkgs.openssl.dev}/include/"; + + depsBuildBuild = [ + pkgsCross.stdenv.cc + pkgsCross.windows.pthreads + ]; + }; + + # For better caching: + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + + # FIXME: currently the Windows build fails because `caryatid_process` does + # `use tokio::signal::unix`, which is not available on Windows. + workspace = craneLib.buildPackage (commonArgs + // { + inherit cargoArtifacts GIT_REVISION ACROPOLIS_OFFLINE_MIRROR; + doCheck = false; # can’t run Windows tests on Linux (at least without Wine) + }); + + acropolis-process-omnibus = pkgs.stdenv.mkDerivation { + inherit (packageVersions.omnibus) pname version; + buildCommand = ''mkdir -p $out && cp ${workspace}/bin/acropolis_process_omnibus.exe $out/''; + meta.description = "A kit of micro-service parts, written in Rust, which allows flexible construction of clients, services and APIs for the Cardano ecosystem"; + }; + + acropolis-process-replayer = pkgs.stdenv.mkDerivation { + inherit (packageVersions.replayer) pname version; + buildCommand = ''mkdir -p $out && cp ${workspace}/bin/acropolis_process_replayer.exe $out/''; + meta.description = "Acropolis replayer process, allowing to debug any module"; + }; +}