push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
export PATH=
for i in $initialPath; do
if [ "$i" = / ]; then i=; fi
PATH=$PATH${PATH:+:}$i/bin
done
mkdir $out
{
echo "export SHELL=$shell"
echo "initialPath=\"$initialPath\""
echo "defaultNativeBuildInputs=\"$defaultNativeBuildInputs\""
echo "defaultBuildInputs=\"$defaultBuildInputs\""
echo "$preHook"
cat "$setup"
} > "$out/setup"
# Allow the user to install stdenv using nix-env and get the packages
# in stdenv.
mkdir $out/nix-support
if [ "${propagatedUserEnvPkgs[*]}" ]; then
printf '%s ' "${propagatedUserEnvPkgs[@]}" > $out/nix-support/propagated-user-env-packages
fi

View File

@@ -0,0 +1,764 @@
# Checks derivation meta and attrs for problems (like brokenness,
# licenses, etc).
{
lib,
config,
hostPlatform,
}:
let
inherit (lib)
all
attrNames
attrValues
concatMapStrings
concatMapStringsSep
concatStrings
findFirst
isDerivation
length
concatMap
mutuallyExclusive
optional
optionalAttrs
optionalString
optionals
isAttrs
isString
mapAttrs
;
inherit (lib.lists)
any
toList
isList
elem
;
inherit (lib.meta)
availableOn
cpeFullVersionWithVendor
tryCPEPatchVersionInUpdateWithVendor
;
inherit (lib.generators)
toPretty
;
# If we're in hydra, we can dispense with the more verbose error
# messages and make problems easier to spot.
inHydra = config.inHydra or false;
# Allow the user to opt-into additional warnings, e.g.
# import <nixpkgs> { config = { showDerivationWarnings = [ "maintainerless" ]; }; }
showWarnings = config.showDerivationWarnings;
getNameWithVersion =
attrs: attrs.name or "${attrs.pname or "«name-missing»"}-${attrs.version or "«version-missing»"}";
allowUnfree = config.allowUnfree || builtins.getEnv "NIXPKGS_ALLOW_UNFREE" == "1";
allowNonSource =
let
envVar = builtins.getEnv "NIXPKGS_ALLOW_NONSOURCE";
in
if envVar != "" then envVar != "0" else config.allowNonSource or true;
allowlist = config.allowlistedLicenses or config.whitelistedLicenses or [ ];
blocklist = config.blocklistedLicenses or config.blacklistedLicenses or [ ];
areLicenseListsValid =
if mutuallyExclusive allowlist blocklist then
true
else
throw "allowlistedLicenses and blocklistedLicenses are not mutually exclusive.";
hasLicense = attrs: attrs ? meta.license;
hasListedLicense =
assert areLicenseListsValid;
list: attrs:
length list > 0
&& hasLicense attrs
&& (
if isList attrs.meta.license then
any (l: elem l list) attrs.meta.license
else
elem attrs.meta.license list
);
hasAllowlistedLicense = attrs: hasListedLicense allowlist attrs;
hasBlocklistedLicense = attrs: hasListedLicense blocklist attrs;
allowBroken = config.allowBroken || builtins.getEnv "NIXPKGS_ALLOW_BROKEN" == "1";
allowUnsupportedSystem =
config.allowUnsupportedSystem || builtins.getEnv "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM" == "1";
isUnfree =
licenses:
if isAttrs licenses then
!licenses.free or true
# TODO: Returning false in the case of a string is a bug that should be fixed.
# In a previous implementation of this function the function body
# was `licenses: lib.lists.any (l: !l.free or true) licenses;`
# which always evaluates to `!true` for strings.
else if isString licenses then
false
else
any (l: !l.free or true) licenses;
hasUnfreeLicense = attrs: hasLicense attrs && isUnfree attrs.meta.license;
hasNoMaintainers =
# To get usable output, we want to avoid flagging "internal" derivations.
# Because we do not have a way to reliably decide between internal or
# external derivation, some heuristics are required to decide.
#
# If `outputHash` is defined, the derivation is a FOD, such as the output of a fetcher.
# If `description` is not defined, the derivation is probably not a package.
# Simply checking whether `meta` is defined is insufficient,
# as some fetchers and trivial builders do define meta.
attrs:
(!attrs ? outputHash)
&& (attrs ? meta.description)
&& (attrs.meta.maintainers or [ ] == [ ])
&& (attrs.meta.teams or [ ] == [ ]);
isMarkedBroken = attrs: attrs.meta.broken or false;
# Allow granular checks to allow only some broken packages
# Example:
# { pkgs, ... }:
# {
# allowBroken = false;
# allowBrokenPredicate = pkg: builtins.elem (pkgs.lib.getName pkg) [ "hello" ];
# }
allowBrokenPredicate = config.allowBrokenPredicate or (x: false);
hasDeniedBroken =
attrs: (attrs.meta.broken or false) && !allowBroken && !allowBrokenPredicate attrs;
hasUnsupportedPlatform = pkg: !(availableOn hostPlatform pkg);
isMarkedInsecure = attrs: (attrs.meta.knownVulnerabilities or [ ]) != [ ];
# Allow granular checks to allow only some unfree packages
# Example:
# {pkgs, ...}:
# {
# allowUnfree = false;
# allowUnfreePredicate = (x: pkgs.lib.hasPrefix "vscode" x.name);
# }
allowUnfreePredicate = config.allowUnfreePredicate or (x: false);
# Check whether unfree packages are allowed and if not, whether the
# package has an unfree license and is not explicitly allowed by the
# `allowUnfreePredicate` function.
hasDeniedUnfreeLicense =
attrs: hasUnfreeLicense attrs && !allowUnfree && !allowUnfreePredicate attrs;
allowInsecureDefaultPredicate =
x: builtins.elem (getNameWithVersion x) (config.permittedInsecurePackages or [ ]);
allowInsecurePredicate = x: (config.allowInsecurePredicate or allowInsecureDefaultPredicate) x;
hasAllowedInsecure =
attrs:
!(isMarkedInsecure attrs)
|| allowInsecurePredicate attrs
|| builtins.getEnv "NIXPKGS_ALLOW_INSECURE" == "1";
isNonSource = sourceTypes: any (t: !t.isSource) sourceTypes;
hasNonSourceProvenance =
attrs: (attrs ? meta.sourceProvenance) && isNonSource attrs.meta.sourceProvenance;
# Allow granular checks to allow only some non-source-built packages
# Example:
# { pkgs, ... }:
# {
# allowNonSource = false;
# allowNonSourcePredicate = with pkgs.lib.lists; pkg: !(any (p: !p.isSource && p != lib.sourceTypes.binaryFirmware) pkg.meta.sourceProvenance);
# }
allowNonSourcePredicate = config.allowNonSourcePredicate or (x: false);
# Check whether non-source packages are allowed and if not, whether the
# package has non-source provenance and is not explicitly allowed by the
# `allowNonSourcePredicate` function.
hasDeniedNonSourceProvenance =
attrs: hasNonSourceProvenance attrs && !allowNonSource && !allowNonSourcePredicate attrs;
showLicenseOrSourceType =
value: toString (map (v: v.shortName or v.fullName or "unknown") (toList value));
showLicense = showLicenseOrSourceType;
showSourceType = showLicenseOrSourceType;
pos_str = meta: meta.position or "«unknown-file»";
remediation = {
unfree = remediate_allowlist "Unfree" (remediate_predicate "allowUnfreePredicate");
non-source = remediate_allowlist "NonSource" (remediate_predicate "allowNonSourcePredicate");
broken = remediate_allowlist "Broken" (x: "");
unsupported = remediate_allowlist "UnsupportedSystem" (x: "");
blocklisted = x: "";
insecure = remediate_insecure;
broken-outputs = remediateOutputsToInstall;
unknown-meta = x: "";
maintainerless = x: "";
};
remediation_env_var =
allow_attr:
{
Unfree = "NIXPKGS_ALLOW_UNFREE";
Broken = "NIXPKGS_ALLOW_BROKEN";
UnsupportedSystem = "NIXPKGS_ALLOW_UNSUPPORTED_SYSTEM";
NonSource = "NIXPKGS_ALLOW_NONSOURCE";
}
.${allow_attr};
remediation_phrase =
allow_attr:
{
Unfree = "unfree packages";
Broken = "broken packages";
UnsupportedSystem = "packages that are unsupported for this system";
NonSource = "packages not built from source";
}
.${allow_attr};
remediate_predicate = predicateConfigAttr: attrs: ''
Alternatively you can configure a predicate to allow specific packages:
{ nixpkgs.config.${predicateConfigAttr} = pkg: builtins.elem (lib.getName pkg) [
"${lib.getName attrs}"
];
}
'';
# flakeNote will be printed in the remediation messages below.
flakeNote = "
Note: When using `nix shell`, `nix build`, `nix develop`, etc with a flake,
then pass `--impure` in order to allow use of environment variables.
";
remediate_allowlist = allow_attr: rebuild_amendment: attrs: ''
a) To temporarily allow ${remediation_phrase allow_attr}, you can use an environment variable
for a single invocation of the nix tools.
$ export ${remediation_env_var allow_attr}=1
${flakeNote}
b) For `nixos-rebuild` you can set
{ nixpkgs.config.allow${allow_attr} = true; }
in configuration.nix to override this.
${rebuild_amendment attrs}
c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
{ allow${allow_attr} = true; }
to ~/.config/nixpkgs/config.nix.
'';
remediate_insecure =
attrs:
''
Known issues:
''
+ (concatStrings (map (issue: " - ${issue}\n") attrs.meta.knownVulnerabilities))
+ ''
You can install it anyway by allowing this package, using the
following methods:
a) To temporarily allow all insecure packages, you can use an environment
variable for a single invocation of the nix tools:
$ export NIXPKGS_ALLOW_INSECURE=1
${flakeNote}
b) for `nixos-rebuild` you can add ${getNameWithVersion attrs} to
`nixpkgs.config.permittedInsecurePackages` in the configuration.nix,
like so:
{
nixpkgs.config.permittedInsecurePackages = [
"${getNameWithVersion attrs}"
];
}
c) For `nix-env`, `nix-build`, `nix-shell` or any other Nix command you can add
${getNameWithVersion attrs} to `permittedInsecurePackages` in
~/.config/nixpkgs/config.nix, like so:
{
permittedInsecurePackages = [
"${getNameWithVersion attrs}"
];
}
'';
remediateOutputsToInstall =
attrs:
let
expectedOutputs = attrs.meta.outputsToInstall or [ ];
actualOutputs = attrs.outputs or [ "out" ];
missingOutputs = builtins.filter (output: !builtins.elem output actualOutputs) expectedOutputs;
in
''
The package ${getNameWithVersion attrs} has set meta.outputsToInstall to: ${builtins.concatStringsSep ", " expectedOutputs}
however ${getNameWithVersion attrs} only has the outputs: ${builtins.concatStringsSep ", " actualOutputs}
and is missing the following outputs:
${concatStrings (map (output: " - ${output}\n") missingOutputs)}
'';
handleEvalIssue =
{ meta, attrs }:
{
reason,
errormsg ? "",
}:
let
msg =
if inHydra then
"Failed to evaluate ${getNameWithVersion attrs}: «${reason}»: ${errormsg}"
else
''
Package ${getNameWithVersion attrs} in ${pos_str meta} ${errormsg}, refusing to evaluate.
''
+ (builtins.getAttr reason remediation) attrs;
handler = if config ? handleEvalIssue then config.handleEvalIssue reason else throw;
in
handler msg;
handleEvalWarning =
{ meta, attrs }:
{
reason,
errormsg ? "",
}:
let
remediationMsg = (builtins.getAttr reason remediation) attrs;
msg =
if inHydra then
"Warning while evaluating ${getNameWithVersion attrs}: «${reason}»: ${errormsg}"
else
"Package ${getNameWithVersion attrs} in ${pos_str meta} ${errormsg}, continuing anyway."
+ (optionalString (remediationMsg != "") "\n${remediationMsg}");
isEnabled = findFirst (x: x == reason) null showWarnings;
in
if isEnabled != null then builtins.trace msg true else true;
metaTypes =
let
types = import ./meta-types.nix { inherit lib; };
inherit (types)
str
union
int
attrs
attrsOf
any
listOf
bool
;
platforms = listOf (union [
str
(attrsOf any)
]); # see lib.meta.platformMatch
in
{
# These keys are documented
description = str;
mainProgram = str;
longDescription = str;
branch = str;
homepage = union [
(listOf str)
str
];
downloadPage = str;
changelog = union [
(listOf str)
str
];
license =
let
# TODO disallow `str` licenses, use a module
licenseType = union [
(attrsOf any)
str
];
in
union [
(listOf licenseType)
licenseType
];
sourceProvenance = listOf attrs;
maintainers = listOf (attrsOf any); # TODO use the maintainer type from lib/tests/maintainer-module.nix
teams = listOf (attrsOf any); # TODO similar to maintainers, use a teams type
priority = int;
pkgConfigModules = listOf str;
inherit platforms;
hydraPlatforms = listOf str;
broken = bool;
unfree = bool;
unsupported = bool;
insecure = bool;
tests = {
name = "test";
verify =
x:
x == { }
||
# Accept {} for tests that are unsupported
(isDerivation x && x ? meta.timeout);
};
timeout = int;
knownVulnerabilities = listOf str;
badPlatforms = platforms;
# Needed for Hydra to expose channel tarballs:
# https://github.com/NixOS/hydra/blob/53335323ae79ca1a42643f58e520b376898ce641/doc/manual/src/jobs.md#meta-fields
isHydraChannel = bool;
# Weirder stuff that doesn't appear in the documentation?
maxSilent = int;
name = str;
version = str;
tag = str;
executables = listOf str;
outputsToInstall = listOf str;
position = str;
available = any;
isBuildPythonPackage = platforms;
schedulingPriority = int;
isFcitxEngine = bool;
isIbusEngine = bool;
isGutenprint = bool;
# Used for the original location of the maintainer and team attributes to assist with pings.
maintainersPosition = any;
teamsPosition = any;
identifiers = attrs;
};
checkMetaAttr =
let
# Map attrs directly to the verify function for performance
metaTypes' = mapAttrs (_: t: t.verify) metaTypes;
in
k: v:
if metaTypes ? ${k} then
if metaTypes'.${k} v then
[ ]
else
[
"key 'meta.${k}' has invalid value; expected ${metaTypes.${k}.name}, got\n ${
toPretty { indent = " "; } v
}"
]
else
[
"key 'meta.${k}' is unrecognized; expected one of: \n [${
concatMapStringsSep ", " (x: "'${x}'") (attrNames metaTypes)
}]"
];
checkMeta =
meta:
optionals config.checkMeta (concatMap (attr: checkMetaAttr attr meta.${attr}) (attrNames meta));
checkOutputsToInstall =
attrs:
let
expectedOutputs = attrs.meta.outputsToInstall or [ ];
actualOutputs = attrs.outputs or [ "out" ];
missingOutputs = builtins.filter (output: !builtins.elem output actualOutputs) expectedOutputs;
in
if config.checkMeta then builtins.length missingOutputs > 0 else false;
# Check if a derivation is valid, that is whether it passes checks for
# e.g brokenness or license.
#
# Return { valid: "yes", "warn" or "no" } and additionally
# { reason: String; errormsg: String } if it is not valid, where
# reason is one of "unfree", "blocklisted", "broken", "insecure", ...
# !!! reason strings are hardcoded into OfBorg, make sure to keep them in sync
# Along with a boolean flag for each reason
checkValidity =
let
validYes = {
valid = "yes";
handled = true;
};
in
attrs:
# Check meta attribute types first, to make sure it is always called even when there are other issues
# Note that this is not a full type check and functions below still need to by careful about their inputs!
let
res = checkMeta (attrs.meta or { });
in
if res != [ ] then
{
valid = "no";
reason = "unknown-meta";
errormsg = "has an invalid meta attrset:${concatMapStrings (x: "\n - " + x) res}\n";
}
# --- Put checks that cannot be ignored here ---
else if checkOutputsToInstall attrs then
{
valid = "no";
reason = "broken-outputs";
errormsg = "has invalid meta.outputsToInstall";
}
# --- Put checks that can be ignored here ---
else if hasDeniedUnfreeLicense attrs && !(hasAllowlistedLicense attrs) then
{
valid = "no";
reason = "unfree";
errormsg = "has an unfree license (${showLicense attrs.meta.license})";
}
else if hasBlocklistedLicense attrs then
{
valid = "no";
reason = "blocklisted";
errormsg = "has a blocklisted license (${showLicense attrs.meta.license})";
}
else if hasDeniedNonSourceProvenance attrs then
{
valid = "no";
reason = "non-source";
errormsg = "contains elements not built from source (${showSourceType attrs.meta.sourceProvenance})";
}
else if hasDeniedBroken attrs then
{
valid = "no";
reason = "broken";
errormsg = "is marked as broken";
}
else if !allowUnsupportedSystem && hasUnsupportedPlatform attrs then
let
toPretty' = toPretty {
allowPrettyValues = true;
indent = " ";
};
in
{
valid = "no";
reason = "unsupported";
errormsg = ''
is not available on the requested hostPlatform:
hostPlatform.system = "${hostPlatform.system}"
package.meta.platforms = ${toPretty' (attrs.meta.platforms or [ ])}
package.meta.badPlatforms = ${toPretty' (attrs.meta.badPlatforms or [ ])}
'';
}
else if !(hasAllowedInsecure attrs) then
{
valid = "no";
reason = "insecure";
errormsg = "is marked as insecure";
}
# --- warnings ---
# Please also update the type in /pkgs/top-level/config.nix alongside this.
else if hasNoMaintainers attrs then
{
valid = "warn";
reason = "maintainerless";
errormsg = "has no maintainers or teams";
}
# -----
else
validYes;
# Helper functions and declarations to handle identifiers, extracted to reduce allocations
hasAllCPEParts =
cpeParts:
let
values = attrValues cpeParts;
in
(length values == 11) && !any isNull values;
makeCPE =
{
part,
vendor,
product,
version,
update,
edition,
sw_edition,
target_sw,
target_hw,
language,
other,
}:
"cpe:2.3:${part}:${vendor}:${product}:${version}:${update}:${edition}:${sw_edition}:${target_sw}:${target_hw}:${language}:${other}";
possibleCPEPartsFuns = [
(vendor: version: {
success = true;
value = cpeFullVersionWithVendor vendor version;
})
tryCPEPatchVersionInUpdateWithVendor
];
# 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.
# Example:
# meta = checkMeta.commonMeta { inherit validity attrs pos references; };
# validity = checkMeta.assertValidity { inherit meta attrs; };
commonMeta =
{
validity,
attrs,
pos ? null,
references ? [ ],
}:
let
outputs = attrs.outputs or [ "out" ];
hasOutput = out: builtins.elem out outputs;
maintainersPosition = builtins.unsafeGetAttrPos "maintainers" (attrs.meta or { });
teamsPosition = builtins.unsafeGetAttrPos "teams" (attrs.meta or { });
in
{
# `name` derivation attribute 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 = [
(
if hasOutput "bin" then
"bin"
else if hasOutput "out" then
"out"
else
findFirst hasOutput null outputs
)
]
++ optional (hasOutput "man") "man";
# CI scripts look at these to determine pings. Note that we should filter nulls out of this,
# or nix-env complains: https://github.com/NixOS/nix/blob/2.18.8/src/nix-env/nix-env.cc#L963
${if maintainersPosition == null then null else "maintainersPosition"} = maintainersPosition;
${if teamsPosition == null then null else "teamsPosition"} = teamsPosition;
}
// attrs.meta or { }
// {
# Fill `meta.position` to identify the source location of the package.
${if pos == null then null else "position"} = pos.file + ":" + toString pos.line;
# Maintainers should be inclusive of teams.
# Note that there may be external consumers of this API (repology, for instance) -
# if you add a new maintainer or team attribute please ensure that this expectation is still met.
maintainers =
attrs.meta.maintainers or [ ] ++ concatMap (team: team.members or [ ]) attrs.meta.teams or [ ];
identifiers =
let
# nix-env writes a warning for each derivation that has null in its meta values, so
# fields without known values are removed from the result
defaultCPEParts = {
part = "a";
#vendor = null;
${if attrs ? pname then "product" else null} = attrs.pname;
#version = null;
#update = null;
edition = "*";
sw_edition = "*";
target_sw = "*";
target_hw = "*";
language = "*";
other = "*";
};
cpeParts = defaultCPEParts // attrs.meta.identifiers.cpeParts or { };
cpe = if hasAllCPEParts cpeParts then makeCPE cpeParts else null;
possibleCPEs =
if cpe != null then
[ { inherit cpeParts cpe; } ]
else if attrs.meta.identifiers.cpeParts.vendor or null == null || attrs.version or null == null then
[ ]
else
concatMap (
f:
let
result = f attrs.meta.identifiers.cpeParts.vendor attrs.version;
# Note that attrs.meta.identifiers.cpeParts at this point can include defaults with user overrides.
# Since we can't split them apart, user overrides don't apply to possibleCPEs.
guessedParts = cpeParts // result.value;
in
optional (result.success && hasAllCPEParts guessedParts) {
cpeParts = guessedParts;
cpe = makeCPE guessedParts;
}
) possibleCPEPartsFuns;
v1 = {
inherit cpeParts possibleCPEs;
${if cpe != null then "cpe" else null} = cpe;
};
in
v1
// {
inherit v1;
};
# Expose the result of the checks for everyone to see.
unfree = hasUnfreeLicense attrs;
broken = isMarkedBroken attrs;
unsupported = hasUnsupportedPlatform attrs;
insecure = isMarkedInsecure attrs;
available =
validity.valid != "no"
&& (
if config.checkMetaRecursively or false then all (d: d.meta.available or true) references else true
);
};
assertValidity =
{ meta, attrs }:
let
validity = checkValidity attrs;
inherit (validity) valid;
in
if validity ? handled then
validity
else
validity
// {
# Throw an error if trying to evaluate a non-valid derivation
# or, alternatively, just output a warning message.
handled = (
if valid == "yes" then
true
else if valid == "no" then
(handleEvalIssue { inherit meta attrs; } { inherit (validity) reason errormsg; })
else if valid == "warn" then
(handleEvalWarning { inherit meta attrs; } { inherit (validity) reason errormsg; })
else
throw "Unknown validity: '${valid}'"
);
};
in
{
inherit assertValidity commonMeta;
}

