From c6d29a926862f0cef0205aae9152ccf1b8f287d9 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Thu, 5 Nov 2026 13:05:56 -0800 Subject: [PATCH] build(nix): schemars-nixgen is built and checked by the flake, and in the dev shell nix/nixgen has the package and the clippy and nextest checks (in the default check sets), from a "nixgen" platform of nix/workspace-src.nix that is the tool alone; it is a stub in every other platform's source, so an edit of it rebuilds none of theirs. --- flake.nix | 1 + nix/checks.nix | 4 + nix/common.nix | 2 + nix/nixgen/build.nix | 185 +++++++++++------------------------- nix/nixgen/flake-module.nix | 42 ++++++++ nix/workspace-src.nix | 22 +++-- 6 files changed, 122 insertions(+), 134 deletions(-) create mode 100644 nix/nixgen/flake-module.nix diff --git a/flake.nix b/flake.nix index 5581b195..e37094bc 100644 --- a/flake.nix +++ b/flake.nix @@ -35,6 +35,7 @@ ./nix/linux/flake-module.nix ./nix/macos/flake-module.nix ./nix/recorder/flake-module.nix + ./nix/nixgen/flake-module.nix ]; }; } diff --git a/nix/checks.nix b/nix/checks.nix index 2384eba6..3e583f22 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -55,6 +55,8 @@ let "linux-nix-options-validation" "linux-schema-fresh" ]; + nixgen-lint = [ "nixgen-clippy" ]; + nixgen-test = [ "nixgen-nextest" ]; recorder-lint = [ "recorder-clippy" ]; recorder-test = [ "recorder-nextest" ]; macos-lint = [ "macos-clippy" ]; @@ -98,6 +100,8 @@ let "macos-options" "recorder-lint" "recorder-test" + "nixgen-lint" + "nixgen-test" ]; in { diff --git a/nix/common.nix b/nix/common.nix index 2fae2bd4..d2e2072c 100644 --- a/nix/common.nix +++ b/nix/common.nix @@ -88,6 +88,8 @@ in pkgs.cargo-deny pkgs.cargo-nextest pkgs.cargo-outdated + # writes the Nix options of the modules from the schemas (`just nixgen-linux`, `just nixgen-macos`) + config.packages.schemars-nixgen # `komorebi-recorder frames` and `selftest` extract frames with ffmpeg; it is never used for # capture and is not bundled into the packaged binary pkgs.ffmpeg-headless diff --git a/nix/nixgen/build.nix b/nix/nixgen/build.nix index 3b17ea0b..3301f132 100644 --- a/nix/nixgen/build.nix +++ b/nix/nixgen/build.nix @@ -1,137 +1,66 @@ +# The crane derivations of schemars-nixgen, the tool that writes the Nix options of the modules from the JSON +# Schemas, from the one Cargo workspace (nix/workspace-src.nix, platform "nixgen": the tool and nothing +# else). It is pure Rust, so one build serves every system. +{ inputs, self }: +let + lib' = import ../lib.nix { inherit inputs; }; + inherit (inputs) crane; + version = + (builtins.fromTOML (builtins.readFile ../../crates/schemars-nixgen/Cargo.toml)).package.version; +in { - inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - flake-parts.url = "github:hercules-ci/flake-parts"; - crane.url = "github:ipetkov/crane"; - rust-overlay.url = "github:oxalica/rust-overlay"; - rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; - treefmt-nix.url = "github:numtide/treefmt-nix"; - treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; - git-hooks-nix.url = "github:cachix/git-hooks.nix"; - git-hooks-nix.inputs.nixpkgs.follows = "nixpkgs"; - }; + mkNixgenPackages = + { pkgs }: + let + toolchain = pkgs.rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml; + craneLib = (crane.mkLib pkgs).overrideToolchain toolchain; - outputs = - inputs@{ - nixpkgs, - flake-parts, - crane, - rust-overlay, - ... - }: - flake-parts.lib.mkFlake { inherit inputs; } { - imports = [ - inputs.treefmt-nix.flakeModule - inputs.git-hooks-nix.flakeModule - ]; + inherit + (import ../workspace-src.nix { + inherit pkgs craneLib; + repoRoot = ../..; + platform = "nixgen"; + }) + src + ; - systems = [ - "x86_64-linux" - "aarch64-linux" - "aarch64-darwin" - ]; + lockFile = lib'.repoFile "Cargo.lock"; + tomlFile = lib'.repoFile "Cargo.toml"; - perSystem = - { - config, - system, - ... - }: - let - pkgs = import nixpkgs { - inherit system; - overlays = [ rust-overlay.overlays.default ]; + commonArgs = { + pname = "schemars-nixgen"; + inherit version src; + cargoExtraArgs = "--locked -p schemars-nixgen"; + # the lock and the root manifest as files of their own: a path inside the filtered source + # would put all of it into the context of every derivation, and an edit of any file + # would then change the dependencies + cargoLock = lockFile; + cargoToml = tomlFile; + cargoVendorDir = craneLib.vendorCargoDeps { cargoLock = lockFile; }; + strictDeps = true; + }; + + # the dummy source is of the manifests alone (nix/lib.nix): the dependencies are the same + # derivations for every source file and every stub, and nothing is built at evaluation + cargoArtifacts = craneLib.buildDepsOnly ( + builtins.removeAttrs commonArgs [ "src" ] + // { + dummySrc = craneLib.mkDummySrc { + src = lib'.manifestSource pkgs.lib; + cargoLock = lockFile; }; + } + ); - rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; - nightlyRustfmt = pkgs.rust-bin.nightly.latest.rustfmt; - rustToolchainWithNightlyRustfmt = pkgs.symlinkJoin { - name = "rust-toolchain-with-nightly-rustfmt"; - paths = [ - nightlyRustfmt - rustToolchain - ]; - }; + individualCrateArgs = commonArgs // { + inherit cargoArtifacts; + doCheck = false; + doDoc = false; + }; - nightlyToolchain = pkgs.rust-bin.nightly.latest.default; - cargo-udeps = pkgs.writeShellScriptBin "cargo-udeps" '' - export PATH="${nightlyToolchain}/bin:$PATH" - exec ${pkgs.cargo-udeps}/bin/cargo-udeps "$@" - ''; - - craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; - - src = pkgs.lib.cleanSourceWith { - src = ./.; - filter = craneLib.filterCargoSources; - }; - - commonArgs = { - inherit src; - strictDeps = true; - }; - - cargoArtifacts = craneLib.buildDepsOnly commonArgs; - - schemars-nixgen = craneLib.buildPackage ( - commonArgs - // { - inherit cargoArtifacts; - } - ); - in - { - checks = { - clippy = craneLib.cargoClippy ( - commonArgs - // { - inherit cargoArtifacts; - } - ); - tests = craneLib.cargoTest ( - commonArgs - // { - inherit cargoArtifacts; - } - ); - }; - - packages = { - inherit schemars-nixgen; - default = schemars-nixgen; - }; - - devShells.default = pkgs.mkShell { - inputsFrom = [ schemars-nixgen ]; - packages = [ - rustToolchainWithNightlyRustfmt - cargo-udeps - pkgs.cargo-outdated - pkgs.bacon - ]; - }; - - pre-commit = { - check.enable = true; - settings.hooks.treefmt = { - enable = true; - package = config.treefmt.build.wrapper; - pass_filenames = false; - }; - }; - - treefmt = { - projectRootFile = "flake.nix"; - programs = { - rustfmt = { - enable = true; - package = nightlyRustfmt; - }; - taplo.enable = true; - nixfmt.enable = true; - deadnix.enable = true; - }; - }; - }; + schemars-nixgen = craneLib.buildPackage individualCrateArgs; + in + { + inherit craneLib src individualCrateArgs schemars-nixgen; }; } diff --git a/nix/nixgen/flake-module.nix b/nix/nixgen/flake-module.nix new file mode 100644 index 00000000..790c8bdc --- /dev/null +++ b/nix/nixgen/flake-module.nix @@ -0,0 +1,42 @@ +# schemars-nixgen: the package of the tool that writes the Nix options (`just nixgen-linux`, +# `just nixgen-macos`), and its checks. It is a development tool: nothing of a release has it. +{ + inputs, + self, + lib, + ... +}: +let + lib' = import ../lib.nix { inherit inputs; }; + nixgen = import ./build.nix { inherit inputs self; }; +in +{ + perSystem = + { pkgs, system, ... }: + let + build = nixgen.mkNixgenPackages { inherit pkgs; }; + in + lib.optionalAttrs (builtins.elem system (lib'.macosSystems ++ lib'.linuxSystems)) { + allChecks = { + # the format, the TOML and the licenses of the tool are checked with those of the rest of + # the workspace (`windows-fmt`, `windows-toml-fmt`, `cargo deny` over the workspace) + nixgen-clippy = build.craneLib.cargoClippy ( + build.individualCrateArgs + // { + cargoClippyExtraArgs = "--all-targets -- -D warnings"; + } + ); + + nixgen-nextest = build.craneLib.cargoNextest (build.individualCrateArgs // { doCheck = true; }); + }; + + packages = { + inherit (build) schemars-nixgen; + }; + + apps.schemars-nixgen = { + type = "app"; + program = "${build.schemars-nixgen}/bin/schemars-nixgen"; + }; + }; +} diff --git a/nix/workspace-src.nix b/nix/workspace-src.nix index 1ababd15..86f2e83a 100644 --- a/nix/workspace-src.nix +++ b/nix/workspace-src.nix @@ -1,6 +1,6 @@ # The source of a build of one platform, cut from the one Cargo workspace of this repository. # -# import ./workspace-src.nix { pkgs; craneLib; repoRoot; platform = "windows" | "linux" | "macos" | "recorder"; } +# import ./workspace-src.nix { pkgs; craneLib; repoRoot; platform = "windows" | "linux" | "macos" | "recorder" | "nixgen"; } # # Cargo has to load every member of the workspace (the root manifest lists the members of all three # platforms), but a build of one platform needs the sources of that platform's crates only. The result: @@ -17,6 +17,9 @@ # indexes the log statements of the daemons of all three platforms (komorebi-recorder/build.rs), so it # has their sources, whole, and nothing else; the Windows build has the recorder as one of its members. # +# The platform "nixgen" is the source of schemars-nixgen's own builds: the tool and nothing else. It is a +# stub in every other platform, so that an edit of it changes none of their derivations. +# # An edit under one platform therefore changes nothing in the derivations of the others, except where # the edit is in a crate they share or in the root manifest, lock or toolchain files. { @@ -44,6 +47,9 @@ let ]; macosOnly = [ "komorebi-macos" ]; + # the development tool that writes the Nix options: built by its own checks (nix/nixgen) + toolOnly = [ "crates/schemars-nixgen" ]; + # the recorder and the crates whose source its build script indexes (komorebi-recorder/build.rs) recorderMembers = [ "komorebi-recorder" @@ -58,8 +64,9 @@ let membersOf = { recorder = recorderMembers; - # everything but the other two platforms' daemons - windows = builtins.filter (m: !(builtins.elem m (linuxOnly ++ macosOnly))) allMembers; + nixgen = toolOnly; + # everything but the other two platforms' daemons and the tool + windows = builtins.filter (m: !(builtins.elem m (linuxOnly ++ macosOnly ++ toolOnly))) allMembers; linux = linuxOnly ++ linuxShared; macos = macosOnly @@ -72,7 +79,7 @@ let "komorebi-scrolling" "komorebi-themes" ] - ++ builtins.filter (m: lib.hasPrefix "crates/" m) allMembers; + ++ builtins.filter (m: lib.hasPrefix "crates/" m && !(builtins.elem m toolOnly)) allMembers; }; members = builtins.filter (m: builtins.elem m membersOf.${platform}) allMembers; @@ -95,7 +102,7 @@ let macos = "(src/macos(\\.rs|/.*)|tests/macos_.*)"; }; # the recorder indexes every platform's files - otherMarkers = if platform == "recorder" then [ ] else builtins.attrValues (removeAttrs markers [ platform ]); + otherMarkers = if platform == "recorder" || platform == "nixgen" then [ ] else builtins.attrValues (removeAttrs markers [ platform ]); ofOtherPlatform = rel: builtins.any ( @@ -111,7 +118,9 @@ let members ++ lib.optional (platform == "windows") "wix" ++ ( - if platform == "recorder" then + if platform == "nixgen" then + [ ".cargo" ] + else if platform == "recorder" then [ ".cargo" # the installer, which a test of the recorder checks for its binaries @@ -178,6 +187,7 @@ let || lib.hasPrefix "komorebic/fixtures/" rel; # the guide and the icon the recorder embeds, and the installer recorder = lib.hasPrefix "komorebi-recorder/" rel || lib.hasPrefix "wix/" rel; + nixgen = false; } .${platform};