Unverified Commit 3d2dd99d authored by Emily's avatar Emily Committed by GitHub
Browse files

stdenv.mkDerivation: small performance wins (#513729)

parents 8c5eb03b 9c56dc66
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -274,6 +274,8 @@

- The default packages in `services.jenkins.packages` have been dropped, since not every Jenkins installation needs any package at all. It's more reasonable to leave it empty and let users configure what they need.

- The `pie` hardening flag has been removed and will now error, after being deprecated in 25.11. Compilers are expected to enable PIE by default, as has been common practice since 2016 outside of Nixpkgs. If a package needs `pie` disabled pass `-no-pie` in `CFLAGS`. It is unlikely this will be necessary in many cases; due to the prevalence of default PIE toolchains, most packages incompatible with PIE already pass `-no-pie`.

## Other Notable Changes {#sec-nixpkgs-release-26.05-notable-changes}

<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
+136 −156
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ let
    concatMapStrings
    concatStringsSep
    elem
    elemAt
    extendDerivation
    filter
    filterAttrs
@@ -95,15 +94,15 @@ let
      # NOTE: the above documentation had to be duplicated in `lib/customisation.nix`: `makeOverridable`.
      overrideAttrs =
        f0:
        let
          extends' =
            overlay: f:
            (
        makeDerivationExtensible (
          final:
          let
                prev = f final;
                thisOverlay = overlay final prev;
                warnForBadVersionOverride = (
            prev = rattrs final;
            thisOverlay = lib.toExtension f0 final prev;
            pos = builtins.unsafeGetAttrPos "version" thisOverlay;
          in
          lib.warnIf
            (
              prev ? src
              && thisOverlay ? version
              && prev ? version
@@ -112,14 +111,10 @@ let
              # && prev.version != thisOverlay.version
              && !(thisOverlay ? src)
              && !(thisOverlay.__intentionallyOverridingVersion or false)
                );
                pname = args.pname or "<unknown name>";
                version = args.version or "<unknown version>";
                pos = builtins.unsafeGetAttrPos "version" thisOverlay;
              in
              lib.warnIf warnForBadVersionOverride ''
            )
            ''
              ${
                  args.name or "${pname}-${version}"
                args.name or "${args.pname or "<unknown name>"}-${args.version or "<unknown version>"}"
              } was overridden with `version` but not `src` at ${pos.file or "<unknown file>"}:${
                toString pos.line or "<unknown line>"
              }:${toString pos.column or "<unknown column>"}.
@@ -136,10 +131,9 @@ let
              })

              (To silence this warning, set `__intentionallyOverridingVersion = true` in your `overrideAttrs` call.)
              '' (prev // (removeAttrs thisOverlay [ "__intentionallyOverridingVersion" ]))
            ''
            (prev // (removeAttrs thisOverlay [ "__intentionallyOverridingVersion" ]))
        );
        in
        makeDerivationExtensible (extends' (lib.toExtension f0) rattrs);

      finalPackage = mkDerivationSimple overrideAttrs args;

@@ -375,17 +369,6 @@ let

      ...
    }@attrs:

    # Policy on acceptable hash types in nixpkgs
    assert
      attrs ? outputHash
      -> (
        let
          algo = attrs.outputHashAlgo or (head (splitString "-" attrs.outputHash));
        in
        if algo == "md5" then throw "Rejected insecure ${algo} hash '${attrs.outputHash}'" else true
      );

    let
      # TODO(@oxij, @Ericson2314): This is here to keep the old semantics, remove when
      # no package has `doCheck = true`.
@@ -395,13 +378,17 @@ let
      separateDebugInfo' =
        let
          actualValue = separateDebugInfo && isLinux;
          conflictingOption =
        in
        if
          actualValue
          && (
            attrs ? "disallowedReferences"
            || attrs ? "disallowedRequisites"
            || attrs ? "allowedRequisites"
            || attrs ? "allowedReferences";
        in
        if actualValue && conflictingOption && !__structuredAttrs then
            || attrs ? "allowedReferences"
          )
          && !__structuredAttrs
        then
          throw "separateDebugInfo = true in ${
            attrs.pname or "mkDerivation argument"
          } requires __structuredAttrs if {dis,}allowedRequisites or {dis,}allowedReferences is set"
@@ -410,7 +397,7 @@ let
      outputs' = outputs ++ optional separateDebugInfo' "debug";

      noNonNativeDeps =
        builtins.length (
        (
          depsBuildTarget
          ++ depsBuildTargetPropagated
          ++ depsHostHost
@@ -419,12 +406,12 @@ let
          ++ propagatedBuildInputs
          ++ depsTargetTarget
          ++ depsTargetTargetPropagated
        ) == 0;
        ) == [ ];
      dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || !stdenvHasCC;

      concretizeFlagImplications =
        flag: impliesFlags: list:
        if builtins.elem flag list then (list ++ impliesFlags) else list;
        if elem flag list then (list ++ impliesFlags) else list;

      hardeningDisable' = unique (
        pipe hardeningDisable [
@@ -437,12 +424,12 @@ let
        ]
      );
      enabledHardeningOptions =
        if builtins.elem "all" hardeningDisable' then
        if elem "all" hardeningDisable' then
          [ ]
        else
          subtractLists hardeningDisable' (defaultHardeningFlags ++ hardeningEnable);
      # hardeningDisable additionally supports "all".
      erroneousHardeningFlags = subtractLists (knownHardeningFlags ++ [ "pie" ]) (
      erroneousHardeningFlags = subtractLists knownHardeningFlags (
        hardeningEnable ++ remove "all" hardeningDisable
      );

@@ -451,7 +438,7 @@ let
        positions: name: deps:
        imap1 (
          index: dep:
          if dep == null || isDerivation dep || builtins.isString dep || builtins.isPath dep then
          if dep == null || isDerivation dep || isString dep || builtins.isPath dep then
            dep
          else if isList dep then
            checkDependencyList' ([ index ] ++ positions) name dep
@@ -461,7 +448,7 @@ let
            }${name} for ${attrs.name or attrs.pname}"
        ) deps;
    in
    if builtins.length erroneousHardeningFlags != 0 then
    if erroneousHardeningFlags != [ ] then
      abort (
        "mkDerivation was called with unsupported hardening flags: "
        + lib.generators.toPretty { } {
@@ -488,53 +475,58 @@ let

        outputs = outputs';

        dependencies = [
          [
            (map (drv: getDev drv.__spliced.buildBuild or drv) (
        buildBuildOutputs = map (drv: getDev drv.__spliced.buildBuild or drv) (
          checkDependencyList "depsBuildBuild" depsBuildBuild
            ))
            (map (drv: getDev drv.__spliced.buildHost or drv) (
        );
        buildHostOutputs = map (drv: getDev drv.__spliced.buildHost or drv) (
          checkDependencyList "nativeBuildInputs" nativeBuildInputs'
            ))
            (map (drv: getDev drv.__spliced.buildTarget or drv) (
        );
        buildTargetOutputs = map (drv: getDev drv.__spliced.buildTarget or drv) (
          checkDependencyList "depsBuildTarget" depsBuildTarget
            ))
          ]
          [
            (map (drv: getDev drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost))
            (map (drv: getDev drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs'))
          ]
          [
            (map (drv: getDev drv.__spliced.targetTarget or drv) (
        );
        hostHostOutputs = map (drv: getDev drv.__spliced.hostHost or drv) (
          checkDependencyList "depsHostHost" depsHostHost
        );
        hostTargetOutputs = map (drv: getDev drv.__spliced.hostTarget or drv) (
          checkDependencyList "buildInputs" buildInputs'
        );
        targetTargetOutputs = map (drv: getDev drv.__spliced.targetTarget or drv) (
          checkDependencyList "depsTargetTarget" depsTargetTarget
            ))
          ]
        );
        allDependencies = concatLists [
          buildBuildOutputs
          buildHostOutputs
          buildTargetOutputs
          hostHostOutputs
          hostTargetOutputs
          targetTargetOutputs
        ];
        propagatedDependencies = [
          [
            (map (drv: getDev drv.__spliced.buildBuild or drv) (

        propagatedBuildBuildOutputs = map (drv: getDev drv.__spliced.buildBuild or drv) (
          checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated
            ))
            (map (drv: getDev drv.__spliced.buildHost or drv) (
        );
        propagatedBuildHostOutputs = map (drv: getDev drv.__spliced.buildHost or drv) (
          checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs
            ))
            (map (drv: getDev drv.__spliced.buildTarget or drv) (
        );
        propagatedBuildTargetOutputs = map (drv: getDev drv.__spliced.buildTarget or drv) (
          checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated
            ))
          ]
          [
            (map (drv: getDev drv.__spliced.hostHost or drv) (
        );
        propagatedHostHostOutputs = map (drv: getDev drv.__spliced.hostHost or drv) (
          checkDependencyList "depsHostHostPropagated" depsHostHostPropagated
            ))
            (map (drv: getDev drv.__spliced.hostTarget or drv) (
        );
        propagatedHostTargetOutputs = map (drv: getDev drv.__spliced.hostTarget or drv) (
          checkDependencyList "propagatedBuildInputs" propagatedBuildInputs
            ))
          ]
          [
            (map (drv: getDev drv.__spliced.targetTarget or drv) (
        );
        propagatedTargetTargetOutputs = map (drv: getDev drv.__spliced.targetTarget or drv) (
          checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated
            ))
          ]
        );
        allPropagatedDependencies = concatLists [
          propagatedBuildBuildOutputs
          propagatedBuildHostOutputs
          propagatedBuildTargetOutputs
          propagatedHostHostOutputs
          propagatedHostTargetOutputs
          propagatedTargetTargetOutputs
        ];

        derivationArg = removeAttrs attrs removedOrReplacedAttrNames // {
@@ -586,19 +578,19 @@ let
          __ignoreNulls = true;
          inherit __structuredAttrs strictDeps;

          depsBuildBuild = elemAt (elemAt dependencies 0) 0;
          nativeBuildInputs = elemAt (elemAt dependencies 0) 1;
          depsBuildTarget = elemAt (elemAt dependencies 0) 2;
          depsHostHost = elemAt (elemAt dependencies 1) 0;
          buildInputs = elemAt (elemAt dependencies 1) 1;
          depsTargetTarget = elemAt (elemAt dependencies 2) 0;
          depsBuildBuild = buildBuildOutputs;
          nativeBuildInputs = buildHostOutputs;
          depsBuildTarget = buildTargetOutputs;
          depsHostHost = hostHostOutputs;
          buildInputs = hostTargetOutputs;
          depsTargetTarget = targetTargetOutputs;

          depsBuildBuildPropagated = elemAt (elemAt propagatedDependencies 0) 0;
          propagatedNativeBuildInputs = elemAt (elemAt propagatedDependencies 0) 1;
          depsBuildTargetPropagated = elemAt (elemAt propagatedDependencies 0) 2;
          depsHostHostPropagated = elemAt (elemAt propagatedDependencies 1) 0;
          propagatedBuildInputs = elemAt (elemAt propagatedDependencies 1) 1;
          depsTargetTargetPropagated = elemAt (elemAt propagatedDependencies 2) 0;
          depsBuildBuildPropagated = propagatedBuildBuildOutputs;
          propagatedNativeBuildInputs = propagatedBuildHostOutputs;
          depsBuildTargetPropagated = propagatedBuildTargetOutputs;
          depsHostHostPropagated = propagatedHostHostOutputs;
          propagatedBuildInputs = propagatedHostTargetOutputs;
          depsTargetTargetPropagated = propagatedTargetTargetOutputs;

          # This parameter is sometimes a string, sometimes null, and sometimes a list, yuck
          configureFlags =
@@ -637,9 +629,7 @@ let
            else
              null
          } =
            lib.warnIf ((builtins.elem "pie" hardeningEnable) || (builtins.elem "pie" hardeningDisable))
              "The 'pie' hardening flag has been removed in favor of enabling PIE by default in compilers and should no longer be used. PIE can be disabled with the -no-pie compiler flag, but this is usually not necessary as most build systems pass this if needed. Usage of the 'pie' hardening flag will become an error in future."
              (builtins.concatStringsSep " " enabledHardeningOptions);
            concatStringsSep " " enabledHardeningOptions;

          # TODO: remove platform condition
          # Enabling this check could be a breaking change as it requires to edit nix.conf
@@ -651,8 +641,6 @@ let
          ${if buildIsDarwin then "__darwinAllowLocalNetworking" else null} = __darwinAllowLocalNetworking;
          ${if buildIsDarwin then "__sandboxProfile" else null} =
            let
              allDependencies = concatLists (concatLists dependencies);
              allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
              computedSandboxProfile = concatMap (input: input.__propagatedSandboxProfile or [ ]) (
                extraNativeBuildInputs ++ extraBuildInputs ++ allDependencies
              );
@@ -673,7 +661,6 @@ let
            concatStringsSep "\n" (filter (x: x != "") (unique profiles));
          ${if buildIsDarwin then "__propagatedSandboxProfile" else null} =
            let
              allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
              computedPropagatedSandboxProfile = concatMap (
                input: input.__propagatedSandboxProfile or [ ]
              ) allPropagatedDependencies;
@@ -681,8 +668,6 @@ let
            unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]);
          ${if buildIsDarwin then "__impureHostDeps" else null} =
            let
              allDependencies = concatLists (concatLists dependencies);
              allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
              computedImpureHostDeps = unique (
                concatMap (input: input.__propagatedImpureHostDeps or [ ]) (
                  extraNativeBuildInputs ++ extraBuildInputs ++ allDependencies
@@ -705,7 +690,6 @@ let
            ];
          ${if buildIsDarwin then "__propagatedImpureHostDeps" else null} =
            let
              allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
              computedPropagatedImpureHostDeps = unique (
                concatMap (input: input.__propagatedImpureHostDeps or [ ]) allPropagatedDependencies
              );
@@ -715,7 +699,7 @@ let
          # -- Windows/Cygwin-specific attrs --
          ${if isWindows || isCygwin then "allowedImpureDLLs" else null} =
            allowedImpureDLLs
            ++ lib.optionals isCygwin [
            ++ optionals isCygwin [
              "KERNEL32.dll"
            ];

@@ -738,7 +722,7 @@ let
                inherit name;
                value =
                  let
                    raw = zipAttrsWith (_: builtins.concatLists) [
                    raw = zipAttrsWith (_: concatLists) [
                      attrsOutputChecksFiltered
                      (makeOutputChecks attrs.outputChecks.${name} or { })
                    ];
@@ -820,9 +804,8 @@ let
      );

    let
      mainProgram = meta.mainProgram or null;
      env' = env // {
        ${if mainProgram != null then "NIX_MAIN_PROGRAM" else null} = mainProgram;
        ${if meta ? mainProgram then "NIX_MAIN_PROGRAM" else null} = meta.mainProgram;
      };

      derivationArg = makeDerivationArgument (
@@ -852,13 +835,12 @@ let
      checkedEnv =
        let
          overlappingNames = attrNames (builtins.intersectAttrs env' derivationArg);
          prettyPrint = lib.generators.toPretty { };
          makeError =
          errors = lib.concatMapStringsSep "\n" (
            name:
            "  - ${name}: in `env`: ${prettyPrint env'.${name}}; in derivation arguments: ${
                prettyPrint derivationArg.${name}
              }";
          errors = lib.concatMapStringsSep "\n" makeError overlappingNames;
            "  - ${name}: in `env`: ${lib.generators.toPretty { } env'.${name}}; in derivation arguments: ${
                lib.generators.toPretty { } derivationArg.${name}
              }"
          ) overlappingNames;
        in
        assert assertMsg (isAttrs env && !isDerivation env)
          "`env` must be an attribute set of environment variables. Set `env.env` or pick a more specific name.";
@@ -871,20 +853,18 @@ let
          v
        ) env';

      attrsToRemove = [
        # Fixed-output derivations may not reference other paths, which means that
        # for a fixed-output derivation, the corresponding inputDerivation should
        # *not* be fixed-output. To achieve this we simply delete the attributes that
        # would make it fixed-output.
      fixedOutputRelatedAttrs = [
        "outputHashAlgo"
        "outputHash"
        "outputHashMode"
      ];

        # inputDerivation produces the inputs; not the outputs, so any
        # restrictions on what used to be the outputs don't serve a purpose
        # anymore.
      outputCheckAttrs = [
        "allowedReferences"
        "allowedRequisites"
        "disallowedReferences"
@@ -902,10 +882,10 @@ let
        # needed to enter a nix-shell with
        #   nix-build shell.nix -A inputDerivation
        inputDerivation = derivation (
          removeAttrs derivationArg (fixedOutputRelatedAttrs ++ outputCheckAttrs)
          removeAttrs derivationArg attrsToRemove
          // {
            # Add a name in case the original drv didn't have one
            name = "inputDerivation" + lib.optionalString (derivationArg ? name) "-${derivationArg.name}";
            name = "inputDerivation" + optionalString (derivationArg ? name) "-${derivationArg.name}";
            # This always only has one output
            outputs = [ "out" ];
            # This doesn’t require any system features even if the original