From f110a182a66005782c0e58091bcda7243bf2a0ae Mon Sep 17 00:00:00 2001 From: John Ericson Date: Mon, 16 Aug 2021 21:16:29 -0400 Subject: [PATCH 1/2] stdenv: Fix overriding + `overrideAttrs` The old stdenv adapters were subtly wrong in two ways: - `overrideAttrs` leaked the original, unoverridden `mkDerivation`. - `stdenv.override` would throw away any manually-set `mkDerivation` from a stdenv reverting to the original. Now, `mkDerivation` is controlled (nearly directly) via an argument, and always correctly closes over the final ("self") stdenv. This means the adapters can work entirely via `.override` without any manual `stdenv // ...`, and both those issues are fixed. Note hashes are changed, because stdenvs no previously overridden like `stdenvNoCC` and `crossLibcStdenv` now are. I had to add some `dontDisableStatic = true` accordingly. The flip side however is that since the overrides compose, we no longer need to override anything but the default `stdenv` from which all the others are created. --- pkgs/os-specific/linux/musl/default.nix | 1 + pkgs/stdenv/adapters.nix | 125 ++++++++++++++---------- pkgs/stdenv/generic/default.nix | 8 +- pkgs/stdenv/generic/make-derivation.nix | 13 ++- pkgs/top-level/stage.nix | 7 +- pkgs/top-level/static.nix | 24 ----- 6 files changed, 94 insertions(+), 84 deletions(-) diff --git a/pkgs/os-specific/linux/musl/default.nix b/pkgs/os-specific/linux/musl/default.nix index ae175a363241..f19c7ea7a44b 100644 --- a/pkgs/os-specific/linux/musl/default.nix +++ b/pkgs/os-specific/linux/musl/default.nix @@ -82,6 +82,7 @@ stdenv.mkDerivation rec { outputs = [ "out" "dev" ]; dontDisableStatic = true; + dontAddStaticConfigureFlags = true; separateDebugInfo = true; NIX_DONT_SET_RPATH = true; diff --git a/pkgs/stdenv/adapters.nix b/pkgs/stdenv/adapters.nix index a8e984d61743..719f67998266 100644 --- a/pkgs/stdenv/adapters.nix +++ b/pkgs/stdenv/adapters.nix @@ -2,7 +2,31 @@ a new stdenv with different behaviour, e.g. using a different C compiler. */ -pkgs: +{ lib, pkgs, config }: + +let + # N.B. Keep in sync with default arg for stdenv/generic. + defaultMkDerivationFromStdenv = import ./generic/make-derivation.nix { inherit lib config; }; + + # Low level function to help with overriding `mkDerivationFromStdenv`. One + # gives it the old stdenv arguments and a "continuation" function, and + # underneath the final stdenv argument it yields to the continuation to do + # whatever it wants with old `mkDerivation` (old `mkDerivationFromStdenv` + # applied to the *new, final* stdenv) provided for convenience. + withOldMkDerivation = stdenvSuperArgs: k: stdenvSelf: let + mkDerivationFromStdenv-super = stdenvSuperArgs.mkDerivationFromStdenv or defaultMkDerivationFromStdenv; + mkDerivationSuper = mkDerivationFromStdenv-super stdenvSelf; + in + k stdenvSelf mkDerivationSuper; + + # Wrap the original `mkDerivation` providing extra args to it. + extendMkDerivationArgs = old: f: withOldMkDerivation old (_: mkDerivationSuper: args: + mkDerivationSuper (args // f args)); + + # Wrap the original `mkDerivation` transforming the result. + overrideMkDerivationResult = old: f: withOldMkDerivation old (_: mkDerivationSuper: args: + f (mkDerivationSuper args)); +in rec { @@ -31,33 +55,32 @@ rec { # Return a modified stdenv that tries to build statically linked # binaries. - makeStaticBinaries = stdenv: - let stdenv' = if stdenv.hostPlatform.libc != "glibc" then stdenv else - stdenv.override (prev: { - extraBuildInputs = (prev.extraBuildInputs or []) ++ [ - stdenv.glibc.static - ]; - }); - in stdenv' // - { mkDerivation = args: - if stdenv'.hostPlatform.isDarwin + makeStaticBinaries = stdenv0: + stdenv0.override (old: { + mkDerivationFromStdenv = withOldMkDerivation old (stdenv: mkDerivationSuper: args: + if stdenv.hostPlatform.isDarwin then throw "Cannot build fully static binaries on Darwin/macOS" - else stdenv'.mkDerivation (args // { + else mkDerivationSuper (args // { NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -static"; - } // pkgs.lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) { + } // lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) { configureFlags = (args.configureFlags or []) ++ [ "--disable-shared" # brrr... ]; - }); - }; + })); + } // lib.optionalAttrs (stdenv0.hostPlatform.libc == "libc") { + extraBuildInputs = (old.extraBuildInputs or []) ++ [ + stdenv0.glibc.static + ]; + }); # Return a modified stdenv that builds static libraries instead of # shared libraries. - makeStaticLibraries = stdenv: stdenv // - { mkDerivation = args: stdenv.mkDerivation (args // { + makeStaticLibraries = stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = extendMkDerivationArgs old (args: { dontDisableStatic = true; - } // pkgs.lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) { + } // lib.optionalAttrs (!(args.dontAddStaticConfigureFlags or false)) { configureFlags = (args.configureFlags or []) ++ [ "--enable-static" "--disable-shared" @@ -65,18 +88,19 @@ rec { cmakeFlags = (args.cmakeFlags or []) ++ [ "-DBUILD_SHARED_LIBS:BOOL=OFF" ]; mesonFlags = (args.mesonFlags or []) ++ [ "-Ddefault_library=static" ]; }); - }; + }); /* Modify a stdenv so that all buildInputs are implicitly propagated to consuming derivations */ - propagateBuildInputs = stdenv: stdenv // - { mkDerivation = args: stdenv.mkDerivation (args // { + propagateBuildInputs = stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = extendMkDerivationArgs old (args: { propagatedBuildInputs = (args.propagatedBuildInputs or []) ++ (args.buildInputs or []); buildInputs = []; }); - }; + }); /* Modify a stdenv so that the specified attributes are added to @@ -88,8 +112,9 @@ rec { { NIX_CFLAGS_COMPILE = "-O0"; } stdenv; */ - addAttrsToDerivation = extraAttrs: stdenv: stdenv // - { mkDerivation = args: stdenv.mkDerivation (args // extraAttrs); }; + addAttrsToDerivation = extraAttrs: stdenv: stdenv.override (old: { + mkDerivationFromStdenv = extendMkDerivationArgs old (_: extraAttrs); + }); /* Return a modified stdenv that builds packages with GCC's coverage @@ -110,21 +135,20 @@ rec { # remove all maintainers. defaultStdenv = replaceMaintainersField allStdenvs.stdenv pkgs []; */ - replaceMaintainersField = stdenv: pkgs: maintainers: stdenv // - { mkDerivation = args: - pkgs.lib.recursiveUpdate - (stdenv.mkDerivation args) - { meta.maintainers = maintainers; }; - }; + replaceMaintainersField = stdenv: pkgs: maintainers: + stdenv.override (old: { + mkDerivationFromStdenv = overrideMkDerivationResult (pkg: + lib.recursiveUpdate pkg { meta.maintainers = maintainers; }); + }); /* Use the trace output to report all processed derivations with their license name. */ - traceDrvLicenses = stdenv: stdenv // - { mkDerivation = args: + traceDrvLicenses = stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = overrideMkDerivationResult (pkg: let - pkg = stdenv.mkDerivation args; printDrvPath = val: let drvPath = builtins.unsafeDiscardStringContext pkg.drvPath; license = pkg.meta.license or null; @@ -133,8 +157,8 @@ rec { in pkg // { outPath = printDrvPath pkg.outPath; drvPath = printDrvPath pkg.drvPath; - }; - }; + }); + }); /* Abort if the license predicate is not verified for a derivation @@ -152,10 +176,10 @@ rec { use it by patching the all-packages.nix file or by using the override feature of ~/.config/nixpkgs/config.nix . */ - validateLicenses = licensePred: stdenv: stdenv // - { mkDerivation = args: + validateLicenses = licensePred: stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = overrideMkDerivationResult (pkg: let - pkg = stdenv.mkDerivation args; drv = builtins.unsafeDiscardStringContext pkg.drvPath; license = pkg.meta.license or @@ -175,40 +199,43 @@ rec { in pkg // { outPath = validate pkg.outPath; drvPath = validate pkg.drvPath; - }; - }; + }); + }); /* Modify a stdenv so that it produces debug builds; that is, binaries have debug info, and compiler optimisations are disabled. */ - keepDebugInfo = stdenv: stdenv // - { mkDerivation = args: stdenv.mkDerivation (args // { + keepDebugInfo = stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = extendMkDerivationArgs old (args: { dontStrip = true; NIX_CFLAGS_COMPILE = toString (args.NIX_CFLAGS_COMPILE or "") + " -ggdb -Og"; }); - }; + }); /* Modify a stdenv so that it uses the Gold linker. */ - useGoldLinker = stdenv: stdenv // - { mkDerivation = args: stdenv.mkDerivation (args // { + useGoldLinker = stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = extendMkDerivationArgs old (args: { NIX_CFLAGS_LINK = toString (args.NIX_CFLAGS_LINK or "") + " -fuse-ld=gold"; }); - }; + }); /* Modify a stdenv so that it builds binaries optimized specifically for the machine they are built on. WARNING: this breaks purity! */ - impureUseNativeOptimizations = stdenv: stdenv // - { mkDerivation = args: stdenv.mkDerivation (args // { + impureUseNativeOptimizations = stdenv: + stdenv.override (old: { + mkDerivationFromStdenv = extendMkDerivationArgs old (args: { NIX_CFLAGS_COMPILE = toString (args.NIX_CFLAGS_COMPILE or "") + " -march=native"; NIX_ENFORCE_NO_NATIVE = false; preferLocalBuild = true; allowSubstitutes = false; }); - }; + }); } diff --git a/pkgs/stdenv/generic/default.nix b/pkgs/stdenv/generic/default.nix index 88ca1b2c7903..d7fb1b0ba063 100644 --- a/pkgs/stdenv/generic/default.nix +++ b/pkgs/stdenv/generic/default.nix @@ -48,6 +48,10 @@ let lib = import ../../../lib; in lib.makeOverridable ( , # The platform which build tools (especially compilers) build for in this stage, targetPlatform + +, # The implementation of `mkDerivation`, parameterized with the final stdenv so we can tie the knot. + # This is convient to have as a parameter so the stdenv "adapters" work better + mkDerivationFromStdenv ? import ./make-derivation.nix { inherit lib config; } }: let @@ -155,9 +159,7 @@ let # to correct type of machine. inherit (hostPlatform) system; - inherit (import ./make-derivation.nix { - inherit lib config stdenv; - }) mkDerivation; + mkDerivation = mkDerivationFromStdenv stdenv; inherit fetchurlBoot; diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index d6704d59111a..c151516130a1 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -1,4 +1,6 @@ -{ lib, config, stdenv }: +{ lib, config }: + +stdenv: let checkMeta = import ./check-meta.nix { @@ -7,7 +9,7 @@ let # to build it. This is a bit confusing for cross compilation. inherit (stdenv) hostPlatform; }; -in rec { +in # `mkDerivation` wraps the builtin `derivation` function to # produce derivations that use this stdenv and its shell. # @@ -18,7 +20,6 @@ in rec { # # * https://nixos.org/nix/manual/#ssec-derivation # Explanation about derivations in general - mkDerivation = { # These types of dependencies are all exhaustively documented in @@ -373,7 +374,7 @@ in rec { lib.extendDerivation validity.handled ({ - overrideAttrs = f: mkDerivation (attrs // (f attrs)); + overrideAttrs = f: stdenv.mkDerivation (attrs // (f attrs)); # A derivation that always builds successfully and whose runtime # dependencies are the original derivations build time dependencies @@ -406,6 +407,4 @@ in rec { # should be made available to Nix expressions using the # derivation (e.g., in assertions). passthru) - (derivation derivationArg); - -} + (derivation derivationArg) diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index dc43bbec9d33..b01ef584d206 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -65,7 +65,12 @@ let stdenvAdapters = self: super: - let res = import ../stdenv/adapters.nix self; in res // { + let + res = import ../stdenv/adapters.nix { + inherit lib config; + pkgs = self; + }; + in res // { stdenvAdapters = res; }; diff --git a/pkgs/top-level/static.nix b/pkgs/top-level/static.nix index 0c9af250e876..73d8d9e53032 100644 --- a/pkgs/top-level/static.nix +++ b/pkgs/top-level/static.nix @@ -35,9 +35,6 @@ self: super: let }; staticAdapters = - # makeStaticDarwin must go first so that the extraBuildInputs - # override does not recreate mkDerivation, removing subsequent - # adapters. optional super.stdenv.hostPlatform.isDarwin makeStaticDarwin ++ [ makeStaticLibraries propagateBuildInputs ] @@ -80,30 +77,9 @@ self: super: let }); }; - llvmStaticAdapter = llvmPackages: - llvmPackages // { - stdenv = foldl (flip id) llvmPackages.stdenv staticAdapters; - libcxxStdenv = foldl (flip id) llvmPackages.libcxxStdenv staticAdapters; - }; - in { stdenv = foldl (flip id) super.stdenv staticAdapters; - gcc49Stdenv = foldl (flip id) super.gcc49Stdenv staticAdapters; - gcc6Stdenv = foldl (flip id) super.gcc6Stdenv staticAdapters; - gcc7Stdenv = foldl (flip id) super.gcc7Stdenv staticAdapters; - gcc8Stdenv = foldl (flip id) super.gcc8Stdenv staticAdapters; - gcc9Stdenv = foldl (flip id) super.gcc9Stdenv staticAdapters; - - llvmPackages_5 = llvmStaticAdapter super.llvmPackages_5; - llvmPackages_6 = llvmStaticAdapter super.llvmPackages_6; - llvmPackages_7 = llvmStaticAdapter super.llvmPackages_7; - llvmPackages_8 = llvmStaticAdapter super.llvmPackages_8; - llvmPackages_9 = llvmStaticAdapter super.llvmPackages_9; - llvmPackages_10 = llvmStaticAdapter super.llvmPackages_10; - llvmPackages_11 = llvmStaticAdapter super.llvmPackages_11; - llvmPackages_12 = llvmStaticAdapter super.llvmPackages_12; - boost = super.boost.override { # Don’t use new stdenv for boost because it doesn’t like the # --disable-shared flag From b4cc2a2479a7ab0f6440b2e1319221920ef72699 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Wed, 18 Aug 2021 17:19:30 +0000 Subject: [PATCH 2/2] pkgs/stdenv/make-derivation: Reindent We previously make it just be the function, not a single-item attrset, without deindenting to make a readable diff. No we deindent. --- pkgs/stdenv/generic/make-derivation.nix | 767 ++++++++++++------------ 1 file changed, 384 insertions(+), 383 deletions(-) diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix index c151516130a1..56cfa0c503f8 100644 --- a/pkgs/stdenv/generic/make-derivation.nix +++ b/pkgs/stdenv/generic/make-derivation.nix @@ -10,401 +10,402 @@ let inherit (stdenv) hostPlatform; }; in - # `mkDerivation` wraps the builtin `derivation` function to - # produce derivations that use this stdenv and its shell. + +# `mkDerivation` wraps the builtin `derivation` function to +# produce derivations that use this stdenv and its shell. +# +# See also: +# +# * https://nixos.org/nixpkgs/manual/#sec-using-stdenv +# Details on how to use this mkDerivation function +# +# * https://nixos.org/nix/manual/#ssec-derivation +# Explanation about derivations in general +{ + +# These types of dependencies are all exhaustively documented in +# the "Specifying Dependencies" section of the "Standard +# Environment" chapter of the Nixpkgs manual. + +# 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 + +, 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 + +, checkInputs ? [] +, installCheckInputs ? [] + +# Configure Phase +, configureFlags ? [] +, cmakeFlags ? [] +, mesonFlags ? [] +, # Target is not included by default because most programs don't care. + # Including it then would cause needless mass rebuilds. # - # See also: - # - # * https://nixos.org/nixpkgs/manual/#sec-using-stdenv - # Details on how to use this mkDerivation function - # - # * https://nixos.org/nix/manual/#ssec-derivation - # Explanation about derivations in general - { + # TODO(@Ericson2314): Make [ "build" "host" ] always the default. + configurePlatforms ? lib.optionals + (stdenv.hostPlatform != stdenv.buildPlatform) + [ "build" "host" ] - # These types of dependencies are all exhaustively documented in - # the "Specifying Dependencies" section of the "Standard - # Environment" chapter of the Nixpkgs manual. +# TODO(@Ericson2314): Make unconditional / resolve #33599 +# Check phase +, doCheck ? config.doCheckByDefault or false - # TODO(@Ericson2314): Stop using legacy dep attribute names +# TODO(@Ericson2314): Make unconditional / resolve #33599 +# InstallCheck phase +, doInstallCheck ? config.doCheckByDefault or false - # 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 +, # TODO(@Ericson2314): Make always true and remove + strictDeps ? stdenv.hostPlatform != stdenv.buildPlatform +, meta ? {} +, passthru ? {} +, pos ? # position used in error messages and for meta.position + (if attrs.meta.description or null != null + then builtins.unsafeGetAttrPos "description" attrs.meta + else if attrs.version or null != null + then builtins.unsafeGetAttrPos "version" attrs + else builtins.unsafeGetAttrPos "name" attrs) +, separateDebugInfo ? false +, outputs ? [ "out" ] +, __darwinAllowLocalNetworking ? false +, __impureHostDeps ? [] +, __propagatedImpureHostDeps ? [] +, sandboxProfile ? "" +, propagatedSandboxProfile ? "" - , depsHostHost ? [] # 0 -> 0 - , depsHostHostPropagated ? [] # 0 -> 0 - , buildInputs ? [] # 0 -> 1 N.B. Legacy name - , propagatedBuildInputs ? [] # 0 -> 1 N.B. Legacy name +, hardeningEnable ? [] +, hardeningDisable ? [] - , depsTargetTarget ? [] # 1 -> 1 - , depsTargetTargetPropagated ? [] # 1 -> 1 +, patches ? [] - , checkInputs ? [] - , installCheckInputs ? [] +, __contentAddressed ? + (! attrs ? outputHash) # Fixed-output drvs can't be content addressed too + && (config.contentAddressedByDefault or false) - # Configure Phase - , configureFlags ? [] - , cmakeFlags ? [] - , mesonFlags ? [] - , # Target is not included by default because most programs don't care. - # Including it then would cause needless mass rebuilds. +, ... } @ attrs: + +let + # TODO(@oxij, @Ericson2314): This is here to keep the old semantics, remove when + # no package has `doCheck = true`. + doCheck' = doCheck && stdenv.hostPlatform == stdenv.buildPlatform; + doInstallCheck' = doInstallCheck && stdenv.hostPlatform == stdenv.buildPlatform; + + separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux && !(stdenv.hostPlatform.useLLVM or false); + outputs' = outputs ++ lib.optional separateDebugInfo' "debug"; + + 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" ]; + # 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.isAarch64 || stdenv.hostPlatform.isAarch32) && stdenv.hostPlatform.isStatic) + then supportedHardeningFlags + else lib.remove "pie" supportedHardeningFlags; + enabledHardeningOptions = + if builtins.elem "all" hardeningDisable + then [] + else lib.subtractLists hardeningDisable (defaultHardeningFlags ++ hardeningEnable); + # hardeningDisable additionally supports "all". + erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable); +in if builtins.length erroneousHardeningFlags != 0 +then abort ("mkDerivation was called with unsupported hardening flags: " + lib.generators.toPretty {} { + inherit erroneousHardeningFlags hardeningDisable hardeningEnable supportedHardeningFlags; +}) +else let + doCheck = doCheck'; + doInstallCheck = doInstallCheck'; + + outputs = outputs'; + + references = nativeBuildInputs ++ buildInputs + ++ propagatedNativeBuildInputs ++ propagatedBuildInputs; + + dependencies = map (map lib.chooseDevOutputs) [ + [ + (map (drv: drv.__spliced.buildBuild or drv) depsBuildBuild) + (map (drv: drv.nativeDrv or drv) 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.buildTarget or drv) depsBuildTarget) + ] + [ + (map (drv: drv.__spliced.hostHost or drv) depsHostHost) + (map (drv: drv.crossDrv or drv) buildInputs) + ] + [ + (map (drv: drv.__spliced.targetTarget or drv) depsTargetTarget) + ] + ]; + propagatedDependencies = map (map lib.chooseDevOutputs) [ + [ + (map (drv: drv.__spliced.buildBuild or drv) depsBuildBuildPropagated) + (map (drv: drv.nativeDrv or drv) propagatedNativeBuildInputs) + (map (drv: drv.__spliced.buildTarget or drv) depsBuildTargetPropagated) + ] + [ + (map (drv: drv.__spliced.hostHost or drv) depsHostHostPropagated) + (map (drv: drv.crossDrv or drv) propagatedBuildInputs) + ] + [ + (map (drv: drv.__spliced.targetTarget or drv) depsTargetTargetPropagated) + ] + ]; + + computedSandboxProfile = + lib.concatMap (input: input.__propagatedSandboxProfile or []) + (stdenv.extraNativeBuildInputs + ++ stdenv.extraBuildInputs + ++ lib.concatLists dependencies); + + computedPropagatedSandboxProfile = + lib.concatMap (input: input.__propagatedSandboxProfile or []) + (lib.concatLists propagatedDependencies); + + computedImpureHostDeps = + lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) + (stdenv.extraNativeBuildInputs + ++ stdenv.extraBuildInputs + ++ lib.concatLists dependencies)); + + computedPropagatedImpureHostDeps = + lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) + (lib.concatLists propagatedDependencies)); + + derivationArg = + (removeAttrs attrs + ["meta" "passthru" "pos" + "checkInputs" "installCheckInputs" + "__darwinAllowLocalNetworking" + "__impureHostDeps" "__propagatedImpureHostDeps" + "sandboxProfile" "propagatedSandboxProfile"]) + // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) { + name = + let + # Indicate the host platform of the derivation if cross compiling. + # Fixed-output derivations like source tarballs shouldn't get a host + # suffix. But we have some weird ones with run-time deps that are + # just used for their side-affects. Those might as well since the + # hash can't be the same. See #32986. + 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 + # hostSuffix before the version, so we could contemplate removing + # it again. + staticMarker = lib.optionalString stdenv.hostPlatform.isStatic "-static"; + in + if attrs ? name + then attrs.name + hostSuffix + else "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"; + }) // { + builder = attrs.realBuilder or stdenv.shell; + args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)]; + inherit stdenv; + + # The `system` attribute of a derivation has special meaning to Nix. + # Derivations set it to choose what sort of machine could be used to + # execute the build, The build platform entirely determines this, + # indeed more finely than Nix knows or cares about. The `system` + # attribute of `buildPlatfom` matches Nix's degree of specificity. + # exactly. + inherit (stdenv.buildPlatform) system; + + userHook = config.stdenv.userHook or null; + __ignoreNulls = true; + + inherit strictDeps; + + depsBuildBuild = lib.elemAt (lib.elemAt dependencies 0) 0; + nativeBuildInputs = lib.elemAt (lib.elemAt dependencies 0) 1; + depsBuildTarget = lib.elemAt (lib.elemAt dependencies 0) 2; + depsHostHost = lib.elemAt (lib.elemAt dependencies 1) 0; + buildInputs = lib.elemAt (lib.elemAt dependencies 1) 1; + depsTargetTarget = lib.elemAt (lib.elemAt dependencies 2) 0; + + depsBuildBuildPropagated = lib.elemAt (lib.elemAt propagatedDependencies 0) 0; + propagatedNativeBuildInputs = lib.elemAt (lib.elemAt propagatedDependencies 0) 1; + depsBuildTargetPropagated = lib.elemAt (lib.elemAt propagatedDependencies 0) 2; + depsHostHostPropagated = lib.elemAt (lib.elemAt propagatedDependencies 1) 0; + propagatedBuildInputs = lib.elemAt (lib.elemAt propagatedDependencies 1) 1; + depsTargetTargetPropagated = lib.elemAt (lib.elemAt propagatedDependencies 2) 0; + + # This parameter is sometimes a string, sometimes null, and sometimes a list, yuck + configureFlags = let inherit (lib) optional elem; in + (/**/ if lib.isString configureFlags then [configureFlags] + else if configureFlags == null then [] + else configureFlags) + ++ optional (elem "build" configurePlatforms) "--build=${stdenv.buildPlatform.config}" + ++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}" + ++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}"; + + inherit patches; + + inherit doCheck doInstallCheck; + + inherit outputs; + } // lib.optionalAttrs (__contentAddressed) { + inherit __contentAddressed; + # Provide default values for outputHashMode and outputHashAlgo because + # most people won't care about these anyways + outputHashAlgo = attrs.outputHashAlgo or "sha256"; + outputHashMode = attrs.outputHashMode or "recursive"; + } // lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform) { + cmakeFlags = + (/**/ if lib.isString cmakeFlags then [cmakeFlags] + else if cmakeFlags == null then [] + else cmakeFlags) + ++ [ "-DCMAKE_SYSTEM_NAME=${lib.findFirst lib.isString "Generic" ( + lib.optional (!stdenv.hostPlatform.isRedox) stdenv.hostPlatform.uname.system)}"] + ++ lib.optional (stdenv.hostPlatform.uname.processor != null) "-DCMAKE_SYSTEM_PROCESSOR=${stdenv.hostPlatform.uname.processor}" + ++ lib.optional (stdenv.hostPlatform.uname.release != null) "-DCMAKE_SYSTEM_VERSION=${stdenv.hostPlatform.release}" + ++ lib.optional (stdenv.hostPlatform.isDarwin) "-DCMAKE_OSX_ARCHITECTURES=${stdenv.hostPlatform.darwinArch}" + ++ lib.optional (stdenv.buildPlatform.uname.system != null) "-DCMAKE_HOST_SYSTEM_NAME=${stdenv.buildPlatform.uname.system}" + ++ lib.optional (stdenv.buildPlatform.uname.processor != null) "-DCMAKE_HOST_SYSTEM_PROCESSOR=${stdenv.buildPlatform.uname.processor}" + ++ lib.optional (stdenv.buildPlatform.uname.release != null) "-DCMAKE_HOST_SYSTEM_VERSION=${stdenv.buildPlatform.uname.release}"; + + mesonFlags = if mesonFlags == null then null 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; + crossFile = builtins.toFile "cross-file.conf" '' + [properties] + needs_exe_wrapper = true + + [host_machine] + system = '${stdenv.targetPlatform.parsed.kernel.name}' + cpu_family = '${cpuFamily stdenv.targetPlatform}' + cpu = '${stdenv.targetPlatform.parsed.cpu.name}' + endian = ${if stdenv.targetPlatform.isLittleEndian then "'little'" else "'big'"} + ''; + in [ "--cross-file=${crossFile}" ] ++ mesonFlags; + } // lib.optionalAttrs (attrs.enableParallelBuilding or false) { + enableParallelChecking = attrs.enableParallelChecking or true; + } // lib.optionalAttrs (hardeningDisable != [] || hardeningEnable != [] || stdenv.hostPlatform.isMusl) { + NIX_HARDENING_ENABLE = enabledHardeningOptions; + } // lib.optionalAttrs (stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform ? gcc.arch) { + requiredSystemFeatures = attrs.requiredSystemFeatures or [] ++ [ "gccarch-${stdenv.hostPlatform.gcc.arch}" ]; + } // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) { + inherit __darwinAllowLocalNetworking; + # TODO: remove lib.unique once nix has a list canonicalization primitive + __sandboxProfile = + let profiles = [ stdenv.extraSandboxProfile ] ++ computedSandboxProfile ++ computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile sandboxProfile ]; + final = lib.concatStringsSep "\n" (lib.filter (x: x != "") (lib.unique profiles)); + in final; + __propagatedSandboxProfile = lib.unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]); + __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ stdenv.__extraImpureHostDeps ++ [ + "/dev/zero" + "/dev/random" + "/dev/urandom" + "/bin/sh" + ]; + __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps; + }; + + 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 (and is under assert), + # lets 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. # - # TODO(@Ericson2314): Make [ "build" "host" ] always the default. - configurePlatforms ? lib.optionals - (stdenv.hostPlatform != stdenv.buildPlatform) - [ "build" "host" ] + # 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 + && (if config.checkMetaRecursively or false + then lib.all (d: d.meta.available or true) references + else true); + }; - # TODO(@Ericson2314): Make unconditional / resolve #33599 - # Check phase - , doCheck ? config.doCheckByDefault or false +in - # TODO(@Ericson2314): Make unconditional / resolve #33599 - # InstallCheck phase - , doInstallCheck ? config.doCheckByDefault or false +lib.extendDerivation + validity.handled + ({ + overrideAttrs = f: stdenv.mkDerivation (attrs // (f attrs)); - , # TODO(@Ericson2314): Make always true and remove - strictDeps ? stdenv.hostPlatform != stdenv.buildPlatform - , meta ? {} - , passthru ? {} - , pos ? # position used in error messages and for meta.position - (if attrs.meta.description or null != null - then builtins.unsafeGetAttrPos "description" attrs.meta - else if attrs.version or null != null - then builtins.unsafeGetAttrPos "version" attrs - else builtins.unsafeGetAttrPos "name" attrs) - , separateDebugInfo ? false - , outputs ? [ "out" ] - , __darwinAllowLocalNetworking ? false - , __impureHostDeps ? [] - , __propagatedImpureHostDeps ? [] - , sandboxProfile ? "" - , propagatedSandboxProfile ? "" + # A derivation that always builds successfully and whose runtime + # dependencies are the original derivations build time dependencies + # This allows easy building and distributing of all derivations + # needed to enter a nix-shell with + # nix-build shell.nix -A inputDerivation + inputDerivation = derivation (derivationArg // { + # Add a name in case the original drv didn't have one + name = derivationArg.name or "inputDerivation"; + # This always only has one output + outputs = [ "out" ]; - , hardeningEnable ? [] - , hardeningDisable ? [] + # Propagate the original builder and arguments, since we override + # them and they might contain references to build inputs + _derivation_original_builder = derivationArg.builder; + _derivation_original_args = derivationArg.args; - , patches ? [] + builder = stdenv.shell; + # The bash builtin `export` dumps all current environment variables, + # which is where all build input references end up (e.g. $PATH for + # 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" ]; + }); - , __contentAddressed ? - (! attrs ? outputHash) # Fixed-output drvs can't be content addressed too - && (config.contentAddressedByDefault or false) - - , ... } @ attrs: - - let - # TODO(@oxij, @Ericson2314): This is here to keep the old semantics, remove when - # no package has `doCheck = true`. - doCheck' = doCheck && stdenv.hostPlatform == stdenv.buildPlatform; - doInstallCheck' = doInstallCheck && stdenv.hostPlatform == stdenv.buildPlatform; - - separateDebugInfo' = separateDebugInfo && stdenv.hostPlatform.isLinux && !(stdenv.hostPlatform.useLLVM or false); - outputs' = outputs ++ lib.optional separateDebugInfo' "debug"; - - 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" ]; - # 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.isAarch64 || stdenv.hostPlatform.isAarch32) && stdenv.hostPlatform.isStatic) - then supportedHardeningFlags - else lib.remove "pie" supportedHardeningFlags; - enabledHardeningOptions = - if builtins.elem "all" hardeningDisable - then [] - else lib.subtractLists hardeningDisable (defaultHardeningFlags ++ hardeningEnable); - # hardeningDisable additionally supports "all". - erroneousHardeningFlags = lib.subtractLists supportedHardeningFlags (hardeningEnable ++ lib.remove "all" hardeningDisable); - in if builtins.length erroneousHardeningFlags != 0 - then abort ("mkDerivation was called with unsupported hardening flags: " + lib.generators.toPretty {} { - inherit erroneousHardeningFlags hardeningDisable hardeningEnable supportedHardeningFlags; - }) - else let - doCheck = doCheck'; - doInstallCheck = doInstallCheck'; - - outputs = outputs'; - - references = nativeBuildInputs ++ buildInputs - ++ propagatedNativeBuildInputs ++ propagatedBuildInputs; - - dependencies = map (map lib.chooseDevOutputs) [ - [ - (map (drv: drv.__spliced.buildBuild or drv) depsBuildBuild) - (map (drv: drv.nativeDrv or drv) 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.buildTarget or drv) depsBuildTarget) - ] - [ - (map (drv: drv.__spliced.hostHost or drv) depsHostHost) - (map (drv: drv.crossDrv or drv) buildInputs) - ] - [ - (map (drv: drv.__spliced.targetTarget or drv) depsTargetTarget) - ] - ]; - propagatedDependencies = map (map lib.chooseDevOutputs) [ - [ - (map (drv: drv.__spliced.buildBuild or drv) depsBuildBuildPropagated) - (map (drv: drv.nativeDrv or drv) propagatedNativeBuildInputs) - (map (drv: drv.__spliced.buildTarget or drv) depsBuildTargetPropagated) - ] - [ - (map (drv: drv.__spliced.hostHost or drv) depsHostHostPropagated) - (map (drv: drv.crossDrv or drv) propagatedBuildInputs) - ] - [ - (map (drv: drv.__spliced.targetTarget or drv) depsTargetTargetPropagated) - ] - ]; - - computedSandboxProfile = - lib.concatMap (input: input.__propagatedSandboxProfile or []) - (stdenv.extraNativeBuildInputs - ++ stdenv.extraBuildInputs - ++ lib.concatLists dependencies); - - computedPropagatedSandboxProfile = - lib.concatMap (input: input.__propagatedSandboxProfile or []) - (lib.concatLists propagatedDependencies); - - computedImpureHostDeps = - lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) - (stdenv.extraNativeBuildInputs - ++ stdenv.extraBuildInputs - ++ lib.concatLists dependencies)); - - computedPropagatedImpureHostDeps = - lib.unique (lib.concatMap (input: input.__propagatedImpureHostDeps or []) - (lib.concatLists propagatedDependencies)); - - derivationArg = - (removeAttrs attrs - ["meta" "passthru" "pos" - "checkInputs" "installCheckInputs" - "__darwinAllowLocalNetworking" - "__impureHostDeps" "__propagatedImpureHostDeps" - "sandboxProfile" "propagatedSandboxProfile"]) - // (lib.optionalAttrs (attrs ? name || (attrs ? pname && attrs ? version)) { - name = - let - # Indicate the host platform of the derivation if cross compiling. - # Fixed-output derivations like source tarballs shouldn't get a host - # suffix. But we have some weird ones with run-time deps that are - # just used for their side-affects. Those might as well since the - # hash can't be the same. See #32986. - 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 - # hostSuffix before the version, so we could contemplate removing - # it again. - staticMarker = lib.optionalString stdenv.hostPlatform.isStatic "-static"; - in - if attrs ? name - then attrs.name + hostSuffix - else "${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"; - }) // { - builder = attrs.realBuilder or stdenv.shell; - args = attrs.args or ["-e" (attrs.builder or ./default-builder.sh)]; - inherit stdenv; - - # The `system` attribute of a derivation has special meaning to Nix. - # Derivations set it to choose what sort of machine could be used to - # execute the build, The build platform entirely determines this, - # indeed more finely than Nix knows or cares about. The `system` - # attribute of `buildPlatfom` matches Nix's degree of specificity. - # exactly. - inherit (stdenv.buildPlatform) system; - - userHook = config.stdenv.userHook or null; - __ignoreNulls = true; - - inherit strictDeps; - - depsBuildBuild = lib.elemAt (lib.elemAt dependencies 0) 0; - nativeBuildInputs = lib.elemAt (lib.elemAt dependencies 0) 1; - depsBuildTarget = lib.elemAt (lib.elemAt dependencies 0) 2; - depsHostHost = lib.elemAt (lib.elemAt dependencies 1) 0; - buildInputs = lib.elemAt (lib.elemAt dependencies 1) 1; - depsTargetTarget = lib.elemAt (lib.elemAt dependencies 2) 0; - - depsBuildBuildPropagated = lib.elemAt (lib.elemAt propagatedDependencies 0) 0; - propagatedNativeBuildInputs = lib.elemAt (lib.elemAt propagatedDependencies 0) 1; - depsBuildTargetPropagated = lib.elemAt (lib.elemAt propagatedDependencies 0) 2; - depsHostHostPropagated = lib.elemAt (lib.elemAt propagatedDependencies 1) 0; - propagatedBuildInputs = lib.elemAt (lib.elemAt propagatedDependencies 1) 1; - depsTargetTargetPropagated = lib.elemAt (lib.elemAt propagatedDependencies 2) 0; - - # This parameter is sometimes a string, sometimes null, and sometimes a list, yuck - configureFlags = let inherit (lib) optional elem; in - (/**/ if lib.isString configureFlags then [configureFlags] - else if configureFlags == null then [] - else configureFlags) - ++ optional (elem "build" configurePlatforms) "--build=${stdenv.buildPlatform.config}" - ++ optional (elem "host" configurePlatforms) "--host=${stdenv.hostPlatform.config}" - ++ optional (elem "target" configurePlatforms) "--target=${stdenv.targetPlatform.config}"; - - inherit patches; - - inherit doCheck doInstallCheck; - - inherit outputs; - } // lib.optionalAttrs (__contentAddressed) { - inherit __contentAddressed; - # Provide default values for outputHashMode and outputHashAlgo because - # most people won't care about these anyways - outputHashAlgo = attrs.outputHashAlgo or "sha256"; - outputHashMode = attrs.outputHashMode or "recursive"; - } // lib.optionalAttrs (stdenv.hostPlatform != stdenv.buildPlatform) { - cmakeFlags = - (/**/ if lib.isString cmakeFlags then [cmakeFlags] - else if cmakeFlags == null then [] - else cmakeFlags) - ++ [ "-DCMAKE_SYSTEM_NAME=${lib.findFirst lib.isString "Generic" ( - lib.optional (!stdenv.hostPlatform.isRedox) stdenv.hostPlatform.uname.system)}"] - ++ lib.optional (stdenv.hostPlatform.uname.processor != null) "-DCMAKE_SYSTEM_PROCESSOR=${stdenv.hostPlatform.uname.processor}" - ++ lib.optional (stdenv.hostPlatform.uname.release != null) "-DCMAKE_SYSTEM_VERSION=${stdenv.hostPlatform.release}" - ++ lib.optional (stdenv.hostPlatform.isDarwin) "-DCMAKE_OSX_ARCHITECTURES=${stdenv.hostPlatform.darwinArch}" - ++ lib.optional (stdenv.buildPlatform.uname.system != null) "-DCMAKE_HOST_SYSTEM_NAME=${stdenv.buildPlatform.uname.system}" - ++ lib.optional (stdenv.buildPlatform.uname.processor != null) "-DCMAKE_HOST_SYSTEM_PROCESSOR=${stdenv.buildPlatform.uname.processor}" - ++ lib.optional (stdenv.buildPlatform.uname.release != null) "-DCMAKE_HOST_SYSTEM_VERSION=${stdenv.buildPlatform.uname.release}"; - - mesonFlags = if mesonFlags == null then null 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; - crossFile = builtins.toFile "cross-file.conf" '' - [properties] - needs_exe_wrapper = true - - [host_machine] - system = '${stdenv.targetPlatform.parsed.kernel.name}' - cpu_family = '${cpuFamily stdenv.targetPlatform}' - cpu = '${stdenv.targetPlatform.parsed.cpu.name}' - endian = ${if stdenv.targetPlatform.isLittleEndian then "'little'" else "'big'"} - ''; - in [ "--cross-file=${crossFile}" ] ++ mesonFlags; - } // lib.optionalAttrs (attrs.enableParallelBuilding or false) { - enableParallelChecking = attrs.enableParallelChecking or true; - } // lib.optionalAttrs (hardeningDisable != [] || hardeningEnable != [] || stdenv.hostPlatform.isMusl) { - NIX_HARDENING_ENABLE = enabledHardeningOptions; - } // lib.optionalAttrs (stdenv.hostPlatform.isx86_64 && stdenv.hostPlatform ? gcc.arch) { - requiredSystemFeatures = attrs.requiredSystemFeatures or [] ++ [ "gccarch-${stdenv.hostPlatform.gcc.arch}" ]; - } // lib.optionalAttrs (stdenv.buildPlatform.isDarwin) { - inherit __darwinAllowLocalNetworking; - # TODO: remove lib.unique once nix has a list canonicalization primitive - __sandboxProfile = - let profiles = [ stdenv.extraSandboxProfile ] ++ computedSandboxProfile ++ computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile sandboxProfile ]; - final = lib.concatStringsSep "\n" (lib.filter (x: x != "") (lib.unique profiles)); - in final; - __propagatedSandboxProfile = lib.unique (computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]); - __impureHostDeps = computedImpureHostDeps ++ computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps ++ __impureHostDeps ++ stdenv.__extraImpureHostDeps ++ [ - "/dev/zero" - "/dev/random" - "/dev/urandom" - "/bin/sh" - ]; - __propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps; - }; - - 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 (and is under assert), - # lets 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 - && (if config.checkMetaRecursively or false - then lib.all (d: d.meta.available or true) references - else true); - }; - - in - - lib.extendDerivation - validity.handled - ({ - overrideAttrs = f: stdenv.mkDerivation (attrs // (f attrs)); - - # A derivation that always builds successfully and whose runtime - # dependencies are the original derivations build time dependencies - # This allows easy building and distributing of all derivations - # needed to enter a nix-shell with - # nix-build shell.nix -A inputDerivation - inputDerivation = derivation (derivationArg // { - # Add a name in case the original drv didn't have one - name = derivationArg.name or "inputDerivation"; - # This always only has one output - outputs = [ "out" ]; - - # Propagate the original builder and arguments, since we override - # them and they might contain references to build inputs - _derivation_original_builder = derivationArg.builder; - _derivation_original_args = derivationArg.args; - - builder = stdenv.shell; - # The bash builtin `export` dumps all current environment variables, - # which is where all build input references end up (e.g. $PATH for - # 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" ]; - }); - - inherit meta passthru; - } // - # 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) + inherit meta passthru; + } // + # 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)