diff --git a/flake.nix b/flake.nix index cf8d9ce51..50c56474b 100644 --- a/flake.nix +++ b/flake.nix @@ -39,19 +39,29 @@ craneLib = (crane.mkLib pkgs).overrideToolchain (_: rustToolchain); + crateSpecs = import ./nix/crate.nix { + inherit pkgs; + root = ./.; + }; + # Crate-by-crate crane helpers (workspace graph, minimal per-crate # source, buildWorkspaceCrate). See nix/workspace.nix. workspace = import ./nix/workspace.nix { inherit lib pkgs craneLib; root = ./.; + inherit crateSpecs; }; inherit (workspace) buildWorkspaceCrate; - crateSpecs = import ./nix/crate.nix { - inherit pkgs; - root = ./.; + workspaceCrates = lib.mapAttrs (_: buildWorkspaceCrate) crateSpecs; + crates = { + openshell = workspaceCrates.openshell-cli.package; + openshell-gateway = workspaceCrates.openshell-server.package; + openshell-sandbox = workspaceCrates.openshell-sandbox.package; + openshell-driver-vm = workspaceCrates.openshell-driver-vm.package; + openshell-driver-kubernetes = workspaceCrates.openshell-driver-kubernetes.package; + openshell-driver-podman = workspaceCrates.openshell-driver-podman.package; }; - crates = lib.mapAttrs (_: buildWorkspaceCrate) crateSpecs; treefmtEval = treefmt-nix.lib.evalModule pkgs { projectRootFile = "flake.nix"; diff --git a/nix/crate.nix b/nix/crate.nix index 018bf6e9b..1458e7ec3 100644 --- a/nix/crate.nix +++ b/nix/crate.nix @@ -5,23 +5,15 @@ pkgs, root, }: -let - # z3 (found via pkg-config) and libclang (for z3-sys bindgen) are only needed - # by crates whose closure contains openshell-prover. - withZ3 = { - nativeBuildInputs = [ - pkgs.pkg-config - pkgs.protobuf - ]; - buildInputs = [ pkgs.z3 ]; - env.LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; - }; -in { - # Each crate declares the compile-time assets its build needs: its own plus - # those of its workspace deps (proto/ arrives via openshell-core, providers/ - # via openshell-providers, registry/ via openshell-prover). - openshell-cli = withZ3 // { + # Each crate declares the compile-time assets and build tools it needs. The + # workspace builder collects nativeBuildInputs/buildInputs/env from the + # transitive Cargo closure. + openshell-bootstrap = { + dir = "openshell-bootstrap"; + assets = [ (root + "/proto") ]; + }; + openshell-cli = { dir = "openshell-cli"; assets = [ (root + "/proto") @@ -29,7 +21,7 @@ in (root + "/crates/openshell-prover/registry") ]; }; - openshell-server = withZ3 // { + openshell-server = { dir = "openshell-server"; assets = [ (root + "/proto") @@ -38,9 +30,17 @@ in (root + "/crates/openshell-server/migrations") ]; }; + openshell-core = { + dir = "openshell-core"; + nativeBuildInputs = [ pkgs.protobuf ]; + assets = [ (root + "/proto") ]; + }; + openshell-driver-docker = { + dir = "openshell-driver-docker"; + assets = [ (root + "/proto") ]; + }; openshell-sandbox = { dir = "openshell-sandbox"; - nativeBuildInputs = [ pkgs.protobuf ]; assets = [ (root + "/proto") (root + "/crates/openshell-sandbox/data") @@ -49,7 +49,6 @@ in }; openshell-driver-vm = { dir = "openshell-driver-vm"; - nativeBuildInputs = [ pkgs.protobuf ]; assets = [ (root + "/proto") (root + "/crates/openshell-driver-vm/scripts") @@ -57,12 +56,52 @@ in }; openshell-driver-kubernetes = { dir = "openshell-driver-kubernetes"; - nativeBuildInputs = [ pkgs.protobuf ]; assets = [ (root + "/proto") ]; }; openshell-driver-podman = { dir = "openshell-driver-podman"; - nativeBuildInputs = [ pkgs.protobuf ]; assets = [ (root + "/proto") ]; }; + openshell-ocsf = { + dir = "openshell-ocsf"; + assets = [ (root + "/crates/openshell-ocsf/schemas") ]; + }; + openshell-policy = { + dir = "openshell-policy"; + assets = [ (root + "/proto") ]; + }; + openshell-prover = { + dir = "openshell-prover"; + nativeBuildInputs = [ pkgs.pkg-config ]; + buildInputs = [ pkgs.z3 ]; + env.LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + assets = [ + (root + "/crates/openshell-prover/registry") + (root + "/crates/openshell-prover/testdata") + ]; + }; + openshell-providers = { + dir = "openshell-providers"; + assets = [ + (root + "/proto") + (root + "/providers") + ]; + }; + openshell-router = { + dir = "openshell-router"; + assets = [ (root + "/proto") ]; + }; + openshell-server-macros = { + dir = "openshell-server-macros"; + }; + openshell-tui = { + dir = "openshell-tui"; + assets = [ + (root + "/proto") + (root + "/providers") + ]; + }; + openshell-vfio = { + dir = "openshell-vfio"; + }; } diff --git a/nix/workspace.nix b/nix/workspace.nix index 41f642192..4189d5a85 100644 --- a/nix/workspace.nix +++ b/nix/workspace.nix @@ -18,6 +18,8 @@ root, # Member directory, relative to root. crateDir ? "crates", + # Crate metadata keyed by workspace crate directory. + crateSpecs ? { }, # Version stamped onto every crate derivation. version ? "0.0.0", }: @@ -50,6 +52,12 @@ let } ); + specFor = dir: lib.attrByPath [ dir ] { } crateSpecs; + + closureList = closure: field: lib.concatLists (map (d: (specFor d).${field} or [ ]) closure); + + closureEnv = closure: lib.foldl' lib.recursiveUpdate { } (map (d: (specFor d).env or { }) closure); + # Every member's Cargo.toml, cargo must see all of them to resolve the # workspace even for crates whose source we leave out. allManifests = map (d: cratesRoot + "/${d}/Cargo.toml") crateDirs; @@ -94,14 +102,17 @@ let let closure = closureOf dir; workspaceDeps = lib.filter (d: d != dir) closure; + effectiveNativeBuildInputs = lib.unique ( + closureList closure "nativeBuildInputs" ++ nativeBuildInputs + ); + effectiveBuildInputs = lib.unique (closureList closure "buildInputs" ++ buildInputs); + effectiveEnv = lib.recursiveUpdate (closureEnv closure) env; common = { pname = dir; - inherit - version - nativeBuildInputs - buildInputs - env - ; + inherit version; + nativeBuildInputs = effectiveNativeBuildInputs; + buildInputs = effectiveBuildInputs; + env = effectiveEnv; strictDeps = true; # Build only, skip the cargo test/check phase for now. doCheck = false; @@ -142,16 +153,18 @@ let } ); in - craneLib.buildPackage ( - common - // { - src = mkSrc { - dirs = closure; - inherit assets; - }; - cargoArtifacts = workspaceLibs; - } - ); + { + package = craneLib.buildPackage ( + common + // { + src = mkSrc { + dirs = closure; + inherit assets; + }; + cargoArtifacts = workspaceLibs; + } + ); + }; in { inherit buildWorkspaceCrate;