View File

@@ -0,0 +1,24 @@
{ pkgs }:
[
pkgs.coreutils
pkgs.findutils
pkgs.diffutils
pkgs.gnused
pkgs.gnugrep
pkgs.gawk
pkgs.gnutar
pkgs.gzip
pkgs.bzip2.bin
pkgs.gnumake
pkgs.bashNonInteractive
pkgs.patch
pkgs.xz.bin
# The `file` command is added here because an enormous number of
# packages have a vendored dependency upon `file` in their
# `./configure` script, due to libtool<=2.4.6, or due to
# libtool>=2.4.7 in which the package author decided to set FILECMD
# when running libtoolize. In fact, file-5.4.6 *depends on itself*
# and tries to invoke `file` from its own ./configure script.
pkgs.file
]

View File

@@ -0,0 +1 @@
genericBuild

View File

@@ -0,0 +1,229 @@
let
lib = import ../../../lib;
stdenv-overridable = lib.makeOverridable (
argsStdenv@{
name ? "stdenv",
preHook ? "",
initialPath,
# If we don't have a C compiler, we might either have `cc = null` or `cc =
# throw ...`, but if we do have a C compiler we should definitely have `cc !=
# null`.
#
# TODO(@Ericson2314): Add assert without creating infinite recursion
hasCC ? cc != null,
cc,
shell,
allowedRequisites ? null,
extraAttrs ? { },
overrides ? (self: super: { }),
config,
disallowedRequisites ? [ ],
# The `fetchurl' to use for downloading curl and its dependencies
# (see all-packages.nix).
fetchurlBoot,
setupScript ? ./setup.sh,
extraNativeBuildInputs ? [ ],
extraBuildInputs ? [ ],
__stdenvImpureHostDeps ? [ ],
__extraImpureHostDeps ? [ ],
stdenvSandboxProfile ? "",
extraSandboxProfile ? "",
## Platform parameters
##
## The "build" "host" "target" terminology below comes from GNU Autotools. See
## its documentation for more information on what those words mean. Note that
## each should always be defined, even when not cross compiling.
##
## For purposes of bootstrapping, think of each stage as a "sliding window"
## over a list of platforms. Specifically, the host platform of the previous
## stage becomes the build platform of the current one, and likewise the
## target platform of the previous stage becomes the host platform of the
## current one.
##
# The platform on which packages are built. Consists of `system`, a
# string (e.g.,`i686-linux') identifying the most import attributes of the
# build platform, and `platform` a set of other details.
buildPlatform,
# The platform on which packages run.
hostPlatform,
# 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 convenient to have as a parameter so the stdenv "adapters" work better
mkDerivationFromStdenv ?
stdenv: (import ./make-derivation.nix { inherit lib config; } stdenv).mkDerivation,
}:
let
defaultNativeBuildInputs =
extraNativeBuildInputs
++ [
../../build-support/setup-hooks/no-broken-symlinks.sh
../../build-support/setup-hooks/audit-tmpdir.sh
../../build-support/setup-hooks/compress-man-pages.sh
../../build-support/setup-hooks/make-symlinks-relative.sh
../../build-support/setup-hooks/move-docs.sh
../../build-support/setup-hooks/move-lib64.sh
../../build-support/setup-hooks/move-sbin.sh
../../build-support/setup-hooks/move-systemd-user-units.sh
../../build-support/setup-hooks/multiple-outputs.sh
../../build-support/setup-hooks/patch-shebangs.sh
../../build-support/setup-hooks/prune-libtool-files.sh
../../build-support/setup-hooks/reproducible-builds.sh
../../build-support/setup-hooks/set-source-date-epoch-to-latest.sh
../../build-support/setup-hooks/strip.sh
]
++ lib.optionals hasCC [ cc ];
defaultBuildInputs = extraBuildInputs;
stdenv = (stdenv-overridable argsStdenv);
in
# The stdenv that we are producing.
derivation (
lib.optionalAttrs (allowedRequisites != null) {
allowedRequisites = allowedRequisites ++ defaultNativeBuildInputs ++ defaultBuildInputs;
}
// lib.optionalAttrs config.contentAddressedByDefault {
__contentAddressed = true;
outputHashAlgo = "sha256";
outputHashMode = "recursive";
}
// {
inherit name;
inherit disallowedRequisites;
# Nix itself uses the `system` field of a derivation to decide where to
# build it. This is a bit confusing for cross compilation.
inherit (buildPlatform) system;
builder = shell;
args = [
"-e"
./builder.sh
];
setup = setupScript;
# We pretty much never need rpaths on Darwin, since all library path references
# are absolute unless we go out of our way to make them relative (like with CF)
# TODO: This really wants to be in stdenv/darwin but we don't have hostPlatform
# there (yet?) so it goes here until then.
preHook =
preHook
+ lib.optionalString buildPlatform.isDarwin ''
export NIX_DONT_SET_RPATH_FOR_BUILD=1
''
+ lib.optionalString (hostPlatform.isDarwin || (!hostPlatform.isElf && !hostPlatform.isMacho)) ''
export NIX_DONT_SET_RPATH=1
export NIX_NO_SELF_RPATH=1
''
+ lib.optionalString (hostPlatform.isDarwin && hostPlatform.isMacOS) ''
export MACOSX_DEPLOYMENT_TARGET=${hostPlatform.darwinMinVersion}
''
# TODO this should be uncommented, but it causes stupid mass rebuilds due to
# `pkgsCross.*.buildPackages` not being the same, resulting in cross-compiling
# for a target rebuilding all of `nativeBuildInputs` for that target.
#
# I think the best solution would just be to fixup linux RPATHs so we don't
# need to set `-rpath` anywhere.
# + lib.optionalString targetPlatform.isDarwin ''
# export NIX_DONT_SET_RPATH_FOR_TARGET=1
# ''
;
inherit
initialPath
shell
defaultNativeBuildInputs
defaultBuildInputs
;
}
// lib.optionalAttrs buildPlatform.isDarwin {
__sandboxProfile = stdenvSandboxProfile;
__impureHostDeps = __stdenvImpureHostDeps;
}
)
// {
meta = {
description = "The default build environment for Unix packages in Nixpkgs";
platforms = lib.platforms.all;
};
inherit buildPlatform hostPlatform targetPlatform;
inherit
extraNativeBuildInputs
extraBuildInputs
__extraImpureHostDeps
extraSandboxProfile
;
# Utility flags to test the type of platform.
inherit (hostPlatform)
isDarwin
isLinux
isSunOS
isCygwin
isBSD
isFreeBSD
isOpenBSD
isi686
isx86_32
isx86_64
is32bit
is64bit
isAarch32
isAarch64
isMips
isBigEndian
;
# Override `system` so that packages can get the system of the host
# platform through `stdenv.system`. `system` is originally set to the
# build platform within the derivation above so that Nix directs the build
# to correct type of machine.
inherit (hostPlatform) system;
mkDerivation = mkDerivationFromStdenv stdenv;
inherit fetchurlBoot;
inherit overrides;
inherit cc hasCC;
# Convenience for doing some very basic shell syntax checking by parsing a script
# without running any commands. Because this will also skip `shopt -s extglob`
# commands and extglob affects the Bash parser, we enable extglob always.
shellDryRun = "${stdenv.shell} -n -O extglob";
tests = {
succeedOnFailure = import ../tests/succeedOnFailure.nix { inherit stdenv; };
};
passthru.tests = lib.warn "Use `stdenv.tests` instead. `passthru` is a `mkDerivation` detail." stdenv.tests;
}
# Propagate any extra attributes. For instance, we use this to
# "lift" packages like curl from the final stdenv for Linux to
# all-packages.nix for that platform (meaning that it has a line
# like curl = if stdenv ? curl then stdenv.curl else ...).
// extraAttrs
);
in
stdenv-overridable

