mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
devShells: Infer inputs from input closure boundary
This commit is contained in:
parent
e2040aecac
commit
1fa235b77c
1 changed files with 203 additions and 25 deletions
|
|
@ -3,10 +3,118 @@
|
||||||
devFlake,
|
devFlake,
|
||||||
}:
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# Some helper functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
Compute a filtered closure of build inputs.
|
||||||
|
|
||||||
|
Specifically, `buildInputsClosure cond startSet` computes the closure formed
|
||||||
|
by recursive application of `p: filter cond p.buildInputs ++ filter cond p.propagatedBuildInputs`
|
||||||
|
to `startSet`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```nix
|
||||||
|
builtInputsClosure isInternal [ pkg1 pkg2 ]
|
||||||
|
=> [ pkg1 pkg3 pkg2 pkg10 ]
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: order tbd
|
||||||
|
|
||||||
|
Note: `startSet` is *NOT* filtered.
|
||||||
|
*/
|
||||||
|
buildInputsClosureCond =
|
||||||
|
cond: startSet:
|
||||||
|
let
|
||||||
|
closure = builtins.genericClosure {
|
||||||
|
startSet = map (d: {
|
||||||
|
key = d.drvPath;
|
||||||
|
value = d;
|
||||||
|
}) startSet;
|
||||||
|
operator =
|
||||||
|
d:
|
||||||
|
let
|
||||||
|
r =
|
||||||
|
map
|
||||||
|
(d': {
|
||||||
|
key = d'.drvPath;
|
||||||
|
value = d';
|
||||||
|
})
|
||||||
|
(
|
||||||
|
lib.filter cond d.value.buildInputs or [ ] ++ lib.filter cond d.value.propagatedBuildInputs or [ ]
|
||||||
|
);
|
||||||
|
in
|
||||||
|
r;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
map (item: item.value) closure;
|
||||||
|
|
||||||
|
/**
|
||||||
|
`[ pkg1 pkg2 ]` -> `{ "...-pkg2.drv" = null; "...-pkg1.drv" = null }`
|
||||||
|
|
||||||
|
Note: fairly arbitrary order (hash based). Use for efficient set membership test only.
|
||||||
|
*/
|
||||||
|
byDrvPath =
|
||||||
|
l:
|
||||||
|
lib.listToAttrs (
|
||||||
|
map (c: {
|
||||||
|
name =
|
||||||
|
# Just a lookup key
|
||||||
|
builtins.unsafeDiscardStringContext c.drvPath;
|
||||||
|
value = null;
|
||||||
|
}) l
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Stable dedup.
|
||||||
|
|
||||||
|
Unlike `listToAttrs` -> `attrValues`, this preserves the input ordering,
|
||||||
|
which is more predictable ("deterministic") than e.g. sorting store paths,
|
||||||
|
whose hashes affect the ordering on every change.
|
||||||
|
*/
|
||||||
|
# TODO: add to Nixpkgs lib, refer from uniqueStrings
|
||||||
|
dedupByString =
|
||||||
|
key: l:
|
||||||
|
let
|
||||||
|
r =
|
||||||
|
lib.foldl'
|
||||||
|
(
|
||||||
|
a@{ list, set }:
|
||||||
|
elem:
|
||||||
|
let
|
||||||
|
k = builtins.unsafeDiscardStringContext (key elem);
|
||||||
|
in
|
||||||
|
if set ? ${k} then
|
||||||
|
a
|
||||||
|
else
|
||||||
|
let
|
||||||
|
# Note: O(n²) copying. Use linkedLists to concat them in one go at the end.
|
||||||
|
# https://github.com/NixOS/nixpkgs/pull/452088
|
||||||
|
newList = [ elem ] ++ list;
|
||||||
|
newSet = set // {
|
||||||
|
${k} = null;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
builtins.seq newList builtins.seq newSet {
|
||||||
|
list = newList;
|
||||||
|
set = newSet;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
{
|
||||||
|
list = [ ];
|
||||||
|
set = { };
|
||||||
|
}
|
||||||
|
l;
|
||||||
|
in
|
||||||
|
r.list;
|
||||||
|
|
||||||
|
in
|
||||||
|
|
||||||
{ pkgs }:
|
{ pkgs }:
|
||||||
|
|
||||||
|
# TODO: don't use nix-util for this?
|
||||||
pkgs.nixComponents2.nix-util.overrideAttrs (
|
pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||||
attrs:
|
finalAttrs: prevAttrs:
|
||||||
|
|
||||||
let
|
let
|
||||||
stdenv = pkgs.nixDependencies2.stdenv;
|
stdenv = pkgs.nixDependencies2.stdenv;
|
||||||
|
|
@ -21,13 +129,89 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||||
"-D${prefix}:${rest}";
|
"-D${prefix}:${rest}";
|
||||||
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
|
havePerl = stdenv.buildPlatform == stdenv.hostPlatform && stdenv.hostPlatform.isUnix;
|
||||||
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
|
ignoreCrossFile = flags: builtins.filter (flag: !(lib.strings.hasInfix "cross-file" flag)) flags;
|
||||||
|
|
||||||
|
activeComponents = buildInputsClosureCond isInternal (
|
||||||
|
lib.attrValues (finalAttrs.passthru.config.getComponents allComponents)
|
||||||
|
);
|
||||||
|
|
||||||
|
allComponents = lib.filterAttrs (k: v: lib.isDerivation v) pkgs.nixComponents2;
|
||||||
|
internalDrvs = byDrvPath (
|
||||||
|
# Drop the attr names (not present in buildInputs anyway)
|
||||||
|
lib.attrValues allComponents
|
||||||
|
++ lib.concatMap (c: lib.attrValues c.tests or { }) (lib.attrValues allComponents)
|
||||||
|
);
|
||||||
|
|
||||||
|
isInternal =
|
||||||
|
dep: internalDrvs ? ${builtins.unsafeDiscardStringContext dep.drvPath or "_non-existent_"};
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
pname = "shell-for-" + attrs.pname;
|
pname = "shell-for-nix";
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit activeComponents;
|
||||||
|
|
||||||
|
# We use this attribute to store non-derivation values like functions and
|
||||||
|
# perhaps other things that are primarily for overriding and not the shell.
|
||||||
|
config = {
|
||||||
|
# Default getComponents
|
||||||
|
getComponents =
|
||||||
|
c:
|
||||||
|
builtins.removeAttrs c (
|
||||||
|
lib.optionals (!havePerl) [ "nix-perl-bindings" ]
|
||||||
|
++ lib.optionals (!buildCanExecuteHost) [ "nix-manual" ]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Produce a devShell for a given set of nix components
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
shell.withActiveComponents (c: {
|
||||||
|
inherit (c) nix-util;
|
||||||
|
})
|
||||||
|
```
|
||||||
|
*/
|
||||||
|
withActiveComponents =
|
||||||
|
f2:
|
||||||
|
finalAttrs.finalPackage.overrideAttrs (
|
||||||
|
finalAttrs: prevAttrs: {
|
||||||
|
passthru = prevAttrs.passthru // {
|
||||||
|
config = prevAttrs.passthru.config // {
|
||||||
|
getComponents = f2;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
small =
|
||||||
|
(finalAttrs.finalPackage.withActiveComponents (c: {
|
||||||
|
inherit (c)
|
||||||
|
nix-cli
|
||||||
|
nix-util-tests
|
||||||
|
nix-store-tests
|
||||||
|
nix-expr-tests
|
||||||
|
nix-fetchers-tests
|
||||||
|
nix-flake-tests
|
||||||
|
nix-functional-tests
|
||||||
|
# Currently required
|
||||||
|
nix-perl-bindings
|
||||||
|
;
|
||||||
|
})).overrideAttrs
|
||||||
|
(o: {
|
||||||
|
mesonFlags = o.mesonFlags ++ [
|
||||||
|
# TODO: infer from activeComponents or vice versa
|
||||||
|
"-Dkaitai-struct-checks=false"
|
||||||
|
"-Djson-schema-checks=false"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
|
# Remove the version suffix to avoid unnecessary attempts to substitute in nix develop
|
||||||
version = lib.fileContents ../.version;
|
version = lib.fileContents ../.version;
|
||||||
name = attrs.pname;
|
name = finalAttrs.pname;
|
||||||
|
|
||||||
installFlags = "sysconfdir=$(out)/etc";
|
installFlags = "sysconfdir=$(out)/etc";
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
|
|
@ -98,17 +282,9 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||||
nativeBuildInputs =
|
nativeBuildInputs =
|
||||||
let
|
let
|
||||||
inputs =
|
inputs =
|
||||||
attrs.nativeBuildInputs or [ ]
|
dedupByString (v: "${v}") (
|
||||||
++ pkgs.nixComponents2.nix-util.nativeBuildInputs
|
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.nativeBuildInputs) activeComponents)
|
||||||
++ pkgs.nixComponents2.nix-store.nativeBuildInputs
|
)
|
||||||
++ pkgs.nixComponents2.nix-fetchers.nativeBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-expr.nativeBuildInputs
|
|
||||||
++ lib.optionals havePerl pkgs.nixComponents2.nix-perl-bindings.nativeBuildInputs
|
|
||||||
++ lib.optionals buildCanExecuteHost pkgs.nixComponents2.nix-manual.externalNativeBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-internal-api-docs.nativeBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-external-api-docs.nativeBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-functional-tests.externalNativeBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-json-schema-checks.externalNativeBuildInputs
|
|
||||||
++ lib.optional (
|
++ lib.optional (
|
||||||
!buildCanExecuteHost
|
!buildCanExecuteHost
|
||||||
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
|
# Hack around https://github.com/nixos/nixpkgs/commit/bf7ad8cfbfa102a90463433e2c5027573b462479
|
||||||
|
|
@ -117,9 +293,7 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||||
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)
|
&& lib.meta.availableOn stdenv.buildPlatform (stdenv.hostPlatform.emulator pkgs.buildPackages)
|
||||||
) pkgs.buildPackages.mesonEmulatorHook
|
) pkgs.buildPackages.mesonEmulatorHook
|
||||||
++ [
|
++ [
|
||||||
pkgs.buildPackages.cmake
|
|
||||||
pkgs.buildPackages.gnused
|
pkgs.buildPackages.gnused
|
||||||
pkgs.buildPackages.changelog-d
|
|
||||||
modular.pre-commit.settings.package
|
modular.pre-commit.settings.package
|
||||||
(pkgs.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript)
|
(pkgs.writeScriptBin "pre-commit-hooks-install" modular.pre-commit.settings.installationScript)
|
||||||
pkgs.buildPackages.nixfmt-rfc-style
|
pkgs.buildPackages.nixfmt-rfc-style
|
||||||
|
|
@ -136,18 +310,22 @@ pkgs.nixComponents2.nix-util.overrideAttrs (
|
||||||
# from making its way into NIX_CFLAGS_COMPILE.
|
# from making its way into NIX_CFLAGS_COMPILE.
|
||||||
lib.filter (p: !lib.hasInfix "separate-debug-info" p) inputs;
|
lib.filter (p: !lib.hasInfix "separate-debug-info" p) inputs;
|
||||||
|
|
||||||
|
propagatedNativeBuildInputs = dedupByString (v: "${v}") (
|
||||||
|
lib.filter (x: !isInternal x) (
|
||||||
|
lib.lists.concatMap (c: c.propagatedNativeBuildInputs) activeComponents
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
pkgs.gbenchmark
|
pkgs.gbenchmark
|
||||||
]
|
]
|
||||||
++ attrs.buildInputs or [ ]
|
++ dedupByString (v: "${v}") (
|
||||||
++ pkgs.nixComponents2.nix-util.buildInputs
|
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.buildInputs) activeComponents)
|
||||||
++ pkgs.nixComponents2.nix-store.buildInputs
|
)
|
||||||
++ pkgs.nixComponents2.nix-store-tests.externalBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-fetchers.buildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-expr.buildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-expr.externalPropagatedBuildInputs
|
|
||||||
++ pkgs.nixComponents2.nix-cmd.buildInputs
|
|
||||||
++ lib.optionals havePerl pkgs.nixComponents2.nix-perl-bindings.externalBuildInputs
|
|
||||||
++ lib.optional havePerl pkgs.perl;
|
++ lib.optional havePerl pkgs.perl;
|
||||||
|
|
||||||
|
propagatedBuildInputs = dedupByString (v: "${v}") (
|
||||||
|
lib.filter (x: !isInternal x) (lib.lists.concatMap (c: c.propagatedBuildInputs) activeComponents)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue