Personal Monorepo ❄️
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 193 lines 6.2 kB view raw
1# rust-nixpkgs/lib.nix 2# 3# Helper functions for assembling a Rust-based stdenv from individual 4# component replacements. Each "component" is a small attribute set 5# describing the original C package it replaces, the Rust replacement 6# package (or null when not yet available), and metadata used for 7# status reporting. 8# 9# Design principles: 10# - Each component is declared in components/*.nix as a function 11# taking `pkgs` and returning the component attrset. 12# - Components whose `replacement` is null are silently skipped 13# when assembling the stdenv — this lets us declare the full 14# target map up front and fill in replacements incrementally. 15# - Replacement packages must be flag-compatible drop-ins for the 16# originals. Wrappers are acceptable when needed for 17# binary name compatibility. 18{lib}: let 19 # Status values used in component declarations. 20 # available — a working Rust replacement exists and is wired in 21 # in-progress — a Rust rewrite is underway (in this repo or upstream) 22 # planned — replacement is on the roadmap but not started 23 status = { 24 available = "available"; 25 inProgress = "in-progress"; 26 planned = "planned"; 27 }; 28 29 # Source values describing where the replacement comes from. 30 # nixpkgs — already packaged in nixpkgs (e.g. uutils, ripgrep) 31 # repo — a sibling subproject at the monorepo root (e.g. ../make) 32 # upstream — an upstream Rust project not yet in nixpkgs 33 # internal — will be developed inside rust-nixpkgs/crates 34 source = { 35 nixpkgs = "nixpkgs"; 36 repo = "repo"; 37 upstream = "upstream"; 38 internal = "internal"; 39 }; 40 41 # mkComponent — canonical constructor for a component declaration. 42 # 43 # mkComponent { 44 # name = "coreutils"; 45 # original = pkgs.coreutils; 46 # replacement = pkgs.uutils-coreutils-noprefix; 47 # status = status.available; 48 # source = source.nixpkgs; 49 # phase = 1; 50 # description = "Core file/text/shell utilities"; 51 # notes = "Using uutils — drop-in noprefix variant"; 52 # } 53 # 54 mkComponent = { 55 name, 56 original, 57 replacement ? null, 58 status ? "planned", 59 source ? "internal", 60 phase ? 0, 61 description ? "", 62 notes ? "", 63 }: { 64 inherit 65 name 66 original 67 replacement 68 status 69 source 70 phase 71 description 72 notes 73 ; 74 isAvailable = replacement != null; 75 }; 76 77 # loadComponents — import every components/*.nix file and call each 78 # with `pkgs`, returning an attrset keyed by component name. 79 loadComponents = pkgs: let 80 dir = ./components; 81 entries = lib.readDir dir; 82 nixFiles = 83 lib.filterAttrs 84 (n: t: t == "regular" && lib.hasSuffix ".nix" n) 85 entries; 86 load = filename: _: let 87 component = import (dir + "/${filename}") {inherit pkgs lib mkComponent status source;}; 88 in { 89 inherit (component) name; 90 value = component; 91 }; 92 in 93 lib.listToAttrs (lib.mapAttrsToList load nixFiles); 94 95 # availableComponents — filter to only components with a non-null 96 # replacement. 97 availableComponents = components: 98 lib.filterAttrs (_: c: c.isAvailable) components; 99 100 # componentsByPhase — group components by their phase number. 101 componentsByPhase = components: let 102 phaseNums = lib.unique (lib.mapAttrsToList (_: c: c.phase) components); 103 grouped = 104 map ( 105 p: { 106 name = toString p; 107 value = lib.filterAttrs (_: c: c.phase == p) components; 108 } 109 ) 110 phaseNums; 111 in 112 lib.listToAttrs grouped; 113 114 # mkReplacements — produce a list of { original, replacement } attrsets 115 # suitable for `system.replaceDependencies.replacements` or for 116 # iterating when building a custom stdenv. Only includes components 117 # whose replacement is non-null. 118 mkReplacements = components: 119 lib.mapAttrsToList 120 (_: c: { 121 inherit (c) original; 122 inherit (c) replacement; 123 }) 124 (availableComponents components); 125 126 # overrideInitialPath — given a stdenv and a components attrset, 127 # produce a new initialPath where every original package that has 128 # a Rust replacement is swapped out. 129 overrideInitialPath = stdenv: components: let 130 available = availableComponents components; 131 replacementMap = lib.listToAttrs ( 132 lib.mapAttrsToList 133 (_: c: { 134 name = lib.unsafeDiscardStringContext (toString c.original); 135 value = c.replacement; 136 }) 137 available 138 ); 139 swapPkg = pkg: let 140 key = lib.unsafeDiscardStringContext (toString pkg); 141 in 142 replacementMap.${key} or pkg; 143 in 144 map swapPkg stdenv.initialPath; 145 146 # mkRustStdenv — create an overridden stdenv with available Rust 147 # replacements swapped into the initial path, and optionally the 148 # shell replaced. 149 # 150 # This is the main entry point for Phase 7 (full oxidized stdenv). 151 # Earlier phases use individual component replacements or targeted 152 # overlays instead. 153 mkRustStdenv = { 154 stdenv, 155 components, 156 replaceShell ? false, 157 }: let 158 available = availableComponents components; 159 newInitialPath = overrideInitialPath stdenv components; 160 shellComponent = available.shell or null; 161 newShell = 162 if replaceShell && shellComponent != null 163 then "${shellComponent.replacement}/bin/bash" 164 else stdenv.shell; 165 in 166 stdenv.override { 167 initialPath = newInitialPath; 168 shell = newShell; 169 }; 170 171 # statusReport — produce a human-readable markdown table of all 172 # components and their replacement status. 173 statusReport = components: let 174 header = "| Component | Phase | Status | Source | Notes |\n|-----------|-------|--------|--------|-------|\n"; 175 rows = lib.mapAttrsToList ( 176 _: c: "| ${c.name} | ${toString c.phase} | ${c.status} | ${c.source} | ${c.notes} |" 177 ) (lib.attrsets.mergeAttrsList (lib.mapAttrsToList (_: phase: phase) (componentsByPhase components))); 178 in 179 header + (lib.concatStringsSep "\n" rows); 180in { 181 inherit 182 status 183 source 184 mkComponent 185 loadComponents 186 availableComponents 187 componentsByPhase 188 mkReplacements 189 overrideInitialPath 190 mkRustStdenv 191 statusReport 192 ; 193}