View File

@@ -0,0 +1,954 @@
{ lib, config }:
stdenv:
let
# Lib attributes are inherited to the lexical scope for performance reasons.
inherit (lib)
any
assertMsg
attrNames
boolToString
concatLists
concatMap
concatMapStrings
concatStringsSep
elem
elemAt
extendDerivation
filter
findFirst
getDev
head
imap1
isAttrs
isBool
isDerivation
isInt
isList
isString
mapAttrs
mapNullable
optional
optionalAttrs
optionalString
optionals
pipe
remove
splitString
subtractLists
toFunction
unique
zipAttrsWith
;
inherit (import ../../build-support/lib/cmake.nix { inherit lib stdenv; }) makeCMakeFlags;
inherit (import ../../build-support/lib/meson.nix { inherit lib stdenv; }) makeMesonFlags;
/**
This function creates a derivation, and returns it in the form of a [package attribute set](https://nix.dev/manual/nix/latest/glossary#package-attribute-set)
that refers to the derivation's outputs.
`mkDerivation` takes many argument attributes, most of which affect the derivation environment,
but [`meta`](#chap-meta) and [`passthru`](#var-stdenv-passthru) only directly affect package attributes.
The `mkDerivation` argument attributes can be made to refer to one another by passing a function to `mkDerivation`.
See [Fixed-point argument of `mkDerivation`](#mkderivation-recursive-attributes).
Reference documentation see: https://nixos.org/manual/nixpkgs/stable/#sec-using-stdenv
:::{.note}
This is used as the fundamental building block of most other functions in Nixpkgs for creating derivations.
Most arguments are also passed through to the underlying call of [`derivation`](https://nixos.org/manual/nix/stable/language/derivations).
:::
*/
mkDerivation = fnOrAttrs: makeDerivationExtensible (toFunction fnOrAttrs);
checkMeta = import ./check-meta.nix {
inherit lib config;
# Nix itself uses the `system` field of a derivation to decide where
# to build it. This is a bit confusing for cross compilation.
inherit (stdenv) hostPlatform;
};
# Based off lib.makeExtensible, with modifications:
makeDerivationExtensible =
rattrs:
let
# NOTE: The following is a hint that will be printed by the Nix cli when
# encountering an infinite recursion. It must not be formatted into
# 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 overrideAttrs; });
# ^^^^
/**
Override the attributes that were passed to `mkDerivation` in order to generate this derivation.
*/
# NOTE: the above documentation had to be duplicated in `lib/customisation.nix`: `makeOverridable`.
overrideAttrs =
f0:
let
extends' =
overlay: f:
(
final:
let
prev = f final;
thisOverlay = overlay final prev;
warnForBadVersionOverride = (
thisOverlay ? version
&& prev ? version
# We could check that the version is actually distinct, but that
# would probably just delay the inevitable, or preserve tech debt.
# && 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}"
} 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>"}.
This is most likely not what you want. In order to properly change the version of a package, override
both the `version` and `src` attributes:
hello.overrideAttrs (oldAttrs: rec {
version = "1.0.0";
src = pkgs.fetchurl {
url = "mirror://gnu/hello/hello-''${version}.tar.gz";
hash = "...";
};
})
(To silence this warning, set `__intentionallyOverridingVersion = true` in your `overrideAttrs` call.)
'' (prev // (removeAttrs thisOverlay [ "__intentionallyOverridingVersion" ]))
);
in
makeDerivationExtensible (extends' (lib.toExtension f0) rattrs);
finalPackage = mkDerivationSimple overrideAttrs args;
in
finalPackage;
knownHardeningFlags = [
"bindnow"
"format"
"fortify"
"fortify3"
"strictflexarrays1"
"strictflexarrays3"
"shadowstack"
"nostrictaliasing"
"pacret"
"pic"
"pie"
"relro"
"stackprotector"
"glibcxxassertions"
"stackclashprotection"
"strictoverflow"
"trivialautovarinit"
"zerocallusedregs"
];
removedOrReplacedAttrNames = [
"checkInputs"
"installCheckInputs"
"nativeCheckInputs"
"nativeInstallCheckInputs"
"__contentAddressed"
"__darwinAllowLocalNetworking"
"__impureHostDeps"
"__propagatedImpureHostDeps"
"sandboxProfile"
"propagatedSandboxProfile"
"disallowedReferences"
"disallowedRequisites"
"allowedReferences"
"allowedRequisites"
"allowedImpureDLLs"
];
inherit (stdenv)
hostPlatform
buildPlatform
targetPlatform
extraNativeBuildInputs
extraBuildInputs
extraSandboxProfile
__extraImpureHostDeps
;
stdenvHasCC = stdenv.hasCC;
stdenvShell = stdenv.shell;
buildPlatformSystem = buildPlatform.system;
buildIsDarwin = buildPlatform.isDarwin;
inherit (hostPlatform)
isLinux
isDarwin
isWindows
isCygwin
isOpenBSD
isStatic
isMusl
;
# Target is not included by default because most programs don't care.
# Including it then would cause needless mass rebuilds.
#
# TODO(@Ericson2314): Make [ "build" "host" ] always the default / resolve #87909
useDefaultConfigurePlatforms = hostPlatform != buildPlatform || config.configurePlatformsByDefault;
defaultConfigurePlatforms = optionals useDefaultConfigurePlatforms [
"build"
"host"
];
buildPlatformConfigureFlag = "--build=${buildPlatform.config}";
hostPlatformConfigureFlag = "--host=${hostPlatform.config}";
targetPlatformConfigureFlag = "--target=${targetPlatform.config}";
defaultConfigurePlatformsFlags = optionals useDefaultConfigurePlatforms [
buildPlatformConfigureFlag
hostPlatformConfigureFlag
];
# TODO(@Ericson2314): Make always true and remove / resolve #178468
defaultStrictDeps = if config.strictDepsByDefault then true else hostPlatform != buildPlatform;
canExecuteHostOnBuild = buildPlatform.canExecute hostPlatform;
defaultHardeningFlags =
(if stdenvHasCC then stdenv.cc else { }).defaultHardeningFlags or
# fallback safe-ish set of flags
(
if isOpenBSD && isStatic then
knownHardeningFlags # Need pie, in fact
else
remove "pie" knownHardeningFlags
);
stdenvHostSuffix = optionalString (hostPlatform != buildPlatform) "-${hostPlatform.config}";
stdenvStaticMarker = optionalString isStatic "-static";
userHook = config.stdenv.userHook or null;
requiredSystemFeaturesShouldBeSet =
buildPlatform ? gcc.arch
&& !(
buildPlatform.isAarch64
&& (
# `aarch64-darwin` sets `{gcc.arch = "armv8.3-a+crypto+sha2+...";}`
buildPlatform.isDarwin
||
# `aarch64-linux` has `{ gcc.arch = "armv8-a"; }` set by default
buildPlatform.gcc.arch == "armv8-a"
)
);
gccArchFeature = [ "gccarch-${buildPlatform.gcc.arch}" ];
# Turn a derivation into its outPath without a string context attached.
# See the comment at the usage site.
unsafeDerivationToUntrackedOutpath =
drv:
if isDerivation drv && (!drv.__contentAddressed or false) then
builtins.unsafeDiscardStringContext drv.outPath
else
drv;
makeOutputChecks =
attrs:
# 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
{
${if (attrs ? disallowedReferences) then "disallowedReferences" else null} =
map unsafeDerivationToUntrackedOutpath attrs.disallowedReferences;
${if (attrs ? disallowedRequisites) then "disallowedRequisites" else null} =
map unsafeDerivationToUntrackedOutpath attrs.disallowedRequisites;
${if (attrs ? allowedReferences) then "allowedReferences" else null} =
mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedReferences;
${if (attrs ? allowedRequisites) then "allowedRequisites" else null} =
mapNullable unsafeDerivationToUntrackedOutpath attrs.allowedRequisites;
};
makeDerivationArgument =
# `makeDerivationArgument` is responsible for the `mkDerivation` arguments that
# affect the actual derivation, excluding a few behaviors that are not
# essential, and specific to `mkDerivation`: `env`, `cmakeFlags`, `mesonFlags`.
#
# See also:
#
# * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
# Details on how to use this mkDerivation function
#
# * https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations
# 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 ? [ ],
nativeCheckInputs ? [ ],
nativeInstallCheckInputs ? [ ],
# Configure Phase
configureFlags ? [ ],
configurePlatforms ? defaultConfigurePlatforms,
# TODO(@Ericson2314): Make unconditional / resolve #33599
# Check phase
doCheck ? config.doCheckByDefault or false,
# TODO(@Ericson2314): Make unconditional / resolve #33599
# InstallCheck phase
doInstallCheck ? config.doCheckByDefault or false,
# TODO(@Ericson2314): Make always true and remove / resolve #178468
strictDeps ? defaultStrictDeps,
enableParallelBuilding ? config.enableParallelBuildingByDefault,
separateDebugInfo ? false,
outputs ? [ "out" ],
__darwinAllowLocalNetworking ? false,
__impureHostDeps ? [ ],
__propagatedImpureHostDeps ? [ ],
sandboxProfile ? "",
propagatedSandboxProfile ? "",
allowedImpureDLLs ? [ ],
hardeningEnable ? [ ],
hardeningDisable ? [ ],
patches ? [ ],
__contentAddressed ?
(!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,
...
}@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`.
doCheck' = doCheck && canExecuteHostOnBuild;
doInstallCheck' = doInstallCheck && canExecuteHostOnBuild;
separateDebugInfo' =
let
actualValue = separateDebugInfo && isLinux;
conflictingOption =
attrs ? "disallowedReferences"
|| attrs ? "disallowedRequisites"
|| attrs ? "allowedRequisites"
|| attrs ? "allowedReferences";
in
if actualValue && conflictingOption && !__structuredAttrs then
throw "separateDebugInfo = true in ${
attrs.pname or "mkDerivation argument"
} requires __structuredAttrs if {dis,}allowedRequisites or {dis,}allowedReferences is set"
else
actualValue;
outputs' = outputs ++ optional separateDebugInfo' "debug";
noNonNativeDeps =
builtins.length (
depsBuildTarget
++ depsBuildTargetPropagated
++ depsHostHost
++ depsHostHostPropagated
++ buildInputs
++ propagatedBuildInputs
++ depsTargetTarget
++ depsTargetTargetPropagated
) == 0;
dontAddHostSuffix = attrs ? outputHash && !noNonNativeDeps || !stdenvHasCC;
concretizeFlagImplications =
flag: impliesFlags: list:
if any (x: x == flag) list then (list ++ impliesFlags) else list;
hardeningDisable' = unique (
pipe hardeningDisable [
# disabling fortify implies fortify3 should also be disabled
(concretizeFlagImplications "fortify" [ "fortify3" ])
# disabling strictflexarrays1 implies strictflexarrays3 should also be disabled
(concretizeFlagImplications "strictflexarrays1" [ "strictflexarrays3" ])
]
);
enabledHardeningOptions =
if builtins.elem "all" hardeningDisable' then
[ ]
else
subtractLists hardeningDisable' (defaultHardeningFlags ++ hardeningEnable);
# hardeningDisable additionally supports "all".
erroneousHardeningFlags = subtractLists knownHardeningFlags (
hardeningEnable ++ remove "all" hardeningDisable
);
checkDependencyList = checkDependencyList' [ ];
checkDependencyList' =
positions: name: deps:
imap1 (
index: dep:
if dep == null || isDerivation dep || builtins.isString dep || builtins.isPath dep then
dep
else if isList dep then
checkDependencyList' ([ index ] ++ positions) name dep
else
throw "Dependency is not of a valid type: ${
concatMapStrings (ix: "element ${toString ix} of ") ([ index ] ++ positions)
}${name} for ${attrs.name or attrs.pname}"
) deps;
in
if builtins.length erroneousHardeningFlags != 0 then
abort (
"mkDerivation was called with unsupported hardening flags: "
+ lib.generators.toPretty { } {
inherit
erroneousHardeningFlags
hardeningDisable
hardeningEnable
knownHardeningFlags
;
}
)
else
let
doCheck = doCheck';
doInstallCheck = doInstallCheck';
buildInputs' =
buildInputs ++ optionals doCheck checkInputs ++ optionals doInstallCheck installCheckInputs;
nativeBuildInputs' =
nativeBuildInputs
++ optional separateDebugInfo' ../../build-support/setup-hooks/separate-debug-info.sh
++ optional isWindows ../../build-support/setup-hooks/win-dll-link.sh
++ optional isCygwin ../../build-support/setup-hooks/cygwin-dll-link.sh
++ optionals doCheck nativeCheckInputs
++ optionals doInstallCheck nativeInstallCheckInputs;
outputs = outputs';
dependencies = [
[
(map (drv: getDev drv.__spliced.buildBuild or drv) (
checkDependencyList "depsBuildBuild" depsBuildBuild
))
(map (drv: getDev drv.__spliced.buildHost or drv) (
checkDependencyList "nativeBuildInputs" nativeBuildInputs'
))
(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) (
checkDependencyList "depsTargetTarget" depsTargetTarget
))
]
];
propagatedDependencies = [
[
(map (drv: getDev drv.__spliced.buildBuild or drv) (
checkDependencyList "depsBuildBuildPropagated" depsBuildBuildPropagated
))
(map (drv: getDev drv.__spliced.buildHost or drv) (
checkDependencyList "propagatedNativeBuildInputs" propagatedNativeBuildInputs
))
(map (drv: getDev drv.__spliced.buildTarget or drv) (
checkDependencyList "depsBuildTargetPropagated" depsBuildTargetPropagated
))
]
[
(map (drv: getDev drv.__spliced.hostHost or drv) (
checkDependencyList "depsHostHostPropagated" depsHostHostPropagated
))
(map (drv: getDev drv.__spliced.hostTarget or drv) (
checkDependencyList "propagatedBuildInputs" propagatedBuildInputs
))
]
[
(map (drv: getDev drv.__spliced.targetTarget or drv) (
checkDependencyList "depsTargetTargetPropagated" depsTargetTargetPropagated
))
]
];
derivationArg =
removeAttrs attrs removedOrReplacedAttrNames
// {
${if (attrs ? name || (attrs ? pname && attrs ? version)) then "name" else null} =
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 = optionalString (!dontAddHostSuffix) stdenvHostSuffix;
# 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 = stdenvStaticMarker;
in
lib.strings.sanitizeDerivationName (
if attrs ? name then
attrs.name + hostSuffix
else
# we cannot coerce null to a string below
assert assertMsg (
attrs ? version && attrs.version != null
) "The `version` attribute cannot be null.";
"${attrs.pname}${staticMarker}${hostSuffix}-${attrs.version}"
);
builder = attrs.realBuilder or stdenvShell;
args =
attrs.args or [
"-e"
./source-stdenv.sh
(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 `buildPlatform` matches Nix's degree of specificity.
# exactly.
system = buildPlatformSystem;
inherit userHook;
__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;
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;
# This parameter is sometimes a string, sometimes null, and sometimes a list, yuck
configureFlags =
configureFlags
++ (
if configurePlatforms == defaultConfigurePlatforms then
defaultConfigurePlatformsFlags
else
optional (elem "build" configurePlatforms) buildPlatformConfigureFlag
++ optional (elem "host" configurePlatforms) hostPlatformConfigureFlag
++ optional (elem "target" configurePlatforms) targetPlatformConfigureFlag
);
inherit patches;
inherit doCheck doInstallCheck;
inherit outputs;
# When the derivations is content addressed provide default values
# for outputHashMode and outputHashAlgo because most people won't
# care about these anyways
${if __contentAddressed then "__contentAddressed" else null} = __contentAddressed;
${if __contentAddressed then "outputHashAlgo" else null} = attrs.outputHashAlgo or "sha256";
${if __contentAddressed then "outputHashMode" else null} = attrs.outputHashMode or "recursive";
${if enableParallelBuilding then "enableParallelBuilding" else null} = enableParallelBuilding;
${if enableParallelBuilding then "enableParallelChecking" else null} =
attrs.enableParallelChecking or true;
${if enableParallelBuilding then "enableParallelInstalling" else null} =
attrs.enableParallelInstalling or true;
${
if (hardeningDisable != [ ] || hardeningEnable != [ ] || isMusl) then
"NIX_HARDENING_ENABLE"
else
null
} =
builtins.concatStringsSep " " enabledHardeningOptions;
# TODO: remove platform condition
# Enabling this check could be a breaking change as it requires to edit nix.conf
# NixOS module already sets gccarch, unsure of nix installers and other distributions
${if requiredSystemFeaturesShouldBeSet then "requiredSystemFeatures" else null} =
attrs.requiredSystemFeatures or [ ] ++ gccArchFeature;
}
// optionalAttrs buildIsDarwin (
let
allDependencies = concatLists (concatLists dependencies);
allPropagatedDependencies = concatLists (concatLists propagatedDependencies);
computedSandboxProfile = concatMap (input: input.__propagatedSandboxProfile or [ ]) (
extraNativeBuildInputs ++ extraBuildInputs ++ allDependencies
);
computedPropagatedSandboxProfile = concatMap (
input: input.__propagatedSandboxProfile or [ ]
) allPropagatedDependencies;
computedImpureHostDeps = unique (
concatMap (input: input.__propagatedImpureHostDeps or [ ]) (
extraNativeBuildInputs ++ extraBuildInputs ++ allDependencies
)
);
computedPropagatedImpureHostDeps = unique (
concatMap (input: input.__propagatedImpureHostDeps or [ ]) allPropagatedDependencies
);
in
{
inherit __darwinAllowLocalNetworking;
# TODO: remove `unique` once nix has a list canonicalization primitive
__sandboxProfile =
let
profiles = [
extraSandboxProfile
]
++ computedSandboxProfile
++ computedPropagatedSandboxProfile
++ [
propagatedSandboxProfile
sandboxProfile
];
final = concatStringsSep "\n" (filter (x: x != "") (unique profiles));
in
final;
__propagatedSandboxProfile = unique (
computedPropagatedSandboxProfile ++ [ propagatedSandboxProfile ]
);
__impureHostDeps =
computedImpureHostDeps
++ computedPropagatedImpureHostDeps
++ __propagatedImpureHostDeps
++ __impureHostDeps
++ __extraImpureHostDeps
++ [
"/dev/zero"
"/dev/random"
"/dev/urandom"
"/bin/sh"
];
__propagatedImpureHostDeps = computedPropagatedImpureHostDeps ++ __propagatedImpureHostDeps;
}
)
// optionalAttrs (isWindows || isCygwin) (
let
dlls =
allowedImpureDLLs
++ lib.optionals isCygwin [
"KERNEL32.dll"
"cygwin1.dll"
];
in
{
allowedImpureDLLs = if dlls != [ ] then dlls else null;
}
)
// (
if !__structuredAttrs then
makeOutputChecks attrs
else
{
outputChecks = builtins.listToAttrs (
map (name: {
inherit name;
value =
let
raw = zipAttrsWith (_: builtins.concatLists) [
(makeOutputChecks attrs)
(makeOutputChecks attrs.outputChecks.${name} or { })
];
in
# separateDebugInfo = true will put all sorts of files in
# the debug output which could carry references, but
# that's "normal". Notably it symlinks to the source.
# So disable reference checking for the debug output
if separateDebugInfo' && name == "debug" then
removeAttrs raw [
"allowedReferences"
"allowedRequisites"
"disallowedReferences"
"disallowedRequisites"
]
else
raw;
}) outputs
);
}
);
in
derivationArg;
mkDerivationSimple =
overrideAttrs:
# `mkDerivation` wraps the builtin `derivation` function to
# produce derivations that use this stdenv and its shell.
#
# Internally, it delegates most of its behavior to `makeDerivationArgument`,
# except for the `env`, `cmakeFlags`, and `mesonFlags` attributes, as well
# as the attributes `meta` and `passthru` that affect [package attributes],
# and not the derivation itself.
#
# See also:
#
# * https://nixos.org/nixpkgs/manual/#sec-using-stdenv
# Details on how to use this mkDerivation function
#
# * https://nixos.org/manual/nix/stable/expressions/derivations.html#derivations
# Explanation about derivations in general
#
# * [package attributes]: https://nixos.org/manual/nix/stable/glossary#package-attribute-set
{
# Configure Phase
cmakeFlags ? [ ],
mesonFlags ? [ ],
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
),
# Experimental. For simple packages mostly just works,
# but for anything complex, be prepared to debug if enabling.
__structuredAttrs ? config.structuredAttrsByDefault or false,
env ? { },
...
}@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
mainProgram = meta.mainProgram or null;
env' = env // lib.optionalAttrs (mainProgram != null) { NIX_MAIN_PROGRAM = mainProgram; };
derivationArg = makeDerivationArgument (
removeAttrs attrs [
"meta"
"passthru"
"pos"
"env"
]
// lib.optionalAttrs __structuredAttrs { env = checkedEnv; }
// {
cmakeFlags = makeCMakeFlags attrs;
mesonFlags = makeMesonFlags attrs;
}
);
meta = checkMeta.commonMeta {
inherit validity attrs pos;
references =
attrs.nativeBuildInputs or [ ]
++ attrs.buildInputs or [ ]
++ attrs.propagatedNativeBuildInputs or [ ]
++ attrs.propagatedBuildInputs or [ ];
};
validity = checkMeta.assertValidity { inherit meta attrs; };
checkedEnv =
let
overlappingNames = attrNames (builtins.intersectAttrs env' derivationArg);
prettyPrint = lib.generators.toPretty { };
makeError =
name:
" - ${name}: in `env`: ${prettyPrint env'.${name}}; in derivation arguments: ${
prettyPrint derivationArg.${name}
}";
errors = lib.concatMapStringsSep "\n" makeError 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.";
assert assertMsg (overlappingNames == [ ])
"The `env` attribute set cannot contain any attributes passed to derivation. The following attributes are overlapping:\n${errors}";
mapAttrs (
n: v:
assert assertMsg (isString v || isBool v || isInt v || 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';
# 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.
deleteFixedOutputRelatedAttrs = lib.flip removeAttrs [
"outputHashAlgo"
"outputHash"
"outputHashMode"
];
in
extendDerivation validity.handled (
{
# 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 (
deleteFixedOutputRelatedAttrs 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 = stdenvShell;
# The builtin `declare -p` dumps all bash and 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). Using placeholder for $out works with
# and without structuredAttrs.
# This build script does not use setup.sh or stdenv, to keep
# the env most pristine. This gives us a very bare bones env,
# hence the extra/duplicated compatibility logic and "pure bash" style.
args = [
"-c"
''
out="${placeholder "out"}"
if [ -e "$NIX_ATTRS_SH_FILE" ]; then . "$NIX_ATTRS_SH_FILE"; fi
declare -p > $out
for var in $passAsFile; do
pathVar="''${var}Path"
printf "%s" "$(< "''${!pathVar}")" >> $out
done
''
];
}
// (
let
sharedOutputChecks = {
# 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 = [ ];
};
in
if __structuredAttrs then
{
outputChecks.out = sharedOutputChecks;
}
else
sharedOutputChecks
)
);
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 // checkedEnv));
in
{
inherit mkDerivation;
}

View File

@@ -0,0 +1,98 @@
{ lib }:
# Simple internal type checks for meta.
# This file is not a stable interface and may be changed arbitrarily.
#
# TODO: add a method to the module system types
# see https://github.com/NixOS/nixpkgs/pull/273935#issuecomment-1854173100
let
inherit (builtins)
isString
isInt
isAttrs
isList
all
any
attrValues
isFunction
isBool
concatStringsSep
isFloat
;
isTypeDef = t: isAttrs t && t ? name && isString t.name && t ? verify && isFunction t.verify;
in
lib.fix (self: {
string = {
name = "string";
verify = isString;
};
str = self.string; # Type alias
any = {
name = "any";
verify = _: true;
};
int = {
name = "int";
verify = isInt;
};
float = {
name = "float";
verify = isFloat;
};
bool = {
name = "bool";
verify = isBool;
};
attrs = {
name = "attrs";
verify = isAttrs;
};
list = {
name = "list";
verify = isList;
};
attrsOf =
t:
assert isTypeDef t;
let
inherit (t) verify;
in
{
name = "attrsOf<${t.name}>";
verify =
# attrsOf<any> can be optimised to just isAttrs
if t == self.any then isAttrs else attrs: isAttrs attrs && all verify (attrValues attrs);
};
listOf =
t:
assert isTypeDef t;
let
inherit (t) verify;
in
{
name = "listOf<${t.name}>";
verify =
# listOf<any> can be optimised to just isList
if t == self.any then isList else v: isList v && all verify v;
};
union =
types:
assert all isTypeDef types;
let
# Store a list of functions so we don't have to pay the cost of attrset lookups at runtime.
funcs = map (t: t.verify) types;
in
{
name = "union<${concatStringsSep "," (map (t: t.name) types)}>";
verify = v: any (func: func v) funcs;
};
})

1811
pkgs/stdenv/generic/setup.sh Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
if [ -e "$NIX_ATTRS_SH_FILE" ]; then . "$NIX_ATTRS_SH_FILE"; fi
source "$stdenv/setup"
source "$1"