From 704946a8ced9bbf208b3e65e5009f5b53b4ad46b Mon Sep 17 00:00:00 2001 From: Torsten Schmits Date: Fri, 21 Jun 2024 21:52:04 +0200 Subject: [PATCH] add packages.*.expose to control the flake outputs each package should be included in --- changelog.md | 2 ++ lib/env.nix | 13 +++++++++++-- lib/output.nix | 42 ++++++++++++++++++++++++------------------ lib/util.nix | 2 ++ modules/env.nix | 16 ---------------- modules/hpack.nix | 5 +++-- modules/output.nix | 18 ++++++++---------- modules/package.nix | 43 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 93 insertions(+), 48 deletions(-) diff --git a/changelog.md b/changelog.md index eba1d8cb..98bb1935 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,8 @@ * Add a reusable workflow for managed bounds updates. * Parse Nix json output messages to diagnose problems; add overrides for installed packages that fail with a bounds error printed by Cabal. +* Replace `envs..derivations` by per-output-category flags in `packages..expose` to control which packages + are included in outputs. # 0.7.0: Hix Unbound: Majors Apart diff --git a/lib/env.nix b/lib/env.nix index 1081d6b5..effbc15f 100644 --- a/lib/env.nix +++ b/lib/env.nix @@ -1,6 +1,6 @@ {util}: let - inherit (util) config; + inherit (util) config lib; targets = env: if env.packages == null then config.internal.packageNames else env.packages; @@ -29,6 +29,15 @@ fi ''; + exposed = purpose: env: let + allow = name: config.packages.${name}.expose.${purpose}; + in lib.filter allow (targets env); + + derivations = purpose: envName: let + env = config.envs.${envName}; + ghc = env.ghc.ghc; + in lib.genAttrs (exposed purpose env ++ config.output.extraPackages) (n: ghc.${n} // { inherit ghc; }); + in { - inherit targets waitScript; + inherit targets waitScript derivations; } diff --git a/lib/output.nix b/lib/output.nix index df9b1286..684f6d5f 100644 --- a/lib/output.nix +++ b/lib/output.nix @@ -1,6 +1,6 @@ -{ lib, config, util, ... }: +{util}: let - inherit (util) app; + inherit (util) app lib config; envCommand = import ./command.nix { inherit config util; }; @@ -68,21 +68,28 @@ let ghc = env.ghc; in withStatic ghc.ghc.${name} // { cross = cross ghc name; musl = nativeMusl ghc name; }; - envOutputs = v: let - env = config.envs.${v}; - in lib.mapAttrs (n: d: (withCross env n)) env.derivations; + envOutputs = purpose: envName: let + env = config.envs.${envName}; + in lib.mapAttrs (n: d: if purpose == "packages" then (withCross env n) else d) (util.env.derivations purpose envName); - fullEnvOutputs = v: let - env = config.envs.${v}; - in envOutputs v // util.attrsetMain (main: { - static = staticDrv env.derivations.${main}; - }) // envExes env; + fullEnvOutputs = purpose: envName: let + env = config.envs.${envName}; + drvs = util.env.derivations purpose envName; + in + envOutputs purpose envName // + util.attrsetMain (main: { static = staticDrv drvs.${main}; }) // + envExes env + ; + + prefixed = purpose: envName: + lib.mapAttrs' (n: d: { name = "${envName}-${n}"; value = d; }) (envOutputs purpose envName); - prefixedInEnv = v: lib.mapAttrs' (n: d: { name = "${v}-${n}"; value = d; }) (envOutputs v); + prefixedInEnvs = purpose: envs: util.mapListCatAttrs (prefixed purpose) envs; - prefixedInEnvs = envs: util.mapListCatAttrs prefixedInEnv envs; + scopedEnvOutputs = envs: lib.genAttrs envs (envOutputs "scoped"); - devOutputs = let + # TODO the main package/exe should probably also respect the targets and expose settings + devPackages = let env = config.envs.dev; ghc = env.ghc.ghc; minGhc = config.envs.min.ghc.ghc; @@ -92,7 +99,7 @@ let min = minGhc.${name}; profiled = profiledGhc.${name}; }; - local = lib.mapAttrs extra config.envs.dev.derivations; + local = lib.mapAttrs extra (util.env.derivations "packages" "dev"); in local // util.attrsetMain (main: { default = local.${main}; min = local.${main}.min; @@ -100,8 +107,6 @@ let static = staticDrv local.${main}; }); - scopedEnvOutputs = envs: lib.genAttrs envs envOutputs; - envsApi = envs: { env = lib.mapAttrs (n: e: { inherit (e.ghc) pkgs ghc; ghc0 = e.ghc.vanillaGhc; } // fullEnvOutputs n) envs; }; @@ -162,9 +167,10 @@ let in { inherit - prefixedInEnvs + envOutputs scopedEnvOutputs - devOutputs + prefixedInEnvs + devPackages envsApi app appimageApp diff --git a/lib/util.nix b/lib/util.nix index 19814c6c..6db18f18 100644 --- a/lib/util.nix +++ b/lib/util.nix @@ -221,6 +221,8 @@ let env = import ./env.nix { inherit util; }; + output = import ./output.nix { inherit util; }; + hpack = import ./hpack/default.nix { inherit util; }; }; diff --git a/modules/env.nix b/modules/env.nix index 30082806..b59eaf81 100644 --- a/modules/env.nix +++ b/modules/env.nix @@ -153,12 +153,6 @@ let }; }; - ghc = config.ghc.ghc; - - extraPackages = genAttrs global.output.extraPackages (n: ghc.${n}); - - localPackages = genAttrs (util.env.targets config) (n: ghc.${n} // { inherit ghc; }); - ghcidMod = if util.minGhc "9.4" config then config.ghc.pkgs.haskell.lib.dontCheck else id; in { @@ -378,14 +372,6 @@ in { default = false; }; - derivations = mkOption { - description = '' - The derivations for the local Cabal packages using this env's GHC, as well as the - [](#opt-general-output.extraPackages). - ''; - type = lazyAttrsOf package; - }; - localPackage = mkOption { description = '' A function that takes override combinators and a derivation and returns a modified version of that derivation. @@ -597,8 +583,6 @@ in { gen-overrides = mkDefault true; }; - derivations = mkDefault (localPackages // extraPackages); - hostPorts = util.mapListCatAttrs (s: mapAttrs (_: effectiveHostPort) s.ports) resolved; shell = mkDefault (global.pkgs.stdenv.mkDerivation { diff --git a/modules/hpack.nix b/modules/hpack.nix index 1e8cc328..f3f7e23c 100644 --- a/modules/hpack.nix +++ b/modules/hpack.nix @@ -2,7 +2,7 @@ let inherit (lib) types mkOption; - libOutput = import ../lib/output.nix { inherit config lib util; }; + libOutput = util.output; maybeDefaultApp = name: a: if name == config.defaultApp @@ -73,7 +73,8 @@ in { hpack = { apps = lib.mkDefault ( - util.catAttrs (lib.mapAttrsToList (packageApps config.envs.dev.derivations) config.hpack.internal.packages) + let drvs = util.env.derivations "apps" "dev"; + in util.catAttrs (lib.mapAttrsToList (packageApps drvs) config.hpack.internal.packages) ); script = util.hpack.gen { verbose = true; }; diff --git a/modules/output.nix b/modules/output.nix index 0e66520f..db562079 100644 --- a/modules/output.nix +++ b/modules/output.nix @@ -7,8 +7,6 @@ let showConfig = import ../lib/show-config.nix { inherit config lib util; }; - libOutput = import ../lib/output.nix { inherit config lib util; }; - genOverrides = import ../lib/gen-overrides.nix { inherit config lib util; }; showOverrides = import ../lib/show-overrides.nix { inherit config lib util; }; @@ -130,12 +128,12 @@ in { }; basicEnvApps = optionalAttrs config.output.envApps { - env = util.mapListCatAttrs libOutput.envApps (lib.attrValues util.visibleAppEnvs); + env = util.mapListCatAttrs util.output.envApps (lib.attrValues util.visibleAppEnvs); }; lowPrio = { - legacyPackages = libOutput.scopedEnvOutputs config.ghcVersions // libOutput.envsApi config.envs // { + legacyPackages = util.output.scopedEnvOutputs config.ghcVersions // util.output.envsApi config.envs // { inherit config; inherit (config.envs.dev.ghc) pkgs ghc; ghc0 = config.envs.dev.ghc.vanillaGhc; @@ -145,8 +143,8 @@ in { apps = config.hackage.output.apps // basicApps // util.managed.output.apps // - libOutput.mainAppimageApp // - optionalAttrs config.output.commandApps { cmd = libOutput.commandApps config.commands; } // + util.output.mainAppimageApp // + optionalAttrs config.output.commandApps { cmd = util.output.commandApps config.commands; } // basicEnvApps // util.managed.output.gen ; @@ -154,11 +152,11 @@ in { }; highPrio = { - packages = libOutput.devOutputs // libOutput.prefixedInEnvs config.ghcVersions; + packages = util.output.devPackages // util.output.prefixedInEnvs "packages" config.ghcVersions; checks = - config.envs.dev.derivations // - optionalAttrs config.compat.enable (libOutput.prefixedInEnvs config.compat.versions) // + util.output.envOutputs "checks" "dev" // + optionalAttrs config.compat.enable (util.output.prefixedInEnvs "compat" config.compat.versions) // util.managed.output.checks ; @@ -174,7 +172,7 @@ in { apps = let exposedCommands = lib.filterAttrs (_: c: c.expose) config.commands; in - libOutput.commandApps exposedCommands // + util.output.commandApps exposedCommands // { gen-cabal = app "${config.hpack.script}"; gen-cabal-quiet = app "${config.hpack.scriptQuiet}"; diff --git a/modules/package.nix b/modules/package.nix index cd4992f7..b9c547e7 100644 --- a/modules/package.nix +++ b/modules/package.nix @@ -359,6 +359,49 @@ in { }; + expose = { + + packages = mkOption { + description = "Whether to expose this package in [](#opt-output-outputs.packages)."; + type = bool; + default = true; + }; + + apps = mkOption { + description = "Whether to expose this package in [](#opt-output-outputs.apps) if it has executables."; + type = bool; + default = true; + }; + + checks = mkOption { + description = "Whether to expose this package in [](#opt-output-outputs.checks)."; + type = bool; + default = true; + }; + + compat = mkOption { + description = '' + Whether to expose this package in [](#opt-output-outputs.checks) for GHC version + [compat checks](#opt-general-compat). + ''; + type = bool; + default = true; + }; + + scoped = mkOption { + description = '' + Whether to expose this package in [](#opt-output-outputs.legacyPackages) in env-keyed subsets like + `ghc98.`. + These are not evaluated by `nix flake check` and only buildable when referring to the whole path, like + `nix build .#ghc98.`, so they can include packages you don't want evaluated or built frequently + (because they pull in expensive dependencies etc). + ''; + type = bool; + default = true; + }; + + }; + }; config = {