2023-04-09 10:34:52 +00:00
{
# The list of systems supported by nixpkgs and hydra
defaultSystems ? [
" a a r c h 6 4 - l i n u x "
" a a r c h 6 4 - d a r w i n "
" x 8 6 _ 6 4 - d a r w i n "
" x 8 6 _ 6 4 - l i n u x "
]
} :
let
2023-04-09 10:36:57 +00:00
inherit defaultSystems ;
2023-04-09 10:34:52 +00:00
# List of all systems defined in nixpkgs
# Keep in sync with nixpkgs wit the following command:
2023-04-09 10:45:24 +00:00
# $ nix-instantiate --json --eval --expr "with import <nixpkgs> {}; lib.platforms.all" | jq 'sort' | sed 's!,!!' > allSystems.nix
allSystems = import ./allSystems.nix ;
2023-04-09 10:34:52 +00:00
# A map from system to system. It's useful to detect typos.
#
# Instead of typing `"x86_64-linux"`, type `flake-utils.lib.system.x86_64-linux`
# and get an error back if you used a dash instead of an underscore.
system =
builtins . listToAttrs
( map ( system : { name = system ; value = system ; } ) allSystems ) ;
# eachSystem using defaultSystems
eachDefaultSystem = eachSystem defaultSystems ;
2024-09-11 17:42:06 +00:00
# Builds a map from <attr>=value to <attr>.<system>=value for each system.
2024-09-11 17:37:38 +00:00
eachSystem =
systems : f :
2024-09-11 17:45:32 +00:00
builtins . foldl'
(
# Merge outputs for each system.
2024-09-11 17:37:38 +00:00
attrs : system :
2023-04-09 10:34:52 +00:00
let
ret = f system ;
in
2024-09-11 17:45:32 +00:00
builtins . foldl' (
attrs : key :
attrs
// {
$ { key } = ( attrs . ${ key } or { } ) // {
$ { system } = ret . ${ key } ;
} ;
}
) attrs ( builtins . attrNames ret )
)
{ }
(
2024-09-16 13:18:48 +00:00
if
! builtins ? currentSystem || builtins . elem builtins . currentSystem systems
then
systems
else
2024-09-11 17:45:32 +00:00
# Add the current system if the --impure flag is used.
2024-09-16 13:18:48 +00:00
systems ++ [ builtins . currentSystem ]
2024-09-11 17:45:32 +00:00
) ;
2023-04-09 10:34:52 +00:00
# eachSystemMap using defaultSystems
eachDefaultSystemMap = eachSystemMap defaultSystems ;
2023-04-09 10:36:57 +00:00
2023-04-09 10:34:52 +00:00
# Builds a map from <attr>=value to <system>.<attr> = value.
eachSystemMap = systems : f : builtins . listToAttrs ( builtins . map ( system : { name = system ; value = f system ; } ) systems ) ;
# Nix flakes insists on having a flat attribute set of derivations in
# various places like the `packages` and `checks` attributes.
#
# This function traverses a tree of attributes (by respecting
# recurseIntoAttrs) and only returns their derivations, with a flattened
# key-space.
#
# Eg:
#
# flattenTree { hello = pkgs.hello; gitAndTools = pkgs.gitAndTools };
#
# Returns:
#
# {
# hello = «derivation»;
# "gitAndTools/git" = «derivation»;
# "gitAndTools/hub" = «derivation»;
# # ...
# }
flattenTree = tree : import ./flattenTree.nix tree ;
# Nix check functionality validates packages for various conditions, like if
# they build for any given platform or if they are marked broken.
#
# This function filters a flattend package set for conditinos that
# would *trivially* break `nix flake check`. It does not flatten a tree and it
# does not implement advanced package validation checks.
#
# Eg:
#
# filterPackages "x86_64-linux" {
# hello = pkgs.hello;
# "gitAndTools/git" = pkgs.gitAndTools // {meta.broken = true;};
# };
#
# Returns:
#
# {
# hello = «derivation»;
# }
filterPackages = import ./filterPackages.nix { inherit allSystems ; } ;
2023-06-25 16:15:56 +00:00
# Meld merges subflakes using common inputs. Useful when you want
# to split up a large flake with many different components into more
# manageable parts.
#
# For example:
#
# {
# inputs = {
# flutils.url = "github:numtide/flake-utils";
# nixpkgs.url = "github:nixos/nixpkgs";
# };
# outputs = inputs@{ flutils, ... }: flutils.lib.meld inputs [
# ./nix/packages
# ./nix/hardware
# ./nix/overlays
# # ...
# ];
# }
#
# Where ./nix/packages/default.nix looks like just the output
# portion of a flake.
#
# { flutils, nixpkgs, ... }: flutils.lib.eachDefaultSystem (system:
# let pkgs = import nixpkgs { inherit system; }; in
# {
# packages = {
# foo = ...;
# bar = ...;
# # ...
# };
# }
# )
#
# You can also use meld within the subflakes to further subdivide
# your flake into a tree like structure. For example,
# ./nix/hardware/default.nix might look like:
#
# inputs@{ flutils, ... }: flutils.lib.meld inputs [
# ./foobox.nix
# ./barbox.nix
# ]
meld = let
# Pulled from nixpkgs.lib
recursiveUpdateUntil =
# Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
pred :
# Left attribute set of the merge.
lhs :
# Right attribute set of the merge.
rhs :
let
f = attrPath :
builtins . zipAttrsWith ( n : values :
let here = attrPath ++ [ n ] ;
in if builtins . length values == 1
|| pred here ( builtins . elemAt values 1 ) ( builtins . head values ) then
builtins . head values
else
f here values ) ;
in f [ ] [ rhs lhs ] ;
# Pulled from nixpkgs.lib
recursiveUpdate =
# Left attribute set of the merge.
lhs :
# Right attribute set of the merge.
rhs :
recursiveUpdateUntil ( path : lhs : rhs : ! ( builtins . isAttrs lhs && builtins . isAttrs rhs ) ) lhs
rhs ;
in inputs :
builtins . foldl' ( output : subflake :
recursiveUpdate output ( import subflake inputs ) ) { } ;
2023-04-09 10:34:52 +00:00
# Returns the structure used by `nix app`
mkApp =
{ drv
, name ? drv . pname or drv . name
, exePath ? drv . passthru . exePath or " / b i n / ${ name } "
} :
{
type = " a p p " ;
program = " ${ drv } ${ exePath } " ;
} ;
# This function tries to capture a common flake pattern.
simpleFlake = import ./simpleFlake.nix { inherit lib defaultSystems ; } ;
# Helper functions for Nix evaluation
check-utils = import ./check-utils.nix ;
lib = {
inherit
allSystems
check-utils
defaultSystems
eachDefaultSystem
eachDefaultSystemMap
2024-09-11 18:17:58 +00:00
eachSystem
2023-04-09 10:34:52 +00:00
eachSystemMap
filterPackages
flattenTree
2023-06-25 16:15:56 +00:00
meld
2023-04-09 10:34:52 +00:00
mkApp
simpleFlake
system
;
} ;
in
lib