--- a/flake.lock +++ b/flake.lock @@ -49,6 +49,24 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "fleet-tf": { "inputs": { "flake-parts": [ @@ -124,6 +142,21 @@ "type": "github" } }, + "nix-filter": { + "locked": { + "lastModified": 1687178632, + "narHash": "sha256-HS7YR5erss0JCaUijPeyg2XrisEb959FIct3n2TMGbE=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "d90c75e8319d0dd9be67d933d8eb9d0894ec9174", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "nix-filter", + "type": "github" + } + }, "nixpkgs": { "locked": { "lastModified": 1781820577, @@ -171,6 +204,46 @@ "type": "github" } }, + "nocargo": { + "inputs": { + "flake-utils": "flake-utils", + "nix-filter": "nix-filter", + "nixpkgs": [ + "nixpkgs" + ], + "registry-crates-io": [ + "registry-crates-io" + ] + }, + "locked": { + "lastModified": 1778181426, + "owner": "deltaex", + "repo": "nocargo", + "rev": "10b5ad93582992ed19bf2bd92840e544601cced4", + "type": "gitlab" + }, + "original": { + "owner": "deltaex", + "repo": "nocargo", + "type": "gitlab" + } + }, + "registry-crates-io": { + "flake": false, + "locked": { + "lastModified": 1783425179, + "narHash": "sha256-g9gZx0E3isjuTXGwmkY7pVmYAkYDn0UucxO5c+GOpvw=", + "owner": "rust-lang", + "repo": "crates.io-index", + "rev": "c4f52e3ab01b43153b474dda067993b982457908", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "repo": "crates.io-index", + "type": "github" + } + }, "root": { "inputs": { "crane": "crane", @@ -178,6 +251,8 @@ "fleet-tf": "fleet-tf", "nix": "nix", "nixpkgs": "nixpkgs", + "nocargo": "nocargo", + "registry-crates-io": "registry-crates-io", "rust-overlay": "rust-overlay", "shelly": "shelly", "treefmt-nix": "treefmt-nix" @@ -216,6 +291,21 @@ "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" + } + }, "treefmt-nix": { "inputs": { "nixpkgs": [ --- a/flake.nix +++ b/flake.nix @@ -12,6 +12,15 @@ inputs.nixpkgs-lib.follows = "nixpkgs"; }; crane.url = "github:ipetkov/crane"; + nocargo = { + url = "gitlab:deltaex/nocargo"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.registry-crates-io.follows = "registry-crates-io"; + }; + registry-crates-io = { + url = "github:rust-lang/crates.io-index"; + flake = false; + }; shelly.url = "github:CertainLach/shelly"; fleet-tf = { url = "github:CertainLach/fleet-tf"; @@ -136,6 +145,7 @@ let packages = pkgs.callPackages ./pkgs { inherit craneLib inputs; + rustToolchain = rust; }; in packages // { default = packages.fleet; } --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -2,12 +2,16 @@ callPackage, craneLib, inputs, + rustToolchain ? null, }: let remowt-agents-bundle = callPackage ./remowt-agents-bundle.nix { inherit craneLib; }; in { fleet = callPackage ./fleet.nix { inherit craneLib inputs remowt-agents-bundle; }; + fleet-nocargo = callPackage ./fleet-nocargo.nix { + inherit inputs remowt-agents-bundle rustToolchain; + }; fleet-install-secrets = callPackage ./fleet-install-secrets.nix { inherit craneLib; }; fleet-generator-helper = callPackage ./fleet-generator-helper.nix { inherit craneLib; }; fleet-usbd = callPackage ./fleet-usbd.nix { inherit craneLib inputs; }; --- /dev/null +++ b/pkgs/fleet-nocargo.nix @@ -0,0 +1,164 @@ +{ + lib, + pkgs, + stdenv, + callPackage, + fetchurl, + pkg-config, + rustPlatform, + rustc, + rofi, + installShellFiles, + inputs, + remowt-agents-bundle, + rustToolchain ? null, +}: +let + system = stdenv.hostPlatform.system; + nocargoSrc = inputs.nocargo; + nocargoLib = import (nocargoSrc + "/lib") { + inherit lib; + inherit (inputs.nocargo.inputs) nix-filter; + }; + toml2json = callPackage (nocargoSrc + "/toml2json") { }; + buildRustCrateUnwrapped = callPackage (nocargoSrc + "/build-rust-crate") { + nocargo-lib = nocargoLib; + inherit toml2json; + }; + # nocargo passes profile.panic to every crate, breaking build script and + # proc-macro linkage; cargo applies it only to final artifacts: + # https://doc.rust-lang.org/cargo/reference/profiles.html#panic + buildRustCrate = + args: + let + profile = args.profile or { }; + crate = buildRustCrateUnwrapped ( + args + // { + profile = removeAttrs profile [ "panic" ]; + buildFlags = [ "--cfg=tokio_unstable" ] ++ args.buildFlags or [ ]; + # Every crate dev output propagates its transitive dev closure, and + # the bintools hook emits -L for each one; on large dependency + # closures the resulting NIX_LDFLAGS overflows the execve limit + # ("Argument list too long"). Those entries only contain .rmeta; + # rustc gets real paths via --extern and -Ldependency. + postHook = '' + _newLdflags= + for _flag in $NIX_LDFLAGS; do + if [[ "$_flag" == -L/nix/store/*-rust_*/lib ]]; then continue; fi + _newLdflags+="''${_newLdflags:+ }$_flag" + done + export NIX_LDFLAGS="$_newLdflags" + unset _newLdflags _flag + ''; + } + ); + in + if profile.panic or "unwind" == "unwind" then + crate + else + crate + // { + bin = crate.bin.overrideAttrs (old: { + buildFlags = old.buildFlags ++ [ "-Cpanic=${profile.panic}" ]; + }); + }; + + extraProcMacroCrates = [ + "bifrostlink-macros" + "curve25519-dalek-derive" + "derive_more-impl" + "iroh-metrics-derive" + "jni-macros" + "jni-sys-macros" + "n0-error-macros" + "proc-macro-error-attr2" + "prost-derive" + "spez" + "test-log-macros" + ]; + cratesIoOverride = + import (nocargoSrc + "/crates-io-override") { inherit lib pkgs; } + // lib.genAttrs extraProcMacroCrates (_: _: { procMacro = true; }) + // { + derive_more = { version, ... }: { procMacro = lib.versionOlder version "1.0.0"; }; + test-log = { version, ... }: { procMacro = lib.versionOlder version "0.2.12"; }; + # scratch bakes env!("OUT_DIR") into its lib as a shared writable + # directory, and cxx-build then creates files there from dependent + # builds; a store path is immutable, so rebake it to a path that + # exists in every build sandbox. + scratch = _: { + postConfigure = '' + export OUT_DIR="$NIX_BUILD_TOP/rust-scratch-out-dir" + mkdir -p "$OUT_DIR" + ''; + }; + }; + cratesIoIndex = nocargoLib.pkg-info.mkIndex fetchurl inputs.registry-crates-io cratesIoOverride; + + mkRustPackageOrWorkspace = callPackage nocargoLib.support.mkRustPackageOrWorkspace { + defaultRegistries = { + "https://github.com/rust-lang/crates.io-index" = cratesIoIndex; + }; + inherit buildRustCrate; + }; + + ws = mkRustPackageOrWorkspace { + src = lib.cleanSourceWith { + src = ../.; + filter = + path: type: + (if type == "directory" then baseNameOf path != "target" else true) + && ( + type == "directory" + || lib.any (suffix: lib.hasSuffix suffix path) [ + ".rs" + ".toml" + ".cc" + ".hh" + ] + || baseNameOf path == "Cargo.lock" + ); + }; + rustc = if rustToolchain != null then rustToolchain else rustc; + buildCrateOverrides = { + nix-eval = _: { + nativeBuildInputs = [ + pkg-config + rustPlatform.bindgenHook + ]; + propagatedBuildInputs = [ + inputs.nix.packages.${system}.nix-expr-c + inputs.nix.packages.${system}.nix-flake-c + inputs.nix.packages.${system}.nix-fetchers-c + ]; + }; + fleet-base = _: { + REMOWT_AGENTS_DIR = "${remowt-agents-bundle}"; + }; + remowt-ui-prompt = _: { + ROFI = "${rofi}/bin/rofi"; + }; + }; + }; + + fleet = ws.release.fleet.bin; +in +stdenv.mkDerivation { + pname = "fleet-nocargo"; + inherit (fleet) version; + + nativeBuildInputs = [ installShellFiles ]; + + buildCommand = '' + mkdir -p $out/bin + ln -s ${fleet}/bin/* $out/bin/ + + for shell in bash fish zsh; do + installShellCompletion --cmd fleet \ + --$shell <($out/bin/fleet complete --shell $shell) + done + ''; + + passthru.workspace = ws; +}