Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Core (builtin) Options set

lib/core.nix

This module is made possible by: birdee

These are the core options that make everything else possible.

They include the .extendModules, .apply, .eval, and .wrap functions, and the .wrapper itself

They are always imported with every module evaluation.

They are somewhat minimal by design. They pertain to building the derivation, not the wrapper script.

The default builderFunction value provides no options.

The default wrapperFunction is null.

wlib.modules.default provides great values for these options, and creates many more for you to use.

But you may want to wrap your package via different means, provide different options, or provide modules for others to use to help do those things!

Doing it this way allows wrapper modules to do anything you might wish involving wrapping some source/package in a derivation.

Excited to see what ways to use these options everyone comes up with! Docker helpers? BubbleWrap? If it’s a derivation, it should be possible!


apply

Function to extend the current configuration with additional modules. Can accept a single module, or a list of modules. Re-evaluates the configuration with the original settings plus the new module(s).

Returns .config from the lib.evalModules result

Type: (read-only) function that evaluates to a(n) raw value

Default:

<function>

Declared by:

binName

The name of the binary output by wrapperFunction to $out/bin

If not specified, the default name from the package will be used.

Type: non-empty line

Default:

"hello"

Declared by:

builderFunction

Outside of importing wlib.modules.symlinkScript module, which is included in wlib.modules.default, This is usually an option you will never have to redefine.

This option takes a function receiving the following arguments:

module arguments + wrapper + pkgs.callPackage

{
  wlib,
  config,
  wrapper,
  ... # <- anything you can get from pkgs.callPackage
}@initialArgs:
"<buildCommand>"

It is in charge of linking wrapper and config.outputs to the final package.

wrapper is the unchecked result of calling wrapperFunction, or null if one was not provided.

  • The function is to return a string which will be added to the buildCommand of the wrapper.

The builtin implementation, and also the wlib.modules.symlinkScript module, accept either a string to prepend to the returned buildCommand string, or a derivation to link with lndir

  • Alternatively, it may return a function which returns a set like:
{ wlib, config, wrapper, ... }@initialArgs:
drvArgs:
drvArgs // {}

If it does this, that function will be given the final computed derivation attributes, and it will be expected to return the final attribute set to be passed to pkgs.stdenv.mkDerivation.

Regardless of if you return a string or function, passthru.wrap, passthru.apply, passthru.eval, passthru.extendModules, passthru.override, passthru.overrideAttrs will be added to the thing you return, and config.sourceStdenv will be handled for you.

However:

  • You can also return a functor with a (required) mkDerivation field.
  { config, stdenv, wrapper, wlib, ... }@initialArgs:
  {
    inherit (stdenv) mkDerivation;
    __functor = {
      mkDerivation,
      __functor,
      defaultPhases, # [ "<all stdenv phases>" ... ]
      setupPhases, # phases: "if [ -z \"${phases[*]:-}\" ]; then phases="etc..."; fi"
      runPhases, # "for curPhase in ${phases[*]}; do runPhase \"$curPhase\"; done"
      ...
    }@self:
    defaultArgs:
    defaultArgs // (if config.sourceStdenv then { } else { buildCommand = ""; }
  }
  • If you do this:
    • You are in control over the entire derivation.
    • This means you need to take care of config.passthru and config.sourceStdenv yourself.
    • The mkDerivation function will be called with the final result of your functor.

As you can see, you are provided with some things to help you via the self argument to your functor.

The generated passthru items mentioned above are given to you as part of what is shown as defaultArgs above

And you are also given some helpers to help you run the phases if needed!

Tip: A functor is a set with a { __functor = self: args: ...; } field. You can call it like a function and it gets passed itself as its first argument!

Type: function that evaluates to a(n) (string or function that evaluates to a(n) attribute set of raw value)

Default:

<function, args: {config, lib, lndir, wlib, wrapper}>

Declared by:

drv

Extra attributes to add to the resulting derivation.

Cannot affect passthru, or outputs. For that, use config.passthru, or config.outputs instead.

Also cannot override buildCommand. That is controlled by the config.builderFunction and config.sourceStdenv options.

Type: attrsRecursive

Default:

{ }

Declared by:

eval

Function to extend the current configuration with additional modules. Can accept a single module, or a list of modules. Re-evaluates the configuration with the original settings plus the new module(s).

Returns the raw lib.evalModules result

Type: (read-only) function that evaluates to a(n) raw value

Default:

<function>

Declared by:

exePath

The relative path to the executable to wrap. i.e. bin/exename

If not specified, the path gained from calling lib.getExe on config.package and subtracting the path to the package will be used.

Type: null or non-empty line

Default:

"bin/hello"

Declared by:

extendModules

Alias for .extendModules so that you can call it from outside of wlib.types.subWrapperModule types

In addition, it is also a set which stores the function args for the module evaluation. This may prove useful when dealing with subWrapperModules or packages, which otherwise would not have access to some of them.

Type: (read-only) function that evaluates to a(n) raw value

Default:

<function, args: {modules?, prefix?, specialArgs?}>

Declared by:

meta.description

Description of the module.

Accepts either a string, or a set of { pre ? "", post ? "" }

Resulting config value will be a list of { pre, post, file }

Type: string or { pre ? “”, post ? “” } (converted to [ { pre, post, file } ])

Default:

""

Declared by:

meta.maintainers

Maintainers of this module.

Type: list of (open submodule of attrsRecursive)

Default:

[ ]

Declared by:

meta.maintainers.*.email

email

Type: null or string

Default:

null

Declared by:

meta.maintainers.*.github

GitHub username

Type: string

Declared by:

