diff --git a/doc/build-helpers/special/buildenv.section.md b/doc/build-helpers/special/buildenv.section.md index 7ae1dbb94e36..e21898c2a27f 100644 --- a/doc/build-helpers/special/buildenv.section.md +++ b/doc/build-helpers/special/buildenv.section.md @@ -12,6 +12,8 @@ For example, [`python.withPackage`](#attributes-on-interpreters-packages) is bas Unless otherwise noted, arguments can be overridden directly using [`.overrideAttrs`](#sec-pkg-overrideAttrs). +`buildEnv` enforces [structured attributes (`{ __structuredAttrs = true; }`)](https://nix.dev/manual/nix/2.18/language/advanced-attributes.html#adv-attr-structuredAttrs). + - `name` or `pname` and `version` (required): The name of the environment. diff --git a/doc/release-notes/rl-2605.section.md b/doc/release-notes/rl-2605.section.md index b7aa319a57e6..247927675053 100644 --- a/doc/release-notes/rl-2605.section.md +++ b/doc/release-notes/rl-2605.section.md @@ -80,6 +80,8 @@ - Note that the above `nodePackages` removal also coincides with the removal of `node2nix` and its tooling, which have been deprecated for a long time. +- `buildEnv`-constructed packages now take only [structured attributes (`{ __structuredAttrs = true; }`)](https://nix.dev/manual/nix/2.18/language/advanced-attributes.html#adv-attr-structuredAttrs). + - `xfce.mkXfceDerivation` has been deprecated (i.e. conditioned behind `nixpkgs.config.allowAliases`) and will be removed in NixOS 26.11, please use `stdenv.mkDerivation` directly. You can migrate by adding `pkg-config`, `xfce4-dev-tools`, and `wrapGAppsHook3` to your `nativeBuildInputs` and diff --git a/pkgs/build-support/buildenv/builder.pl b/pkgs/build-support/buildenv/builder.pl index cf4fc875b585..d065ec214e06 100644 --- a/pkgs/build-support/buildenv/builder.pl +++ b/pkgs/build-support/buildenv/builder.pl @@ -12,10 +12,35 @@ STDOUT->autoflush(1); $SIG{__WARN__} = sub { warn "pkgs.buildEnv warning: ", @_ }; $SIG{__DIE__} = sub { die "pkgs.buildEnv error: ", @_ }; -my $out = $ENV{"out"}; -my $extraPrefix = $ENV{"extraPrefix"}; +my $out; +my $extraPrefix; +my @pathsToLink; +my $ignoreCollisions; +my $checkCollisionContents; +my $ignoreSingleFileOutputs; +my @chosenOutputsRefs; +my $extraPathsFrom; +my $manifest; -my @pathsToLink = @{decode_json $ENV{"pathsToLinkJSON"}}; +if ($ENV{"NIX_ATTRS_JSON_FILE"} // "") { + open FILE, $ENV{"NIX_ATTRS_JSON_FILE"} or die "cannot open structured attrs JSON file $ENV{NIX_ATTRS_JSON_FILE}: $!"; + my $json_text = do { local $/; }; + my $attrsFromJSONRef = decode_json $json_text; + close FILE; + + my $outputsRef = $attrsFromJSONRef->{"outputs"}; + $out = $outputsRef->{"out"} // (values %{$outputsRef})[0]; + $extraPrefix = $attrsFromJSONRef->{"extraPrefix"}; + @pathsToLink = @{$attrsFromJSONRef->{"pathsToLink"}}; + $ignoreCollisions = $attrsFromJSONRef->{"ignoreCollisions"}; + $checkCollisionContents = $attrsFromJSONRef->{"checkCollisionContents"}; + $ignoreSingleFileOutputs = $attrsFromJSONRef->{"ignoreSingleFileOutputs"}; + @chosenOutputsRefs = @{$attrsFromJSONRef->{"chosenOutputs"}}; + $extraPathsFrom = $attrsFromJSONRef->{"extraPathsFrom"}; + $manifest = $attrsFromJSONRef->{"manifest"}; +} else { + die "missing required environment variable NIX_ATTRS_JSON_FILE"; +} sub isInPathsToLink($path) { $path = "/" if $path eq ""; @@ -210,26 +235,15 @@ sub addPkg($pkgDir, $ignoreCollisions, $checkCollisionContents, $priority, $igno } } -# Read packages list. -my $pkgs; - -if (exists $ENV{"pkgsPath"}) { - open FILE, $ENV{"pkgsPath"}; - $pkgs = ; - close FILE; -} else { - $pkgs = $ENV{"pkgs"} -} - # Symlink to the packages that have been installed explicitly by the # user. -for my $pkg (@{decode_json $pkgs}) { +for my $pkg (@chosenOutputsRefs) { for my $path (@{$pkg->{paths}}) { addPkg($path, - $ENV{"ignoreCollisions"} eq "1", - $ENV{"checkCollisionContents"} eq "1", + $ignoreCollisions, + $checkCollisionContents, $pkg->{priority}, - $ENV{"ignoreSingleFileOutputs"} eq "1") + $ignoreSingleFileOutputs) if -e $path; } } @@ -244,21 +258,20 @@ while (scalar(keys %postponed) > 0) { my @pkgDirs = keys %postponed; %postponed = (); foreach my $pkgDir (sort @pkgDirs) { - addPkg($pkgDir, 2, $ENV{"checkCollisionContents"} eq "1", $priorityCounter++, $ENV{"ignoreSingleFileOutputs"} eq "1"); + addPkg($pkgDir, 2, $checkCollisionContents, $priorityCounter++, $ignoreSingleFileOutputs); } } -my $extraPathsFilePath = $ENV{"extraPathsFrom"}; -if ($extraPathsFilePath) { - open FILE, $extraPathsFilePath or die "cannot open extra paths file $extraPathsFilePath: $!"; +if ($extraPathsFrom) { + open FILE, $extraPathsFrom or die "cannot open extra paths file $extraPathsFrom: $!"; while(my $line = ) { chomp $line; addPkg($line, - $ENV{"ignoreCollisions"} eq "1", - $ENV{"checkCollisionContents"} eq "1", + $ignoreCollisions, + $checkCollisionContents, 1000, - $ENV{"ignoreSingleFileOutputs"} eq "1") + $ignoreSingleFileOutputs) if -d $line; } @@ -286,7 +299,6 @@ foreach my $relName (sort keys %symlinks) { print STDERR "created $nrLinks symlinks in user environment\n"; -my $manifest = $ENV{"manifest"}; if ($manifest) { symlink($manifest, "$out/manifest") or die "cannot create manifest"; } diff --git a/pkgs/build-support/buildenv/default.nix b/pkgs/build-support/buildenv/default.nix index 9b7a828b8293..a645224ffa54 100644 --- a/pkgs/build-support/buildenv/default.nix +++ b/pkgs/build-support/buildenv/default.nix @@ -92,6 +92,25 @@ lib.makeOverridable ( // lib.optionalAttrs (args ? buildInputs) { inherit buildInputs; }; + in + compatArgs + // derivationArgs + // { + # Explicitly opt in: builder.pl reads all configuration from file $ENV["NIX_ATTRS_JSON_FILE"]. + __structuredAttrs = true; + + inherit + extraOutputsToInstall + manifest + ignoreCollisions + checkCollisionContents + ignoreSingleFileOutputs + includeClosures + meta + pathsToLink + extraPrefix + postBuild + ; chosenOutputs = map (drv: { paths = @@ -115,43 +134,19 @@ lib.makeOverridable ( # Silently use the original `paths` if `passthru.paths` is missing. }) finalAttrs.passthru.paths or paths; - pathsForClosure = lib.pipe chosenOutputs [ - (map (p: p.paths)) - lib.flatten - (lib.remove null) - ]; - in - compatArgs - // derivationArgs - // { - inherit - extraOutputsToInstall - manifest - ignoreCollisions - checkCollisionContents - ignoreSingleFileOutputs - includeClosures - meta - pathsToLink - extraPrefix - postBuild - ; - pathsToLinkJSON = builtins.toJSON pathsToLink; - pkgs = builtins.toJSON chosenOutputs; - extraPathsFrom = lib.optionalString finalAttrs.includeClosures (writeClosure pathsForClosure); - - # Explicitly opt out: builder.pl reads all configuration from %ENV, - # which is fundamentally incompatible with __structuredAttrs = true. - __structuredAttrs = false; + extraPathsFrom = lib.optionalString finalAttrs.includeClosures ( + let + pathsForClosure = lib.pipe finalAttrs.chosenOutputs [ + (map (p: p.paths)) + lib.flatten + (lib.remove null) + ]; + in + writeClosure pathsForClosure + ); preferLocalBuild = derivationArgs.preferLocalBuild or true; allowSubstitutes = derivationArgs.allowSubstitutes or false; - passAsFile = [ - "buildCommand" - ] - # XXX: The size is somewhat arbitrary - ++ lib.optional (lib.stringLength finalAttrs.pkgs >= 128 * 1024) "pkgs" - ++ derivationArgs.passAsFile or [ ]; buildCommand = '' ${buildPackages.perl}/bin/perl -w ${builder} diff --git a/pkgs/test/buildenv.nix b/pkgs/test/buildenv.nix index 8ca7a1d7b2e4..f47abe246446 100644 --- a/pkgs/test/buildenv.nix +++ b/pkgs/test/buildenv.nix @@ -275,16 +275,16 @@ let touch $out ''; - # buildEnv explicitly sets __structuredAttrs = false because builder.pl - # reads all inputs from environment variables. Verify the build succeeds - # even when derivationArgs tries to enable structuredAttrs. + # buildEnv explicitly sets __structuredAttrs = true because builder.pl + # reads all inputs from `$NIX_ATTRS_JSON_FILE`. + # Verify the build succeeds even when derivationArgs tries to disable structuredAttrs. structuredAttrs-overridden = pkgs.runCommand "test-buildenv-structuredAttrs-overridden" { testEnv = buildEnv { name = "test-env-structuredAttrs"; paths = [ pkgs.hello ]; - derivationArgs.__structuredAttrs = true; + derivationArgs.__structuredAttrs = false; }; } '' @@ -313,9 +313,9 @@ let ''; }; - # buildEnv's builder.pl reads all inputs from %ENV, which is - # fundamentally incompatible with __structuredAttrs = true. - # buildEnv explicitly forces __structuredAttrs = false. + # buildEnv's builder.pl reads all inputs from `$NIX_ATTRS_JSON_FILE`, + # which requires __structuredAttrs = true. + # buildEnv explicitly forces __structuredAttrs = true. tests-structuredAttrs = { testStructuredAttrsExplicitlyFalse = { expr = @@ -323,7 +323,7 @@ let name = "test-env"; paths = [ ]; }).__structuredAttrs; - expected = false; + expected = true; }; testStructuredAttrsCantBeOverriddenViaDerivationArgs = { @@ -331,9 +331,9 @@ let (buildEnv { name = "test-env"; paths = [ ]; - derivationArgs.__structuredAttrs = true; + derivationArgs.__structuredAttrs = false; }).__structuredAttrs; - expected = false; + expected = true; }; }; diff --git a/pkgs/tools/typesetting/tex/texlive/build-tex-env.sh b/pkgs/tools/typesetting/tex/texlive/build-tex-env.sh index ec755554b80d..7a2f8c6efa9d 100644 --- a/pkgs/tools/typesetting/tex/texlive/build-tex-env.sh +++ b/pkgs/tools/typesetting/tex/texlive/build-tex-env.sh @@ -123,15 +123,13 @@ installtl_do_path_adjustments () { ln -s "$texmfdist" "$out"/share/texmf # generate other outputs - local otherOutput otherOutputName - local otherOutputs="$otherOutputs" - for otherOutputName in $outputs ; do + local otherOutputIdx=0 otherOutputName + for otherOutputName in "${!outputs[@]}" ; do if [[ $otherOutputName == out ]] ; then continue fi - otherOutput="${otherOutputs%% *}" - otherOutputs="${otherOutputs#* }" - ln -s "$otherOutput" "${!otherOutputName}" + ln -s "${otherOutputs[$otherOutputIdx]}" "${outputs[$otherOutputName]}" + ((otherOutputIdx++)) || true done }