haskell.nix/ci.nix
Hamish Mackenzie a443611ecf
Add evalSystem and evalPackages project args (#1546)
This adds a way to specify the `evalSystem` or `evalPackages` explicitly when calling the `project` functions.

Currently if we want to make a `flake` that supports multiple systems we have few options:

* Require builders for all the supported systems (even just for `nix flake show`).

* Pass `--impure` so that haskell.nix can see `builtins.currentSystem` to set up `pkgs.evalPackages` to use that.  Unfortunately this prevents nix from caching some of the work it does and often results in it recalculating for each supported system when it would otherwise be cached and take no time at all.

* Add an overlay to replace `evalPackages`.  This works, but it is not straight forward.

* Materialize the nix files for the project.

This change allows `evalSystem = "x86_64-linux";` to be passed telling `haskell.nix` to run `cabal` and `nix-tools` on that system.  The user will have to have a builder for that system, but does not need to have builders for the others (unless building outputs for them).
2022-07-28 20:03:05 +12:00

127 lines
7.1 KiB
Nix

# 'supportedSystems' restricts the set of systems that we will evaluate for. Useful when you're evaluating
# on a machine with e.g. no way to build the Darwin IFDs you need!
{ supportedSystems ? [ "x86_64-linux" "x86_64-darwin" ]
, ifdLevel ? 3
# Whether or not we are evaluating in restricted mode. This is true in Hydra, but not in Hercules.
, restrictEval ? false
, checkMaterialization ? false
, pkgs ? (import ./. {}).pkgs }:
let
inherit (import ./ci-lib.nix { inherit pkgs; }) dimension platformFilterGeneric filterAttrsOnlyRecursive;
inherit (pkgs.haskell-nix) sources;
nixpkgsVersions = {
"R2111" = "nixpkgs-2111";
"R2205" = "nixpkgs-2205";
"unstable" = "nixpkgs-unstable";
};
haskellNix = import ./default.nix { inherit checkMaterialization; };
nixpkgsArgs = haskellNix.nixpkgsArgs // {
# Needed for dwarf tests
config = haskellNix.nixpkgsArgs.config // {
permittedInsecurePackages = ["libdwarf-20210528" "libdwarf-20181024" "dwarfdump-20181024"];
};
};
compilerNixNames = nixpkgsName: nixpkgs: builtins.mapAttrs (compiler-nix-name: runTests: {
inherit runTests;
}) (
# GHC version to cache and whether to run the tests against them.
# This list of GHC versions should include everything for which we
# have a ./materialized/ghcXXX directory containing the materialized
# cabal-install and nix-tools plans. When removing a ghc version
# from here (so that is no longer cached) also remove ./materialized/ghcXXX.
# Update supported-ghc-versions.md to reflect any changes made here.
nixpkgs.lib.optionalAttrs (nixpkgsName == "R2111") {
ghc865 = false;
ghc8107 = true;
} // nixpkgs.lib.optionalAttrs (nixpkgsName == "R2205") {
ghc865 = false;
ghc8107 = true;
} // nixpkgs.lib.optionalAttrs (nixpkgsName == "unstable") {
ghc865 = false;
ghc884 = false; # Native version is used to boot 9.0.1
ghc8107 = true;
ghc902 = true;
ghc923 = true;
});
systems = nixpkgsName: nixpkgs: compiler-nix-name: nixpkgs.lib.genAttrs (
nixpkgs.lib.filter (v:
# We have less x86_64-darwin build capacity so build fewer GhC versions
(v != "x86_64-darwin" || (
!__elem compiler-nix-name ["ghc8104" "ghc810420210212" "ghc8105" "ghc8106" "ghc901" "ghc921" "ghc922"]))
&&
# aarch64-darwin requires ghc 8.10.7
(v != "aarch64-darwin" || (
!__elem compiler-nix-name ["ghc865" "ghc884" "ghc8104" "ghc810420210212" "ghc8105" "ghc8106" "ghc901" "ghc921" "ghc922"]))
&&
# aarch64-linux requires ghc 8.8.4
(v != "aarch64-linux" || (
!__elem compiler-nix-name ["ghc865" "ghc8104" "ghc810420210212" "ghc8105" "ghc8106" "ghc901" "ghc921" "ghc922"]
))) supportedSystems) (v: v);
crossSystems = nixpkgsName: nixpkgs: compiler-nix-name: system:
# We need to use the actual nixpkgs version we're working with here, since the values
# of 'lib.systems.examples' are not understood between all versions
let lib = nixpkgs.lib;
in lib.optionalAttrs (nixpkgsName == "unstable"
&& ((system == "x86_64-linux" && __elem compiler-nix-name ["ghc865" "ghc884" "ghc8107"])
|| (system == "x86_64-darwin" && __elem compiler-nix-name ["ghc8107"]))) {
inherit (lib.systems.examples) ghcjs;
} // lib.optionalAttrs (nixpkgsName == "unstable"
&& ((system == "x86_64-linux" && __elem compiler-nix-name ["ghc8107" "ghc902" "ghc923"])
|| (system == "x86_64-darwin" && __elem compiler-nix-name []))) { # TODO add ghc versions when we have more darwin build capacity
inherit (lib.systems.examples) mingwW64;
} // lib.optionalAttrs (system == "x86_64-linux" && nixpkgsName == "unstable" && __elem compiler-nix-name ["ghc8107" "ghc902" "ghc922" "ghc923"]) {
# Musl cross only works on linux
# aarch64 cross only works on linux
inherit (lib.systems.examples) musl64 aarch64-multiplatform;
};
isDisabled = d: d.meta.disabled or false;
in
dimension "Nixpkgs version" nixpkgsVersions (nixpkgsName: nixpkgs-pin:
let pinnedNixpkgsSrc = sources.${nixpkgs-pin};
evalPackages = import pinnedNixpkgsSrc nixpkgsArgs;
in dimension "GHC version" (compilerNixNames nixpkgsName evalPackages) (compiler-nix-name: {runTests}:
dimension "System" (systems nixpkgsName evalPackages compiler-nix-name) (systemName: system:
let pkgs = import pinnedNixpkgsSrc (nixpkgsArgs // { inherit system; });
build = import ./build.nix { inherit pkgs evalPackages ifdLevel compiler-nix-name; };
platformFilter = platformFilterGeneric pkgs system;
in filterAttrsOnlyRecursive (_: v: platformFilter v && !(isDisabled v)) ({
# Native builds
# TODO: can we merge this into the general case by picking an appropriate "cross system" to mean native?
native = pkgs.recurseIntoAttrs ({
roots = pkgs.haskell-nix.roots' compiler-nix-name ifdLevel;
ghc = pkgs.buildPackages.haskell-nix.compiler."${compiler-nix-name}";
} // pkgs.lib.optionalAttrs runTests {
inherit (build) tests tools maintainer-scripts maintainer-script-cache;
} // pkgs.lib.optionalAttrs (ifdLevel >= 1) {
iserv-proxy = pkgs.ghc-extra-projects."${compiler-nix-name}".getComponent "iserv-proxy:exe:iserv-proxy";
} // pkgs.lib.optionalAttrs (ifdLevel >= 3) {
hello = (pkgs.haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2"; inherit evalPackages compiler-nix-name; }).getComponent "exe:hello";
});
}
//
dimension "Cross system" (crossSystems nixpkgsName evalPackages compiler-nix-name system) (crossSystemName: crossSystem:
# Cross builds
let pkgs = import pinnedNixpkgsSrc (nixpkgsArgs // { inherit system crossSystem; });
build = import ./build.nix { inherit pkgs evalPackages ifdLevel compiler-nix-name; };
in pkgs.recurseIntoAttrs (pkgs.lib.optionalAttrs (ifdLevel >= 1) ({
roots = pkgs.haskell-nix.roots' compiler-nix-name ifdLevel;
ghc = pkgs.buildPackages.haskell-nix.compiler."${compiler-nix-name}";
# TODO: look into cross compiling ghc itself
# ghc = pkgs.haskell-nix.compiler."${compiler-nix-name}";
# TODO: look into making tools work when cross compiling
# inherit (build) tools;
} // pkgs.lib.optionalAttrs (runTests && crossSystemName != "aarch64-multiplatform") {
# Tests are broken on aarch64 cross https://github.com/input-output-hk/haskell.nix/issues/513
inherit (build) tests;
}) // pkgs.lib.optionalAttrs (ifdLevel >= 2 && crossSystemName != "ghcjs") {
# GHCJS builds its own template haskell runner.
remote-iserv = pkgs.ghc-extra-projects."${compiler-nix-name}".getComponent "remote-iserv:exe:remote-iserv";
iserv-proxy = pkgs.ghc-extra-projects."${compiler-nix-name}".getComponent "iserv-proxy:exe:iserv-proxy";
} // pkgs.lib.optionalAttrs (ifdLevel >= 3) {
hello = (pkgs.haskell-nix.hackage-package { name = "hello"; version = "1.0.0.2"; inherit compiler-nix-name; }).getComponent "exe:hello";
})
))
)
)
)