meta.maintainers.*.githubId

GitHub id

Type: signed integer

Declared by:

meta.maintainers.*.matrix

Matrix ID

Type: null or string

Default:

null

Declared by:

meta.maintainers.*.name

name

Type: string

Default:

"‹name›"

Declared by:

meta.platforms

Supported platforms

Type: list of strings from enum of lib.platforms.all

Default:

lib.platforms.all

Example:

[
  "x86_64-linux"
  "aarch64-linux"
]

Declared by:

outputs

Override the list of nix outputs that get symlinked into the final package.

Default is config.package.outputs or [ "out" ] if invalid.

Type: non-empty list of string

Default:

[
  "out"
]

Declared by:

overrides

the list of .override and .overrideAttrs to apply to config.package

Accessing config.package will return the package with all overrides applied.

Accepts a list of { data, type ? null, name ? null, before ? [], after ? [] }

If type == null then data must be a function. It will receive and return the package.

If type is a string like override or overrideAttrs, it represents the attribute of config.package to pass the data field to.

If a raw value is given, it will be used as the data field, and type will be null.

config.package = pkgs.mpv;
config.overrides = [
  { # If they don't have a name they cannot be targeted!
    type = "override";
    after = [ "MPV_SCRIPTS" ];
    data = (prev: {
      scripts = (prev.scripts or []) ++ [ pkgs.mpvScripts.visualizer ];
    });
  }
  {
    name = "MPV_SCRIPTS";
    type = "override";
    data = (prev: {
      scripts = (prev.scripts or []) ++ [ pkgs.mpvScripts.modernz ];
    });
  }
  # the default `type` is `null`
  (pkg: pkg.override (prev: {
    scripts = (prev.scripts or []) ++ [ pkgs.mpvScripts.autocrop ];
  }))
  {
    type = null;
    before = [ "MPV_SCRIPTS" ];
    data = (pkg: pkg.override (prev: {
      scripts = (prev.scripts or []) ++ config.scripts;
    }));
  }
  { # It was already after "MPV_SCRIPTS" so this will stay where it is
    type = "overrideAttrs";
    after = [ "MPV_SCRIPTS" ];
    data = prev: {
      name = prev.name + "-wrapped";
    };
  }
];

The above will add config.scripts, then modernz then visualizer and finally autocrop

Then it will add -wrapped to the end of config.package’s name attribute.

The sort will not always put the value directly after the targeted value, it fulfils the requested before or after dependencies and no more.

You can modify the specs!

The type supports type merging, so you may redeclare it in order to add more options or change default values.

{ config, lib, wlib, pkgs, ... }:{
  options.overrides = lib.mkOption {
    type = wlib.types.seriesOf (wlib.types.spec ({ config, ... }: {
      options = {};
      config = {};
    }));
  };
}

Type: series of spec with main field: data of raw value

Default:

[ ]

Declared by:

overrides.*.after

Items that this spec should be ordered after.

Type: list of string

Default:

[ ]

Declared by:

overrides.*.before

Items that this spec should be ordered before.

Type: list of string

Default:

[ ]

Declared by:

overrides.*.data

If type is null, then this is the function to call on the package.

If type is a string, then this is the data to pass to the function corresponding with that attribute.

Type: raw value

Declared by:

overrides.*.name

The name for targeting from the before or after fields of other specs.

If null it cannot be targeted by other specs.

Type: null or string

Default:

null

Declared by:

overrides.*.type

The attribute of config.package to pass the override argument to. If null, then data receives and returns the package instead.

If null, data must be a function. If a string, config.package must have the corresponding attribute, and it must be a function.

Type: null or one of “override”, “overrideAttrs” or string

Default:

null

Declared by:

package

The base package to wrap. This means config.builderFunction will be responsible for inheriting all other files from this package (like man page, /share, …)

The config.package value given by this option already has all values from config.overrides applied to it.

Type: str|path|drv

Declared by:

passthru

Additional attributes to add to the resulting derivation’s passthru. This can be used to add additional metadata or functionality to the wrapped package. Anything added under the attribute name configuration will be ignored, as that value is used internally.

Type: attrsRecursive

Default:

{ }

Declared by:

pkgs

The nixpkgs pkgs instance to use.

Required in order to access .wrapper attribute, either directly, or indirectly.

Type: Nixpkgs package set

Declared by:

sourceStdenv

Run the enabled stdenv phases on the wrapper derivation.

NOTE: often you may prefer to use things like drv.doDist = true;, or even drv.phases = [ ... "buildPhase" etc ... ]; instead, to override this choice in a more fine-grained manner

Type: boolean

Default:

true

Declared by:

wrap

Function to extend the current configuration with additional modules. Can accept a single module, or a list of modules. Re-evaluates the configuration with the original settings plus the new module(s).

Returns the updated package.

Type: (read-only) function that evaluates to a(n) package

Default:

<function>

Declared by:

wrapper

The final wrapped package.

You may still call .eval and the rest on the package again afterwards.

Accessing this value without defining pkgs option, either directly, or via some other means like .wrap, will cause an error.

Type: (read-only) package

Default:

<derivation hello-2.12.2>

Declared by:

wrapperFunction

Arguments:

This option takes a function receiving the following arguments:

module arguments + pkgs.callPackage

{
  config,
  wlib,
  ... # <- anything you can get from pkgs.callPackage
}

The result of this function is passed DIRECTLY to the value of the builderFunction function.

The relative path to the thing to wrap from within config.package is config.exePath

You should wrap the package and place the wrapper at "$out/bin/${config.binName}"

Type: null or (function that evaluates to a(n) raw value)

Default:

null

Declared by: