diff options
author | Alyssa Ross <hi@alyssa.is> | 2023-06-16 06:56:35 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2023-06-16 06:56:35 +0000 |
commit | 99fcaeccb89621dd492203ce1f2d551c06f228ed (patch) | |
tree | 41cb730ae07383004789779b0f6e11cb3f4642a3 /nixpkgs/pkgs/stdenv/generic/make-derivation.nix | |
parent | 59c5f5ac8682acc13bb22bc29c7cf02f7d75f01f (diff) | |
parent | 75a5ebf473cd60148ba9aec0d219f72e5cf52519 (diff) | |
download | nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.gz nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.bz2 nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.lz nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.xz nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.tar.zst nixlib-99fcaeccb89621dd492203ce1f2d551c06f228ed.zip |
Merge branch 'nixos-unstable' of https://github.com/NixOS/nixpkgs
Conflicts: nixpkgs/nixos/modules/config/console.nix nixpkgs/nixos/modules/services/mail/mailman.nix nixpkgs/nixos/modules/services/mail/public-inbox.nix nixpkgs/nixos/modules/services/mail/rss2email.nix nixpkgs/nixos/modules/services/networking/ssh/sshd.nix nixpkgs/pkgs/applications/networking/instant-messengers/dino/default.nix nixpkgs/pkgs/applications/networking/irc/weechat/default.nix nixpkgs/pkgs/applications/window-managers/sway/default.nix nixpkgs/pkgs/build-support/go/module.nix nixpkgs/pkgs/build-support/rust/build-rust-package/default.nix nixpkgs/pkgs/development/interpreters/python/default.nix nixpkgs/pkgs/development/node-packages/overrides.nix nixpkgs/pkgs/development/tools/b4/default.nix nixpkgs/pkgs/servers/dict/dictd-db.nix nixpkgs/pkgs/servers/mail/public-inbox/default.nix nixpkgs/pkgs/tools/security/pinentry/default.nix nixpkgs/pkgs/tools/text/unoconv/default.nix nixpkgs/pkgs/top-level/all-packages.nix
Diffstat (limited to 'nixpkgs/pkgs/stdenv/generic/make-derivation.nix')
-rw-r--r-- | nixpkgs/pkgs/stdenv/generic/make-derivation.nix | 282 |
1 files changed, 171 insertions, 111 deletions
diff --git a/nixpkgs/pkgs/stdenv/generic/make-derivation.nix b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix index 78cbad190a6e..40ad357739b7 100644 --- a/nixpkgs/pkgs/stdenv/generic/make-derivation.nix +++ b/nixpkgs/pkgs/stdenv/generic/make-derivation.nix @@ -18,33 +18,34 @@ let # separate lines, because Nix would only show the last line of the comment. # An infinite recursion here can be caused by having the attribute names of expression `e` in `.overrideAttrs(finalAttrs: previousAttrs: e)` depend on `finalAttrs`. Only the attribute values of `e` can depend on `finalAttrs`. - args = rattrs (args // { inherit finalPackage; }); + args = rattrs (args // { inherit finalPackage overrideAttrs; }); # ^^^^ - finalPackage = - mkDerivationSimple - (f0: - let - f = self: super: - # Convert f0 to an overlay. Legacy is: - # overrideAttrs (super: {}) - # We want to introduce self. We follow the convention of overlays: - # overrideAttrs (self: super: {}) - # Which means the first parameter can be either self or super. - # This is surprising, but far better than the confusion that would - # arise from flipping an overlay's parameters in some cases. - let x = f0 super; - in - if builtins.isFunction x - then - # Can't reuse `x`, because `self` comes first. - # Looks inefficient, but `f0 super` was a cheap thunk. - f0 self super - else x; + overrideAttrs = f0: + let + f = self: super: + # Convert f0 to an overlay. Legacy is: + # overrideAttrs (super: {}) + # We want to introduce self. We follow the convention of overlays: + # overrideAttrs (self: super: {}) + # Which means the first parameter can be either self or super. + # This is surprising, but far better than the confusion that would + # arise from flipping an overlay's parameters in some cases. + let x = f0 super; in - makeDerivationExtensible - (self: let super = rattrs self; in super // f self super)) - args; + if builtins.isFunction x + then + # Can't reuse `x`, because `self` comes first. + # Looks inefficient, but `f0 super` was a cheap thunk. + f0 self super + else x; + in + makeDerivationExtensible + (self: let super = rattrs self; in super // f self super); + + finalPackage = + mkDerivationSimple overrideAttrs args; + in finalPackage; # makeDerivationExtensibleConst == makeDerivationExtensible (_: attrs), @@ -85,24 +86,26 @@ let # TODO(@Ericson2314): Stop using legacy dep attribute names -# host offset -> target offset - depsBuildBuild ? [] # -1 -> -1 -, depsBuildBuildPropagated ? [] # -1 -> -1 -, nativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name -, propagatedNativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name -, depsBuildTarget ? [] # -1 -> 1 -, depsBuildTargetPropagated ? [] # -1 -> 1 +# host offset -> target offset + depsBuildBuild ? [] # -1 -> -1 +, depsBuildBuildPropagated ? [] # -1 -> -1 +, nativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name +, propagatedNativeBuildInputs ? [] # -1 -> 0 N.B. Legacy name +, depsBuildTarget ? [] # -1 -> 1 +, depsBuildTargetPropagated ? [] # -1 -> 1 -, depsHostHost ? [] # 0 -> 0 -, depsHostHostPropagated ? [] # 0 -> 0 -, buildInputs ? [] # 0 -> 1 N.B. Legacy name -, propagatedBuildInputs ? [] # 0 -> 1 N.B. Legacy name +, depsHostHost ? [] # 0 -> 0 +, depsHostHostPropagated ? [] # 0 -> 0 +, buildInputs ? [] # 0 -> 1 N.B. Legacy name +, propagatedBuildInputs ? [] # 0 -> 1 N.B. Legacy name -, depsTargetTarget ? [] # 1 -> 1 -, depsTargetTargetPropagated ? [] # 1 -> 1 +, depsTargetTarget ? [] # 1 -> 1 +, depsTargetTargetPropagated ? [] # 1 -> 1 -, checkInputs ? [] -, installCheckInputs ? [] +, checkInputs ? [] +, installCheckInputs ? [] +, nativeCheckInputs ? [] +, nativeInstallCheckInputs ? [] # Configure Phase , configureFlags ? [] @@ -154,6 +157,12 @@ let (! attrs ? outputHash) # Fixed-output drvs can't be content addressed too && config.contentAddressedByDefault +# Experimental. For simple packages mostly just works, +# but for anything complex, be prepared to debug if enabling. +, __structuredAttrs ? config.structuredAttrsByDefault or false + +, env ? { } + , ... } @ attrs: let @@ -162,35 +171,50 @@ let doCheck' = doCheck && stdenv.buildPlatform.canExecute stdenv.hostPlatform; doInstallCheck' = doInstallCheck && stdenv.buildPlatform.canExecute stdenv.hostPlatform; - separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux && !(stdenv.hostPlatform.useLLVM or false); + separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux; outputs' = outputs ++ lib.optional separateDebugInfo' "debug"; + # Turn a derivation into its outPath without a string context attached. + # See the comment at the usage site. + unsafeDerivationToUntrackedOutpath = drv: + if lib.isDerivation drv + then builtins.unsafeDiscardStringContext drv.outPath + else drv; + noNonNativeDeps = builtins.length (depsBuildTarget ++ depsBuildTargetPropagated ++ depsHostHost ++ depsHostHostPropagated ++ buildInputs ++ propagatedBuildInputs ++ depsTargetTarget ++ depsTargetTargetPropagated) == 0; dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || !stdenv.hasCC; - supportedHardeningFlags = [ "fortify" "stackprotector" "pie" "pic" "strictoverflow" "format" "relro" "bindnow" ]; + + hardeningDisable' = if lib.any (x: x == "fortify") hardeningDisable + # disabling fortify implies fortify3 should also be disabled + then lib.unique (hardeningDisable ++ [ "fortify3" ]) + else hardeningDisable; + supportedHardeningFlags = [ "fortify" "fortify3" "stackprotector" "pie" "pic" "strictoverflow" "format" "relro" "bindnow" ]; # Musl-based platforms will keep "pie", other platforms will not. # If you change this, make sure to update section `{#sec-hardening-in-nixpkgs}` # in the nixpkgs manual to inform users about the defaults. - defaultHardeningFlags = if stdenv.hostPlatform.isMusl && - # Except when: - # - static aarch64, where compilation works, but produces segfaulting dynamically linked binaries. - # - static armv7l, where compilation fails. - !(stdenv.hostPlatform.isAarch && stdenv.hostPlatform.isStatic) - then supportedHardeningFlags - else lib.remove "pie" supportedHardeningFlags; + defaultHardeningFlags = let + # not ready for this by default + supportedHardeningFlags' = lib.remove "fortify3" supportedHardeningFlags; + in if stdenv.hostPlatform.isMusl && + # Except when: + # - static aarch64, where compilation works, but produces segfaulting dynamically linked binaries. + # - static armv7l, where compilation fails. + !(stdenv.hostPlatform.isAarch && stdenv.hostPlatform.isStatic) + then supportedHardeningFlags' + else lib.remove "pie" supportedHardeningFlags'; enabledHardeningOptions = - if builtins.elem "all" hardeningDisable + if builtins.elem "all" hardeningDisable' then [] - else lib.subtractLists hardeningDisable (defaultHardeningFlags ++ hardeningEnable); + else lib.subtractLists hardeningDisable' (defaultHardeningFlags ++ hardeningEnable); # hardeningDisable additionally supports "all". erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable); checkDependencyList = checkDependencyList' []; checkDependencyList' = positions: name: deps: lib.flip lib.imap1 deps (index: dep: - if lib.isDerivation dep || isNull dep || builtins.typeOf dep == "string" || builtins.typeOf dep == "path" then dep + if lib.isDerivation dep || dep == null || builtins.typeOf dep == "string" || builtins.typeOf dep == "path" then dep else if lib.isList dep then checkDependencyList' ([index] ++ positions) name dep else throw "Dependency is not of a valid type: ${lib.concatMapStrings (ix: "element ${toString ix} of ") ([index] ++ positions)}${name} for ${attrs.name or attrs.pname}"); in if builtins.length erroneousHardeningFlags != 0 @@ -200,6 +224,14 @@ then abort ("mkDerivation was called with unsupported hardening flags: " + lib.g else let doCheck = doCheck'; doInstallCheck = doInstallCheck'; + buildInputs' = buildInputs + ++ lib.optionals doCheck checkInputs + ++ lib.optionals doInstallCheck installCheckInputs; + nativeBuildInputs' = nativeBuildInputs + ++ lib.optional separateDebugInfo' ../../build-support/setup-hooks/separate-debug-info.sh + ++ lib.optional stdenv.hostPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh + ++ lib.optionals doCheck nativeCheckInputs + ++ lib.optionals doInstallCheck nativeInstallCheckInputs; outputs = outputs'; @@ -209,16 +241,12 @@ else let dependencies = map (map lib.chooseDevOutputs) [ [ (map (drv: drv.__spliced.buildBuild or drv) (checkDependencyList "depsBuildBuild" depsBuildBuild)) - (map (drv: drv.nativeDrv or drv) (checkDependencyList "nativeBuildInputs" nativeBuildInputs - ++ lib.optional separateDebugInfo' ../../build-support/setup-hooks/separate-debug-info.sh - ++ lib.optional stdenv.hostPlatform.isWindows ../../build-support/setup-hooks/win-dll-link.sh - ++ lib.optionals doCheck checkInputs - ++ lib.optionals doInstallCheck' installCheckInputs)) + (map (drv: drv.__spliced.buildHost or drv) (checkDependencyList "nativeBuildInputs" nativeBuildInputs')) (map (drv: drv.__spliced.buildTarget or drv) (checkDependencyList "depsBuildTarget" depsBuildTarget)) ] [ (map (drv: drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHost" depsHostHost)) - (map (drv: drv.crossDrv or drv) (checkDependencyList "buildInputs" buildInputs)) + (map (drv: drv.__spliced.hostTarget or drv) (checkDependencyList "buildInputs" buildInputs')) ] [ (map (drv: drv.__spliced.targetTarget or drv) (checkDependencyList "depsTargetTarget" depsTargetTarget)) @@ -227,12 +255,12 @@ else let propagatedDependencies = map (map lib.chooseDevOutputs) [ [ (map (drv: drv.__spliced.buildBuild or drv) (checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated)) - (map (drv: drv.nativeDrv or drv) (checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs)) + (map (drv: drv.__spliced.buildHost or drv) (checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs)) (map (drv: drv.__spliced.buildTarget or drv) (checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated)) ] [ (map (drv: drv.__spliced.hostHost or drv) (checkDependencyList "depsHostHostPropagated" depsHostHostPropagated)) - (map (drv: drv.crossDrv or drv) (checkDependencyList "propagatedBuildInputs" propagatedBuildInputs)) + (map (drv: drv.__spliced.hostTarget or drv) (checkDependencyList "propagatedBuildInputs" propagatedBuildInputs)) ] [ (map (drv: drv.__spliced.targetTarget or drv) (checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated)) @@ -259,13 +287,18 @@ else let lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) (lib.concatLists propagatedDependencies)); + envIsExportable = lib.isAttrs env && !lib.isDerivation env; + derivationArg = (removeAttrs attrs - ["meta" "passthru" "pos" + (["meta" "passthru" "pos" "checkInputs" "installCheckInputs" + "nativeCheckInputs" "nativeInstallCheckInputs" + "__contentAddressed" "__darwinAllowLocalNetworking" "__impureHostDeps" "__propagatedImpureHostDeps" - "sandboxProfile" "propagatedSandboxProfile"]) + "sandboxProfile" "propagatedSandboxProfile"] + ++ lib.optional (__structuredAttrs || envIsExportable) "env")) // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) { name = let @@ -277,6 +310,7 @@ else let hostSuffix = lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform && !dontAddHostSuffix) "-${stdenv.hostPlatform.config}"; + # Disambiguate statically built packages. This was originally # introduce as a means to prevent nix-env to get confused between # nix and nixStatic. This should be also achieved by moving the @@ -287,9 +321,12 @@ else let lib.strings.sanitizeDerivationName ( if attrs ? name then attrs.name + hostSuffix - else "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}" + else + # we cannot coerce null to a string below + assert lib.assertMsg (attrs ? version && attrs.version != null) "The ‘version’ attribute cannot be null."; + "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}" ); - }) // { + }) // lib.optionalAttrs __structuredAttrs { env = checkedEnv; } // { builder = attrs.realBuilder or stdenv.shell; args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)]; inherit stdenv; @@ -304,8 +341,7 @@ else let userHook = config.stdenv.userHook or null; __ignoreNulls = true; - - inherit strictDeps; + inherit __structuredAttrs strictDeps; depsBuildBuild = lib.elemAt (lib.elemAt dependencies 0) 0; nativeBuildInputs = lib.elemAt (lib.elemAt dependencies 0) 1; @@ -377,10 +413,8 @@ else let # See https://mesonbuild.com/Reference-tables.html#cpu-families cpuFamily = platform: with platform; /**/ if isAarch32 then "arm" - else if isAarch64 then "aarch64" else if isx86_32 then "x86" - else if isx86_64 then "x86_64" - else platform.parsed.cpu.family + builtins.toString platform.parsed.cpu.bits; + else platform.uname.processor; crossFile = builtins.toFile "cross-file.conf" '' [properties] @@ -410,7 +444,9 @@ else let outputHashAlgo = attrs.outputHashAlgo or "sha256"; outputHashMode = attrs.outputHashMode or "recursive"; } // lib.optionalAttrs (enableParallelBuilding) { + inherit enableParallelBuilding; enableParallelChecking = attrs.enableParallelChecking or true; + enableParallelInstalling = attrs.enableParallelInstalling or true; } // lib.optionalAttrs (hardeningDisable != [] || hardeningEnable != [] || stdenv.hostPlatform.isMusl) { NIX_HARDENING_ENABLE = enabledHardeningOptions; } // lib.optionalAttrs (stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform ? gcc.arch) { @@ -430,48 +466,57 @@ else let "/bin/sh" ]; __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps; + } // + # If we use derivations directly here, they end up as build-time dependencies. + # This is especially problematic in the case of disallowed*, since the disallowed + # derivations will be built by nix as build-time dependencies, while those + # derivations might take a very long time to build, or might not even build + # successfully on the platform used. + # We can improve on this situation by instead passing only the outPath, + # without an attached string context, to nix. The out path will be a placeholder + # which will be replaced by the actual out path if the derivation in question + # is part of the final closure (and thus needs to be built). If it is not + # part of the final closure, then the placeholder will be passed along, + # but in that case we know for a fact that the derivation is not part of the closure. + # This means that passing the out path to nix does the right thing in either + # case, both for disallowed and allowed references/requisites, and we won't + # build the derivation if it wouldn't be part of the closure, saving time and resources. + # While the problem is less severe for allowed*, since we want the derivation + # to be built eventually, we would still like to get the error early and without + # having to wait while nix builds a derivation that might not be used. + # See also https://github.com/NixOS/nix/issues/4629 + lib.optionalAttrs (attrs ? disallowedReferences) { + disallowedReferences = + map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences; + } // + lib.optionalAttrs (attrs ? disallowedRequisites) { + disallowedRequisites = + map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites; + } // + lib.optionalAttrs (attrs ? allowedReferences) { + allowedReferences = + lib.mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences; + } // + lib.optionalAttrs (attrs ? allowedRequisites) { + allowedRequisites = + lib.mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites; }; - validity = checkMeta { inherit meta attrs; }; - - # The meta attribute is passed in the resulting attribute set, - # but it's not part of the actual derivation, i.e., it's not - # passed to the builder and is not a dependency. But since we - # include it in the result, it *is* available to nix-env for queries. - meta = { - # `name` above includes cross-compilation cruft, - # is under assert, and is sanitized. - # Let's have a clean always accessible version here. - name = attrs.name or "${attrs.pname}-${attrs.version}"; - - # If the packager hasn't specified `outputsToInstall`, choose a default, - # which is the name of `p.bin or p.out or p` along with `p.man` when - # present. - # - # If the packager has specified it, it will be overridden below in - # `// meta`. - # - # Note: This default probably shouldn't be globally configurable. - # Services and users should specify outputs explicitly, - # unless they are comfortable with this default. - outputsToInstall = - let - hasOutput = out: builtins.elem out outputs; - in [( lib.findFirst hasOutput null (["bin" "out"] ++ outputs) )] - ++ lib.optional (hasOutput "man") "man"; - } - // attrs.meta or {} - # Fill `meta.position` to identify the source location of the package. - // lib.optionalAttrs (pos != null) { - position = pos.file + ":" + toString pos.line; - } // { - # Expose the result of the checks for everyone to see. - inherit (validity) unfree broken unsupported insecure; - available = validity.valid != "no" - && (if config.checkMetaRecursively or false - then lib.all (d: d.meta.available or true) references - else true); - }; + meta = checkMeta.commonMeta { inherit validity attrs pos references; }; + validity = checkMeta.assertValidity { inherit meta attrs; }; + + checkedEnv = + let + overlappingNames = lib.attrNames (builtins.intersectAttrs env derivationArg); + in + assert lib.assertMsg envIsExportable + "When using structured attributes, `env` must be an attribute set of environment variables."; + assert lib.assertMsg (overlappingNames == [ ]) + "The ‘env’ attribute set cannot contain any attributes passed to derivation. The following attributes are overlapping: ${lib.concatStringsSep ", " overlappingNames}"; + lib.mapAttrs + (n: v: assert lib.assertMsg (lib.isString v || lib.isBool v || lib.isInt v || lib.isDerivation v) + "The ‘env’ attribute set can only contain derivation, string, boolean or integer attributes. The ‘${n}’ attribute is of type ${builtins.typeOf v}."; v) + env; in @@ -500,16 +545,31 @@ lib.extendDerivation # binaries). By writing this to $out, Nix can find and register # them as runtime dependencies (since Nix greps for store paths # through $out to find them) - args = [ "-c" "export > $out" ]; + args = [ "-c" '' + export > $out + for var in $passAsFile; do + pathVar="''${var}Path" + printf "%s" "$(< "''${!pathVar}")" >> $out + done + '' ]; + + # inputDerivation produces the inputs; not the outputs, so any + # restrictions on what used to be the outputs don't serve a purpose + # anymore. + allowedReferences = null; + allowedRequisites = null; + disallowedReferences = [ ]; + disallowedRequisites = [ ]; }); - inherit meta passthru overrideAttrs; + inherit passthru overrideAttrs; + inherit meta; } // # Pass through extra attributes that are not inputs, but # should be made available to Nix expressions using the # derivation (e.g., in assertions). passthru) - (derivation derivationArg); + (derivation (derivationArg // lib.optionalAttrs envIsExportable checkedEnv)); in fnOrAttrs: |