mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-26 15:44:20 +00:00
72f462bdba
The attrNamesOnly feature is used by pkgs/top-level/release-attrpaths-superset.nix to return a superset of all attributes that might be built by Hydra. Before this change it would include all attribute paths to derivations that could be found recursively, ignoring the recurseForDerivations and recurseForRelease attributes that control Hydra's recursion. This had the effect that it would end up with ~266000 attributes, most of which definitely won't be built by Hydra. We can remove those while staying true to the superset notion to end up with just ~97000, a reduction of ~63.6%! This also comes with an eval time reduction from 31.7s to 18.7s (-41.0%)! As an example, all derivations in pypy310Packages don't get included anymore, because it doesn't have a `.recurseForDerivations` set. As a nice side effect, with `--arg enableWarnings false`, no more warnings are printed, because things like `checkpointBuildTools.mkCheckpointedBuild` (which is deprecated) isn't being recursed to anymore.
209 lines
6.8 KiB
Nix
209 lines
6.8 KiB
Nix
{ supportedSystems
|
||
, system ? builtins.currentSystem
|
||
, packageSet ? (import ../..)
|
||
, scrubJobs ? true
|
||
, # Attributes passed to nixpkgs. Don't build packages marked as unfree.
|
||
nixpkgsArgs ? { config = { allowUnfree = false; inHydra = true; }; }
|
||
}:
|
||
|
||
let
|
||
lib = import ../../lib;
|
||
|
||
inherit (lib)
|
||
addMetaAttrs
|
||
any
|
||
derivations
|
||
filter
|
||
flip
|
||
genAttrs
|
||
getAttrFromPath
|
||
hydraJob
|
||
id
|
||
isDerivation
|
||
lists
|
||
maintainers
|
||
mapAttrs
|
||
mapAttrs'
|
||
mapAttrsRecursive
|
||
matchAttrs
|
||
meta
|
||
nameValuePair
|
||
platforms
|
||
recursiveUpdate
|
||
subtractLists
|
||
systems
|
||
;
|
||
|
||
pkgs = packageSet (recursiveUpdate { inherit system; config.allowUnsupportedSystem = true; } nixpkgsArgs);
|
||
|
||
hydraJob' = if scrubJobs then hydraJob else id;
|
||
|
||
|
||
/* !!! Hack: poor man's memoisation function. Necessary to prevent
|
||
Nixpkgs from being evaluated again and again for every
|
||
job/platform pair. */
|
||
mkPkgsFor = crossSystem: let
|
||
packageSet' = args: packageSet (args // { inherit crossSystem; } // nixpkgsArgs);
|
||
|
||
pkgs_x86_64_linux = packageSet' { system = "x86_64-linux"; };
|
||
pkgs_i686_linux = packageSet' { system = "i686-linux"; };
|
||
pkgs_aarch64_linux = packageSet' { system = "aarch64-linux"; };
|
||
pkgs_riscv64_linux = packageSet' { system = "riscv64-linux"; };
|
||
pkgs_aarch64_darwin = packageSet' { system = "aarch64-darwin"; };
|
||
pkgs_armv6l_linux = packageSet' { system = "armv6l-linux"; };
|
||
pkgs_armv7l_linux = packageSet' { system = "armv7l-linux"; };
|
||
pkgs_x86_64_darwin = packageSet' { system = "x86_64-darwin"; };
|
||
pkgs_x86_64_freebsd = packageSet' { system = "x86_64-freebsd"; };
|
||
pkgs_i686_freebsd = packageSet' { system = "i686-freebsd"; };
|
||
pkgs_i686_cygwin = packageSet' { system = "i686-cygwin"; };
|
||
pkgs_x86_64_cygwin = packageSet' { system = "x86_64-cygwin"; };
|
||
|
||
in system:
|
||
if system == "x86_64-linux" then pkgs_x86_64_linux
|
||
else if system == "i686-linux" then pkgs_i686_linux
|
||
else if system == "aarch64-linux" then pkgs_aarch64_linux
|
||
else if system == "riscv64-linux" then pkgs_riscv64_linux
|
||
else if system == "aarch64-darwin" then pkgs_aarch64_darwin
|
||
else if system == "armv6l-linux" then pkgs_armv6l_linux
|
||
else if system == "armv7l-linux" then pkgs_armv7l_linux
|
||
else if system == "x86_64-darwin" then pkgs_x86_64_darwin
|
||
else if system == "x86_64-freebsd" then pkgs_x86_64_freebsd
|
||
else if system == "i686-freebsd" then pkgs_i686_freebsd
|
||
else if system == "i686-cygwin" then pkgs_i686_cygwin
|
||
else if system == "x86_64-cygwin" then pkgs_x86_64_cygwin
|
||
else abort "unsupported system type: ${system}";
|
||
|
||
pkgsFor = pkgsForCross null;
|
||
|
||
|
||
# More poor man's memoisation
|
||
pkgsForCross = let
|
||
examplesByConfig = flip mapAttrs'
|
||
systems.examples
|
||
(_: crossSystem: nameValuePair crossSystem.config {
|
||
inherit crossSystem;
|
||
pkgsFor = mkPkgsFor crossSystem;
|
||
});
|
||
native = mkPkgsFor null;
|
||
in crossSystem: let
|
||
candidate = examplesByConfig.${crossSystem.config} or null;
|
||
in if crossSystem == null
|
||
then native
|
||
else if candidate != null && matchAttrs crossSystem candidate.crossSystem
|
||
then candidate.pkgsFor
|
||
else mkPkgsFor crossSystem; # uncached fallback
|
||
|
||
|
||
# Given a list of 'meta.platforms'-style patterns, return the sublist of
|
||
# `supportedSystems` containing systems that matches at least one of the given
|
||
# patterns.
|
||
#
|
||
# This is written in a funny way so that we only elaborate the systems once.
|
||
supportedMatches = let
|
||
supportedPlatforms = map
|
||
(system: systems.elaborate { inherit system; })
|
||
supportedSystems;
|
||
in metaPatterns: let
|
||
anyMatch = platform:
|
||
any (meta.platformMatch platform) metaPatterns;
|
||
matchingPlatforms = filter anyMatch supportedPlatforms;
|
||
in map ({ system, ...}: system) matchingPlatforms;
|
||
|
||
|
||
assertTrue = bool:
|
||
if bool
|
||
then pkgs.runCommand "evaluated-to-true" {} "touch $out"
|
||
else pkgs.runCommand "evaluated-to-false" {} "false";
|
||
|
||
|
||
/* The working or failing mails for cross builds will be sent only to
|
||
the following maintainers, as most package maintainers will not be
|
||
interested in the result of cross building a package. */
|
||
crossMaintainers = [ ];
|
||
|
||
|
||
# Generate attributes for all supported systems.
|
||
forAllSystems = genAttrs supportedSystems;
|
||
|
||
|
||
# Generate attributes for all systems matching at least one of the given
|
||
# patterns
|
||
forMatchingSystems = metaPatterns: genAttrs (supportedMatches metaPatterns);
|
||
|
||
|
||
/* Build a package on the given set of platforms. The function `f'
|
||
is called for each supported platform with Nixpkgs for that
|
||
platform as an argument . We return an attribute set containing
|
||
a derivation for each supported platform, i.e. ‘{ x86_64-linux =
|
||
f pkgs_x86_64_linux; i686-linux = f pkgs_i686_linux; ... }’. */
|
||
testOn = testOnCross null;
|
||
|
||
|
||
/* Similar to the testOn function, but with an additional
|
||
'crossSystem' parameter for packageSet', defining the target
|
||
platform for cross builds. */
|
||
testOnCross = crossSystem: metaPatterns: f: forMatchingSystems metaPatterns
|
||
(system: hydraJob' (f (pkgsForCross crossSystem system)));
|
||
|
||
|
||
/* Given a nested set where the leaf nodes are lists of platforms,
|
||
map each leaf node to `testOn [platforms...] (pkgs:
|
||
pkgs.<attrPath>)'. */
|
||
mapTestOn = _mapTestOnHelper id null;
|
||
|
||
|
||
_mapTestOnHelper = f: crossSystem: mapAttrsRecursive
|
||
(path: metaPatterns: testOnCross crossSystem metaPatterns
|
||
(pkgs: f (getAttrFromPath path pkgs)));
|
||
|
||
/* Similar to the testOn function, but with an additional 'crossSystem'
|
||
* parameter for packageSet', defining the target platform for cross builds,
|
||
* and triggering the build of the host derivation. */
|
||
mapTestOnCross = _mapTestOnHelper
|
||
(addMetaAttrs { maintainers = crossMaintainers; });
|
||
|
||
|
||
/* Recursive for packages and apply a function to them */
|
||
recursiveMapPackages = f: mapAttrs (name: value:
|
||
if isDerivation value then
|
||
f value
|
||
else if value.recurseForDerivations or false || value.recurseForRelease or false then
|
||
recursiveMapPackages f value
|
||
else
|
||
[]
|
||
);
|
||
|
||
/* Gets the list of Hydra platforms for a derivation */
|
||
getPlatforms = drv:
|
||
drv.meta.hydraPlatforms
|
||
or (subtractLists (drv.meta.badPlatforms or [])
|
||
(drv.meta.platforms or supportedSystems));
|
||
|
||
/* Recursively map a (nested) set of derivations to an isomorphic
|
||
set of meta.platforms values. */
|
||
packagePlatforms = recursiveMapPackages getPlatforms;
|
||
|
||
in {
|
||
/* Common platform groups on which to test packages. */
|
||
inherit (platforms) unix linux darwin cygwin all;
|
||
|
||
inherit
|
||
assertTrue
|
||
forAllSystems
|
||
forMatchingSystems
|
||
hydraJob'
|
||
lib
|
||
mapTestOn
|
||
mapTestOnCross
|
||
recursiveMapPackages
|
||
getPlatforms
|
||
packagePlatforms
|
||
pkgs
|
||
pkgsFor
|
||
pkgsForCross
|
||
supportedMatches
|
||
testOn
|
||
testOnCross
|
||
;
|
||
}
|