2017-07-28 20:05:35 -04:00
{ lib }:
2009-11-19 17:30:21 +00:00
2023-11-27 12:14:54 +13:00
let
inherit ( builtins )
2024-12-20 20:57:46 +08:00
intersectAttrs
;
2023-11-27 12:14:54 +13:00
inherit ( lib )
2024-12-20 20:57:46 +08:00
functionArgs
isFunction
mirrorFunctionArgs
isAttrs
setFunctionArgs
optionalAttrs
attrNames
filter
elemAt
concatStringsSep
sortOn
take
length
filterAttrs
optionalString
flip
pathIsDirectory
head
pipe
isDerivation
listToAttrs
mapAttrs
seq
flatten
deepSeq
extends
2023-05-28 11:26:14 +00:00
toFunction
id
2023-11-27 12:14:54 +13:00
;
2023-12-03 03:49:22 +00:00
inherit ( lib . strings ) levenshtein levenshteinAtMost ;
2023-11-27 12:14:54 +13:00
in
2009-11-19 17:30:21 +00:00
rec {
2009-11-19 16:43:58 +00:00
2024-03-22 10:02:09 +01:00
/* *
` overrideDerivation drv f ` takes a derivation ( i . e . , the result
of a call to the builtin function ` derivation ` ) and returns a new
derivation in which the attributes of the original are overridden
according to the function ` f ` . The function ` f ` is called with
the original derivation attributes .
` overrideDerivation ` allows certain " a d - h o c " customisation
scenarios ( e . g . in ~/.config/nixpkgs/config.nix ) . For instance ,
if you want to " p a t c h " the derivation returned by a package
function in Nixpkgs to build another version than what the
function itself provides .
For another application , see build-support/vm , where this
function is used to build arbitrary derivations inside a QEMU
virtual machine .
Note that in order to preserve evaluation errors , the new derivation's
outPath depends on the old one's , which means that this function cannot
be used in circular situations when the old derivation also depends on the
new one .
You should in general prefer ` drv . overrideAttrs ` over this function ;
see the nixpkgs manual for more information on overriding .
# Inputs
` drv `
: 1 \ . Function argument
` f `
: 2 \ . Function argument
# Type
` ` `
overrideDerivation : : Derivation -> ( Derivation -> AttrSet ) -> Derivation
` ` `
# Examples
: : : { . example }
## `lib.customisation.overrideDerivation` usage example
` ` ` nix
mySed = overrideDerivation pkgs . gnused ( oldAttrs : {
name = " s e d - 4 . 2 . 2 - p r e " ;
src = fetchurl {
url = ftp://alpha.gnu.org/gnu/sed/sed-4.2.2-pre.tar.bz2 ;
hash = " s h a 2 5 6 - M x B J R c M 2 r Y z Q Y w J 5 X K x h X T Q B y v S g 5 j Z c 5 c S H E Z o B 2 I Y = " ;
} ;
patches = [ ] ;
} ) ;
` ` `
: : :
2015-03-19 15:48:54 +00:00
* /
2024-12-20 20:57:46 +08:00
overrideDerivation =
drv : f :
2009-11-19 16:43:58 +00:00
let
2013-05-15 00:38:03 -04:00
newDrv = derivation ( drv . drvAttrs // ( f drv ) ) ;
2024-12-20 20:57:46 +08:00
in
flip ( extendDerivation ( seq drv . drvPath true ) ) newDrv (
{
meta = drv . meta or { } ;
passthru = if drv ? passthru then drv . passthru else { } ;
2012-01-19 22:29:26 +00:00
}
2024-12-20 20:57:46 +08:00
// ( drv . passthru or { } )
// optionalAttrs ( drv ? __spliced ) {
__spliced = { } // ( mapAttrs ( _ : sDrv : overrideDerivation sDrv f ) drv . __spliced ) ;
}
) ;
2009-11-19 16:43:58 +00:00
2024-03-22 10:02:09 +01:00
/* *
` makeOverridable ` takes a function from attribute set to attribute set and
injects ` override ` attribute which can be used to override arguments of
the function .
2017-06-24 12:42:56 +02:00
2024-03-22 10:02:09 +01:00
Please refer to documentation on [ ` <pkg> . overrideDerivation ` ] ( #sec-pkg-overrideDerivation) to learn about `overrideDerivation` and caveats
related to its use .
2023-10-20 20:57:10 +08:00
2024-03-22 10:02:09 +01:00
# Inputs
2017-06-24 12:42:56 +02:00
2024-03-22 10:02:09 +01:00
` f `
2017-06-24 12:42:56 +02:00
2024-03-22 10:02:09 +01:00
: 1 \ . Function argument
2017-06-24 12:42:56 +02:00
2024-03-22 10:02:09 +01:00
# Type
` ` `
makeOverridable : : ( AttrSet -> a ) -> AttrSet -> a
` ` `
# Examples
: : : { . example }
## `lib.customisation.makeOverridable` usage example
` ` ` nix
nix-repl > x = { a , b }: { result = a + b ; }
nix-repl > y = lib . makeOverridable x { a = 1 ; b = 2 ; }
nix-repl > y
{ override = « lambda » ; overrideDerivation = « lambda » ; result = 3 ; }
nix-repl > y . override { a = 10 ; }
{ override = « lambda » ; overrideDerivation = « lambda » ; result = 12 ; }
` ` `
: : :
2017-06-24 12:42:56 +02:00
* /
2024-12-20 20:57:46 +08:00
makeOverridable =
f :
2023-05-29 05:52:21 +08:00
let
# Creates a functor with the same arguments as f
2023-11-27 12:14:54 +13:00
mirrorArgs = mirrorFunctionArgs f ;
2023-05-29 05:52:21 +08:00
in
2024-12-20 20:57:46 +08:00
mirrorArgs (
origArgs :
let
result = f origArgs ;
# Changes the original arguments with (potentially a function that returns) a set of new attributes
overrideWith = newArgs : origArgs // ( if isFunction newArgs then newArgs origArgs else newArgs ) ;
# Re-call the function but with different arguments
overrideArgs = mirrorArgs ( newArgs : makeOverridable f ( overrideWith newArgs ) ) ;
# Change the result of the function call by applying g to it
overrideResult = g : makeOverridable ( mirrorArgs ( args : g ( f args ) ) ) origArgs ;
in
2023-11-27 12:14:54 +13:00
if isAttrs result then
2024-12-20 20:57:46 +08:00
result
// {
2019-09-05 00:16:01 +02:00
override = overrideArgs ;
overrideDerivation = fdrv : overrideResult ( x : overrideDerivation x fdrv ) ;
2024-12-20 20:57:46 +08:00
$ { if result ? overrideAttrs then " o v e r r i d e A t t r s " else null } =
fdrv : overrideResult ( x : x . overrideAttrs fdrv ) ;
2019-09-05 00:16:01 +02:00
}
2023-11-27 12:14:54 +13:00
else if isFunction result then
2019-09-05 00:16:01 +02:00
# Transform the result into a functor while propagating its arguments
2024-12-20 20:57:46 +08:00
setFunctionArgs result ( functionArgs result )
// {
2019-09-05 00:14:22 +02:00
override = overrideArgs ;
}
2024-12-20 20:57:46 +08:00
else
result
) ;
2010-08-02 13:57:57 +00:00
2024-03-22 10:02:09 +01:00
/* *
Call the package function in the file ` fn ` with the required
2010-08-02 13:57:57 +00:00
arguments automatically . The function is called with the
2023-01-02 07:51:54 +10:00
arguments ` args ` , but any missing arguments are obtained from
` autoArgs ` . This function is intended to be partially
2010-08-02 13:57:57 +00:00
parameterised , e . g . ,
2023-10-20 20:57:10 +08:00
` ` ` nix
2010-08-02 13:57:57 +00:00
callPackage = callPackageWith pkgs ;
pkgs = {
libfoo = callPackage ./foo.nix { } ;
libbar = callPackage ./bar.nix { } ;
} ;
2023-10-20 20:57:10 +08:00
` ` `
2010-08-02 13:57:57 +00:00
2023-01-02 07:51:54 +10:00
If the ` libbar ` function expects an argument named ` libfoo ` , it is
2010-08-02 13:57:57 +00:00
automatically passed as an argument . Overrides or missing
2023-01-02 07:51:54 +10:00
arguments can be supplied in ` args ` , e . g .
2010-08-02 13:57:57 +00:00
2023-10-20 20:57:10 +08:00
` ` ` nix
2010-08-02 13:57:57 +00:00
libbar = callPackage ./bar.nix {
libfoo = null ;
enableX11 = true ;
} ;
2023-10-20 20:57:10 +08:00
` ` `
< ! - - TODO : Apply " E x a m p l e : " tag to the examples above - ->
2024-03-22 10:02:09 +01:00
# Inputs
` autoArgs `
: 1 \ . Function argument
` fn `
: 2 \ . Function argument
` args `
: 3 \ . Function argument
# Type
` ` `
callPackageWith : : AttrSet -> ( ( AttrSet -> a ) | Path ) -> AttrSet -> a
` ` `
2010-08-02 13:57:57 +00:00
* /
2024-12-20 20:57:46 +08:00
callPackageWith =
autoArgs : fn : args :
2017-09-29 09:11:26 -04:00
let
2023-11-27 12:14:54 +13:00
f = if isFunction fn then fn else import fn ;
fargs = functionArgs f ;
2020-07-25 19:54:37 +02:00
# All arguments that will be passed to the function
# This includes automatic ones and ones passed explicitly
2023-11-27 12:14:54 +13:00
allArgs = intersectAttrs fargs autoArgs // args ;
2020-07-25 19:54:37 +02:00
2023-10-20 20:57:10 +08:00
# a list of argument names that the function requires, but
2020-07-25 19:54:37 +02:00
# wouldn't be passed to it
2023-11-27 12:28:52 +13:00
missingArgs =
2020-07-25 19:54:37 +02:00
# Filter out arguments that have a default value
2024-12-20 20:57:46 +08:00
(
filterAttrs ( name : value : ! value )
# Filter out arguments that would be passed
( removeAttrs fargs ( attrNames allArgs ) )
) ;
2020-07-25 19:54:37 +02:00
# Get a list of suggested argument names for a given missing one
2024-12-20 20:57:46 +08:00
getSuggestions =
arg :
pipe ( autoArgs // args ) [
attrNames
# Only use ones that are at most 2 edits away. While mork would work,
# levenshteinAtMost is only fast for 2 or less.
( filter ( levenshteinAtMost 2 arg ) )
# Put strings with shorter distance first
( sortOn ( levenshtein arg ) )
# Only take the first couple results
( take 3 )
# Quote all entries
( map ( x : " \" " + x + " \" " ) )
] ;
prettySuggestions =
suggestions :
if suggestions = = [ ] then
" "
else if length suggestions = = 1 then
" , d i d y o u m e a n ${ elemAt suggestions 0 } ? "
else
" , d i d y o u m e a n ${ concatStringsSep " , " ( lib . init suggestions ) } o r ${ lib . last suggestions } ? " ;
errorForArg =
arg :
2020-07-25 19:54:37 +02:00
let
loc = builtins . unsafeGetAttrPos arg fargs ;
# loc' can be removed once lib/minver.nix is >2.3.4, since that includes
# https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
2024-12-20 20:57:46 +08:00
loc' =
if loc != null then
loc . file + " : " + toString loc . line
else if ! isFunction fn then
2023-11-27 12:14:54 +13:00
toString fn + optionalString ( pathIsDirectory fn ) " / d e f a u l t . n i x "
2024-12-20 20:57:46 +08:00
else
" < u n k n o w n l o c a t i o n > " ;
in
" F u n c t i o n c a l l e d w i t h o u t r e q u i r e d a r g u m e n t \" ${ arg } \" a t "
2020-07-25 19:54:37 +02:00
+ " ${ loc' } ${ prettySuggestions ( getSuggestions arg ) } " ;
# Only show the error for the first missing argument
2023-12-03 01:28:17 +03:00
error = errorForArg ( head ( attrNames missingArgs ) ) ;
2020-07-25 19:54:37 +02:00
2024-12-20 20:57:46 +08:00
in
if missingArgs = = { } then
makeOverridable f allArgs
# This needs to be an abort so it can't be caught with `builtins.tryEval`,
# which is used by nix-env and ofborg to filter out packages that don't evaluate.
# This way we're forced to fix such errors in Nixpkgs,
# which is especially relevant with allowAliases = false
else
abort " l i b . c u s t o m i s a t i o n . c a l l P a c k a g e W i t h : ${ error } " ;
2015-03-20 19:23:55 +01:00
2024-03-22 10:02:09 +01:00
/* *
Like callPackage , but for a function that returns an attribute
set of derivations . The override function is added to the
individual attributes .
# Inputs
` autoArgs `
: 1 \ . Function argument
` fn `
: 2 \ . Function argument
` args `
: 3 \ . Function argument
# Type
2023-10-20 20:57:10 +08:00
2024-03-22 10:02:09 +01:00
` ` `
callPackagesWith : : AttrSet -> ( ( AttrSet -> AttrSet ) | Path ) -> AttrSet -> AttrSet
` ` `
2023-10-20 20:57:10 +08:00
* /
2024-12-20 20:57:46 +08:00
callPackagesWith =
autoArgs : fn : args :
2015-07-28 21:35:17 +02:00
let
2023-11-27 12:14:54 +13:00
f = if isFunction fn then fn else import fn ;
auto = intersectAttrs ( functionArgs f ) autoArgs ;
2022-06-17 14:42:04 +09:00
mirrorArgs = mirrorFunctionArgs f ;
2017-02-12 13:57:42 +00:00
origArgs = auto // args ;
pkgs = f origArgs ;
2022-06-17 14:42:04 +09:00
mkAttrOverridable = name : _ : makeOverridable ( mirrorArgs ( newArgs : ( f newArgs ) . ${ name } ) ) origArgs ;
2020-03-04 11:58:03 +01:00
in
2024-12-20 20:57:46 +08:00
if isDerivation pkgs then
throw (
" f u n c t i o n ` c a l l P a c k a g e s ` w a s c a l l e d o n a * s i n g l e * d e r i v a t i o n "
+ '' " ${ pkgs . name or " < u n k n o w n - n a m e > " } " ; ''
+ " d i d y o u m e a n t o u s e ` c a l l P a c k a g e ` i n s t e a d ? "
)
else
mapAttrs mkAttrOverridable pkgs ;
2015-07-28 21:35:17 +02:00
2024-03-22 10:02:09 +01:00
/* *
Add attributes to each output of a derivation without changing
the derivation itself and check a given condition when evaluating .
# Inputs
` condition `
: 1 \ . Function argument
` passthru `
: 2 \ . Function argument
` drv `
2023-10-20 20:57:10 +08:00
2024-03-22 10:02:09 +01:00
: 3 \ . Function argument
# Type
` ` `
extendDerivation : : Bool -> Any -> Derivation -> Derivation
` ` `
2023-10-20 20:57:10 +08:00
* /
2024-12-20 20:57:46 +08:00
extendDerivation =
condition : passthru : drv :
2013-03-24 08:29:10 -04:00
let
outputs = drv . outputs or [ " o u t " ] ;
2024-12-20 20:57:46 +08:00
commonAttrs =
drv // ( listToAttrs outputsList ) // ( { all = map ( x : x . value ) outputsList ; } ) // passthru ;
2013-03-24 08:29:10 -04:00
2024-12-20 20:57:46 +08:00
outputToAttrListElement = outputName : {
name = outputName ;
value =
commonAttrs
// {
2017-12-25 18:06:49 +00:00
inherit ( drv . ${ outputName } ) type outputName ;
2021-10-15 16:30:58 +02:00
outputSpecified = true ;
2024-12-20 20:57:46 +08:00
drvPath =
assert condition ;
drv . ${ outputName } . drvPath ;
outPath =
assert condition ;
drv . ${ outputName } . outPath ;
}
//
2022-11-19 11:40:46 +01:00
# TODO: give the derivation control over the outputs.
# `overrideAttrs` may not be the only attribute that needs
# updating when switching outputs.
2024-12-20 20:57:46 +08:00
optionalAttrs ( passthru ? overrideAttrs ) {
2022-11-19 11:40:46 +01:00
# TODO: also add overrideAttrs when overrideAttrs is not custom, e.g. when not splicing.
overrideAttrs = f : ( passthru . overrideAttrs f ) . ${ outputName } ;
} ;
2024-12-20 20:57:46 +08:00
} ;
2013-03-24 08:29:10 -04:00
outputsList = map outputToAttrListElement outputs ;
2024-12-20 20:57:46 +08:00
in
commonAttrs
// {
drvPath =
assert condition ;
drv . drvPath ;
outPath =
assert condition ;
drv . outPath ;
2017-12-25 18:06:49 +00:00
} ;
2015-03-20 19:23:55 +01:00
2024-03-22 10:02:09 +01:00
/* *
Strip a derivation of all non-essential attributes , returning
only those needed by hydra-eval-jobs . Also strictly evaluate the
result to ensure that there are no thunks kept alive to prevent
garbage collection .
# Inputs
` drv `
: 1 \ . Function argument
2023-10-20 20:57:10 +08:00
2024-03-22 10:02:09 +01:00
# Type
` ` `
hydraJob : : ( Derivation | Null ) -> ( Derivation | Null )
` ` `
2023-10-20 20:57:10 +08:00
* /
2024-12-20 20:57:46 +08:00
hydraJob =
drv :
2015-03-20 19:23:55 +01:00
let
2024-12-20 20:57:46 +08:00
outputs = drv . outputs or [ " o u t " ] ;
2015-03-20 19:23:55 +01:00
commonAttrs =
2024-12-20 20:57:46 +08:00
{
inherit ( drv ) name system meta ;
inherit outputs ;
}
2023-11-27 12:14:54 +13:00
// optionalAttrs ( drv . _hydraAggregate or false ) {
2015-03-20 19:23:55 +01:00
_hydraAggregate = true ;
2023-11-27 12:14:54 +13:00
constituents = map hydraJob ( flatten drv . constituents ) ;
2015-03-20 19:23:55 +01:00
}
2023-11-27 12:14:54 +13:00
// ( listToAttrs outputsList ) ;
2015-03-20 19:23:55 +01:00
2024-12-20 20:57:46 +08:00
makeOutput =
outputName :
let
output = drv . ${ outputName } ;
in
{
name = outputName ;
2015-03-20 19:23:55 +01:00
value = commonAttrs // {
outPath = output . outPath ;
drvPath = output . drvPath ;
type = " d e r i v a t i o n " ;
inherit outputName ;
} ;
} ;
outputsList = map makeOutput outputs ;
2023-11-27 12:14:54 +13:00
drv' = ( head outputsList ) . value ;
2024-12-20 20:57:46 +08:00
in
if drv = = null then null else deepSeq drv' drv' ;
2015-03-20 19:23:55 +01:00
2024-03-09 19:29:13 +01:00
/* *
Make an attribute set ( a " s c o p e " ) from functions that take arguments from that same attribute set .
See [ ] ( #ex-makeScope) for how to use it.
2023-10-20 20:57:10 +08:00
2024-03-09 19:29:13 +01:00
# Inputs
1 . ` newScope ` ( ` AttrSet -> ( ( AttrSet -> a ) | Path ) -> AttrSet -> a ` )
A function that takes an attribute set ` attrs ` and returns what ends up as ` callPackage ` in the output .
Typical values are ` callPackageWith ` or the output attribute ` newScope ` .
2 . ` f ` ( ` AttrSet -> AttrSet ` )
A function that takes an attribute set as returned by ` makeScope newScope f ` ( a " s c o p e " ) and returns any attribute set .
This function is used to compute the fixpoint of the resulting scope using ` callPackage ` .
Its argument is the lazily evaluated reference to the value of that fixpoint , and is typically called ` self ` or ` final ` .
See [ ] ( #ex-makeScope) for how to use it.
See [ ] ( #sec-functions-library-fixedPoints) for details on fixpoint computation.
# Output
` makeScope ` returns an attribute set of a form called ` scope ` , which also contains the final attributes produced by ` f ` :
` ` `
scope : : {
callPackage : : ( ( AttrSet -> a ) | Path ) -> AttrSet -> a
newScope = AttrSet -> scope
overrideScope = ( scope -> scope -> AttrSet ) -> scope
packages : : AttrSet -> AttrSet
}
` ` `
- ` callPackage ` ( ` ( ( AttrSet -> a ) | Path ) -> AttrSet -> a ` )
A function that
1 . Takes a function ` p ` , or a path to a Nix file that contains a function ` p ` , which takes an attribute set and returns value of arbitrary type ` a ` ,
2 . Takes an attribute set ` args ` with explicit attributes to pass to ` p ` ,
2024-08-17 16:47:58 +09:00
3 . Calls ` f ` with attributes from the original attribute set ` attrs ` passed to ` newScope ` updated with ` args ` , i . e . ` attrs // args ` , if they match the attributes in the argument of ` p ` .
2024-03-09 19:29:13 +01:00
All such functions ` p ` will be called with the same value for ` attrs ` .
See [ ] ( #ex-makeScope-callPackage) for how to use it.
- ` newScope ` ( ` AttrSet -> scope ` )
Takes an attribute set ` attrs ` and returns a scope that extends the original scope .
- ` overrideScope ` ( ` ( scope -> scope -> AttrSet ) -> scope ` )
Takes a function ` g ` of the form ` final : prev : { # attributes }` to act as an overlay on `f`, and returns a new scope with values determined by `extends g f`.
See [ ] ( https://nixos.org/manual/nixpkgs/unstable/ #function-library-lib.fixedPoints.extends) for details.
This allows subsequent modification of the final attribute set in a consistent way , i . e . all functions ` p ` invoked with ` callPackage ` will be called with the modified values .
- ` packages ` ( ` AttrSet -> AttrSet ` )
The value of the argument ` f ` to ` makeScope ` .
- final attributes
The final values returned by ` f ` .
# Examples
: : : { #ex-makeScope .example}
# Create an interdependent package set on top of `pkgs`
The functions in ` foo . nix ` and ` bar . nix ` can depend on each other , in the sense that ` foo . nix ` can contain a function that expects ` bar ` as an attribute in its argument .
` ` ` nix
let
pkgs = import <nixpkgs> { } ;
in
pkgs . lib . makeScope pkgs . newScope ( self : {
foo = self . callPackage ./foo.nix { } ;
bar = self . callPackage ./bar.nix { } ;
} )
` ` `
evaluates to
` ` ` nix
{
callPackage = « lambda » ;
newScope = « lambda » ;
overrideScope = « lambda » ;
packages = « lambda » ;
foo = « derivation » ;
bar = « derivation » ;
}
` ` `
: : :
: : : { #ex-makeScope-callPackage .example}
# Using `callPackage` from a scope
` ` ` nix
let
pkgs = import <nixpkgs> { } ;
inherit ( pkgs ) lib ;
scope = lib . makeScope lib . callPackageWith ( self : { a = 1 ; b = 2 ; } ) ;
three = scope . callPackage ( { a , b }: a + b ) { } ;
four = scope . callPackage ( { a , b }: a + b ) { a = 2 ; } ;
in
[ three four ]
` ` `
evaluates to
` ` ` nix
[ 3 4 ]
` ` `
: : :
# Type
` ` `
makeScope : : ( AttrSet -> ( ( AttrSet -> a ) | Path ) -> AttrSet -> a ) -> ( AttrSet -> AttrSet ) -> scope
` ` `
2023-10-20 20:57:10 +08:00
* /
2024-12-20 20:57:46 +08:00
makeScope =
newScope : f :
let
self = f self // {
newScope = scope : newScope ( self // scope ) ;
callPackage = self . newScope { } ;
overrideScope = g : makeScope newScope ( extends g f ) ;
packages = f ;
} ;
in
self ;
2015-09-27 09:45:23 -05:00
2024-03-22 10:02:09 +01:00
/* *
backward compatibility with old uncurried form ; deprecated
# Inputs
` splicePackages `
: 1 \ . Function argument
` newScope `
: 2 \ . Function argument
` otherSplices `
: 3 \ . Function argument
` keep `
: 4 \ . Function argument
` extra `
: 5 \ . Function argument
` f `
: 6 \ . Function argument
* /
2023-08-14 02:47:59 +03:00
makeScopeWithSplicing =
splicePackages : newScope : otherSplices : keep : extra : f :
2024-12-20 20:57:46 +08:00
makeScopeWithSplicing' { inherit splicePackages newScope ; } {
inherit
otherSplices
keep
extra
f
;
} ;
2023-08-14 02:47:59 +03:00
2024-03-22 10:02:09 +01:00
/* *
Like makeScope , but aims to support cross compilation . It's still ugly , but
hopefully it helps a little bit .
# Type
` ` `
makeScopeWithSplicing' : :
{ splicePackages : : Splice -> AttrSet
, newScope : : AttrSet -> ( ( AttrSet -> a ) | Path ) -> AttrSet -> a
}
-> { otherSplices : : Splice , keep : : AttrSet -> AttrSet , extra : : AttrSet -> AttrSet }
-> AttrSet
Splice : :
{ pkgsBuildBuild : : AttrSet
, pkgsBuildHost : : AttrSet
, pkgsBuildTarget : : AttrSet
, pkgsHostHost : : AttrSet
, pkgsHostTarget : : AttrSet
, pkgsTargetTarget : : AttrSet
}
` ` `
2023-10-20 20:57:10 +08:00
* /
2023-08-14 02:47:59 +03:00
makeScopeWithSplicing' =
2024-12-20 20:57:46 +08:00
{
splicePackages ,
newScope ,
2023-08-14 02:47:59 +03:00
} :
2024-12-20 20:57:46 +08:00
{
otherSplices ,
# Attrs from `self` which won't be spliced.
# Avoid using keep, it's only used for a python hook workaround, added in PR #104201.
# ex: `keep = (self: { inherit (self) aAttr; })`
keep ? ( _self : { } ) ,
# Additional attrs to add to the sets `callPackage`.
# When the package is from a subset (but not a subset within a package IS #211340)
# within `spliced0` it will be spliced.
# When using an package outside the set but it's available from `pkgs`, use the package from `pkgs.__splicedPackages`.
# If the package is not available within the set or in `pkgs`, such as a package in a let binding, it will not be spliced
# ex:
# ```
# nix-repl> darwin.apple_sdk.frameworks.CoreFoundation
# «derivation ...CoreFoundation-11.0.0.drv»
# nix-repl> darwin.CoreFoundation
# error: attribute 'CoreFoundation' missing
# nix-repl> darwin.callPackage ({ CoreFoundation }: CoreFoundation) { }
# «derivation ...CoreFoundation-11.0.0.drv»
# ```
extra ? ( _spliced0 : { } ) ,
f ,
2023-08-14 02:47:59 +03:00
} :
2020-11-18 12:12:34 -05:00
let
2021-05-04 00:08:20 -04:00
spliced0 = splicePackages {
2020-11-18 12:12:34 -05:00
pkgsBuildBuild = otherSplices . selfBuildBuild ;
pkgsBuildHost = otherSplices . selfBuildHost ;
pkgsBuildTarget = otherSplices . selfBuildTarget ;
pkgsHostHost = otherSplices . selfHostHost ;
pkgsHostTarget = self ; # Not `otherSplices.selfHostTarget`;
pkgsTargetTarget = otherSplices . selfTargetTarget ;
2021-05-04 00:08:20 -04:00
} ;
spliced = extra spliced0 // spliced0 // keep self ;
2020-11-18 12:12:34 -05:00
self = f self // {
newScope = scope : newScope ( spliced // scope ) ;
callPackage = newScope spliced ; # == self.newScope {};
# N.B. the other stages of the package set spliced in are *not*
# overridden.
2024-12-20 20:57:46 +08:00
overrideScope =
g :
( makeScopeWithSplicing' { inherit splicePackages newScope ; } {
inherit otherSplices keep extra ;
2023-11-27 12:14:54 +13:00
f = extends g f ;
2023-08-14 02:47:59 +03:00
} ) ;
2020-11-18 12:12:34 -05:00
packages = f ;
} ;
2024-12-20 20:57:46 +08:00
in
self ;
2020-11-18 12:12:34 -05:00
2023-05-28 11:26:14 +00:00
/* *
Define a ` mkDerivation ` - like function based on another ` mkDerivation ` - like function .
[ ` stdenv . mkDerivation ` ] ( #part-stdenv) gives access to
its final set of derivation attributes when it is passed a function ,
or when it is passed an overlay-style function in ` overrideAttrs ` .
Instead of composing new ` stdenv . mkDerivation ` - like build helpers
using normal function composition ,
` extendMkDerivation ` makes sure that the returned build helper
supports such first class recursion like ` mkDerivation ` does .
` extendMkDerivation ` takes an extra attribute set to configure its behaviour .
One can optionally specify
` transformDrv ` to specify a function to apply to the result derivation ,
or ` inheritFunctionArgs ` to decide whether to inherit the ` __functionArgs `
from the base build helper .
# Inputs
` extendMkDerivation ` - specific configurations
: ` constructDrv ` : Base build helper , the ` mkDerivation ` - like build helper to extend .
: ` excludeDrvArgNames ` : Argument names not to pass from the input fixed-point arguments to ` constructDrv ` . Note : It doesn't apply to the updating arguments returned by ` extendDrvArgs ` .
: ` extendDrvArgs ` : An extension ( overlay ) of the argument set , like the one taken by [ overrideAttrs ] ( #sec-pkg-overrideAttrs) but applied before passing to `constructDrv`.
: ` inheritFunctionArgs ` : Whether to inherit ` __functionArgs ` from the base build helper ( default to ` true ` ) .
: ` transformDrv ` : Function to apply to the result derivation ( default to ` lib . id ` ) .
# Type
` ` `
extendMkDerivation : :
{
constructDrv : : ( ( FixedPointArgs | AttrSet ) -> a )
excludeDrvArgNames : : [ String ] ,
extendDrvArgs : : ( AttrSet -> AttrSet -> AttrSet )
inheritFunctionArgs : : Bool ,
transformDrv : : a -> a ,
}
-> ( FixedPointArgs | AttrSet ) -> a
FixedPointArgs = AttrSet -> AttrSet
a = Derivation when defining a build helper
` ` `
# Examples
: : : { . example }
## `lib.customisation.extendMkDerivation` usage example
` ` ` nix-repl
mkLocalDerivation = lib . extendMkDerivation {
constructDrv = pkgs . stdenv . mkDerivation ;
excludeDrvArgNames = [ " s p e c i a l A r g " ] ;
extendDrvArgs =
finalAttrs : args @ { preferLocalBuild ? true , allowSubstitute ? false , specialArg ? ( _ : false ) , . . . }:
{ inherit preferLocalBuild allowSubstitute ; passthru = { inherit specialArg ; } // args . passthru or { } ; } ;
}
mkLocalDerivation . __functionArgs
= > { allowSubstitute = true ; preferLocalBuild = true ; specialArg = true ; }
mkLocalDerivation { inherit ( pkgs . hello ) pname version src ; specialArg = _ : false ; }
= > « derivation /nix/store/xirl67m60ahg6jmzicx43a81g635g8z8-hello-2.12.1.drv »
mkLocalDerivation ( finalAttrs : { inherit ( pkgs . hello ) pname version src ; specialArg = _ : false ; } )
= > « derivation /nix/store/xirl67m60ahg6jmzicx43a81g635g8z8-hello-2.12.1.drv »
( mkLocalDerivation ( finalAttrs : { inherit ( pkgs . hello ) pname version src ; passthru = { foo = " a " ; bar = " ${ finalAttrs . passthru . foo } b " ; } ; } ) ) . bar
= > " a b "
` ` `
: : :
: : : { . note }
If ` transformDrv ` is specified ,
it should take care of existing attributes that perform overriding
( e . g . , [ ` overrideAttrs ` ] ( #sec-pkg-overrideAttrs))
to ensure that the overriding functionality of the result derivation
work as expected .
Modifications that breaks the overriding include
direct [ attribute set update ] ( https://nixos.org/manual/nix/stable/language/operators #update)
and [ ` lib . extendDerivation ` ] ( #function-library-lib.customisation.extendDerivation).
: : :
* /
extendMkDerivation =
let
extendsWithExclusion =
excludedNames : g : f : final :
let
previous = f final ;
in
removeAttrs previous excludedNames // g final previous ;
in
{
constructDrv ,
excludeDrvArgNames ? [ ] ,
extendDrvArgs ,
inheritFunctionArgs ? true ,
transformDrv ? id ,
} :
setFunctionArgs
# Adds the fixed-point style support
(
fpargs :
transformDrv (
constructDrv ( extendsWithExclusion excludeDrvArgNames extendDrvArgs ( toFunction fpargs ) )
)
)
# Add __functionArgs
(
# Inherit the __functionArgs from the base build helper
optionalAttrs inheritFunctionArgs ( removeAttrs ( functionArgs constructDrv ) excludeDrvArgNames )
# Recover the __functionArgs from the derived build helper
// functionArgs ( extendDrvArgs { } )
)
// {
inherit
# Expose to the result build helper.
constructDrv
excludeDrvArgNames
extendDrvArgs
transformDrv
;
} ;
2009-11-19 16:43:58 +00:00
}