2019-02-26 11:45:54 +00:00
|
|
|
|
{ lib, stdenv, stdenvNoCC, lndir, runtimeShell }:
|
2009-11-19 16:07:47 +00:00
|
|
|
|
|
2016-09-27 15:36:16 +01:00
|
|
|
|
rec {
|
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/* Run the shell command `buildCommand' to produce a store path named
|
|
|
|
|
* `name'. The attributes in `env' are added to the environment
|
2021-03-18 17:49:40 +00:00
|
|
|
|
* prior to running the command. By default `runCommand` runs in a
|
|
|
|
|
* stdenv with no compiler environment. `runCommandCC` uses the default
|
|
|
|
|
* stdenv, `pkgs.stdenv`.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*
|
|
|
|
|
* Examples:
|
2019-04-19 05:29:42 +01:00
|
|
|
|
* runCommand "name" {envVariable = true;} ''echo hello > $out''
|
|
|
|
|
* runCommandNoCC "name" {envVariable = true;} ''echo hello > $out'' # equivalent to prior
|
2019-02-26 11:45:54 +00:00
|
|
|
|
* runCommandCC "name" {} ''gcc -o myfile myfile.c; cp myfile $out'';
|
2019-11-29 15:27:11 +00:00
|
|
|
|
*
|
|
|
|
|
* The `*Local` variants force a derivation to be built locally,
|
|
|
|
|
* it is not substituted.
|
|
|
|
|
*
|
|
|
|
|
* This is intended for very cheap commands (<1s execution time).
|
|
|
|
|
* It saves on the network roundrip and can speed up a build.
|
|
|
|
|
*
|
|
|
|
|
* It is the same as adding the special fields
|
|
|
|
|
* `preferLocalBuild = true;`
|
|
|
|
|
* `allowSubstitutes = false;`
|
|
|
|
|
* to a derivation’s attributes.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*/
|
2016-09-27 15:36:16 +01:00
|
|
|
|
runCommand = runCommandNoCC;
|
2019-11-29 15:27:11 +00:00
|
|
|
|
runCommandLocal = runCommandNoCCLocal;
|
|
|
|
|
|
2021-03-18 17:49:40 +00:00
|
|
|
|
runCommandNoCC = name: env: runCommandWith {
|
|
|
|
|
stdenv = stdenvNoCC;
|
|
|
|
|
runLocal = false;
|
|
|
|
|
inherit name;
|
|
|
|
|
derivationArgs = env;
|
|
|
|
|
};
|
|
|
|
|
runCommandNoCCLocal = name: env: runCommandWith {
|
|
|
|
|
stdenv = stdenvNoCC;
|
|
|
|
|
runLocal = true;
|
|
|
|
|
inherit name;
|
|
|
|
|
derivationArgs = env;
|
|
|
|
|
};
|
2019-11-29 15:27:11 +00:00
|
|
|
|
|
2021-03-18 17:49:40 +00:00
|
|
|
|
runCommandCC = name: env: runCommandWith {
|
|
|
|
|
stdenv = stdenv;
|
|
|
|
|
runLocal = false;
|
|
|
|
|
inherit name;
|
|
|
|
|
derivationArgs = env;
|
|
|
|
|
};
|
2019-12-03 18:09:58 +00:00
|
|
|
|
# `runCommandCCLocal` left out on purpose.
|
|
|
|
|
# We shouldn’t force the user to have a cc in scope.
|
2009-11-19 16:07:47 +00:00
|
|
|
|
|
2021-03-18 17:49:40 +00:00
|
|
|
|
/* Generalized version of the `runCommand`-variants
|
|
|
|
|
* which does customized behavior via a single
|
|
|
|
|
* attribute set passed as the first argument
|
|
|
|
|
* instead of having a lot of variants like
|
|
|
|
|
* `runCommand*`. Additionally it allows changing
|
|
|
|
|
* the used `stdenv` freely and has a more explicit
|
|
|
|
|
* approach to changing the arguments passed to
|
|
|
|
|
* `stdenv.mkDerivation`.
|
|
|
|
|
*/
|
|
|
|
|
runCommandWith =
|
|
|
|
|
let
|
|
|
|
|
# prevent infinite recursion for the default stdenv value
|
|
|
|
|
defaultStdenv = stdenv;
|
|
|
|
|
in
|
|
|
|
|
{ stdenv ? defaultStdenv
|
|
|
|
|
# which stdenv to use, defaults to a stdenv with a C compiler, pkgs.stdenv
|
|
|
|
|
, runLocal ? false
|
|
|
|
|
# whether to build this derivation locally instead of substituting
|
|
|
|
|
, derivationArgs ? {}
|
|
|
|
|
# extra arguments to pass to stdenv.mkDerivation
|
|
|
|
|
, name
|
|
|
|
|
# name of the resulting derivation
|
|
|
|
|
}: buildCommand:
|
|
|
|
|
stdenv.mkDerivation ({
|
|
|
|
|
name = lib.strings.sanitizeDerivationName name;
|
|
|
|
|
inherit buildCommand;
|
|
|
|
|
passAsFile = [ "buildCommand" ]
|
|
|
|
|
++ (derivationArgs.passAsFile or []);
|
|
|
|
|
}
|
|
|
|
|
// (lib.optionalAttrs runLocal {
|
|
|
|
|
preferLocalBuild = true;
|
|
|
|
|
allowSubstitutes = false;
|
|
|
|
|
})
|
|
|
|
|
// builtins.removeAttrs derivationArgs [ "passAsFile" ]);
|
|
|
|
|
|
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/* Writes a text file to the nix store.
|
|
|
|
|
* The contents of text is added to the file in the store.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
|
|
|
|
* # Writes my-file to /nix/store/<store path>
|
2019-04-07 23:38:13 +01:00
|
|
|
|
* writeTextFile {
|
|
|
|
|
* name = "my-file";
|
|
|
|
|
* text = ''
|
|
|
|
|
* Contents of File
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* '';
|
2019-04-07 23:38:13 +01:00
|
|
|
|
* }
|
|
|
|
|
* # See also the `writeText` helper function below.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*
|
|
|
|
|
* # Writes executable my-file to /nix/store/<store path>/bin/my-file
|
2019-04-07 23:38:13 +01:00
|
|
|
|
* writeTextFile {
|
|
|
|
|
* name = "my-file";
|
|
|
|
|
* text = ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
* executable = true;
|
|
|
|
|
* destination = "/bin/my-file";
|
|
|
|
|
* }
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*/
|
2009-11-19 16:07:47 +00:00
|
|
|
|
writeTextFile =
|
|
|
|
|
{ name # the name of the derivation
|
|
|
|
|
, text
|
|
|
|
|
, executable ? false # run chmod +x ?
|
|
|
|
|
, destination ? "" # relative path appended to $out eg "/bin/foo"
|
2016-01-27 22:26:40 +00:00
|
|
|
|
, checkPhase ? "" # syntax checks, e.g. for scripts
|
2009-11-19 16:07:47 +00:00
|
|
|
|
}:
|
2012-04-26 16:01:41 +01:00
|
|
|
|
runCommand name
|
trivial-builders: refactor writeTextFile to be overridable
This fixes #126344, specifically with the goal of enabling overriding the
checkPhase argument. See `design notes` at the end for details.
This allows among other things, enabling bash extension for the `checkPhase`.
Previously using such bash extensions was prohibited by the `writeShellScript`
code because there was no way to enable the extension in the checker.
As an example:
```nix
(writeShellScript "foo" ''
shopt -s extglob
echo @(foo|bar)
'').overrideAttrs (old: {
checkPhase = ''
# use subshell to preserve outer environment
(
export BASHOPTS
shopt -s extglob
${old.checkPhase}
)
'';
})
```
This commit also adds tests for this feature to `pkgs/tests/default.nix`,
under `trivial-overriding`. The test code is located at
`pkgs/build-support/trivial-builders/test-overriding.nix`.
Design notes:
-------------
Per discussion with @sternenseemann, the original approach of just wrapping
`writeTextFile` in `makeOverridable` had the issue that combined with `callPackage`
in the following form, would shadow the `.override` attribute of the `writeTextFile`:
```nix
with import <nixpkgs>;
callPackage ({writeShellScript}: writeShellScript "foo" "echo foo")
```
A better approach can be seen in this commit, where `checkPhase` is moved
from an argument of `writeTextFile`, which is substituted into `buildCommand`,
into an `mkDerivation` argument, which is substituted from the environment
and `eval`-ed. (see the source)
This way we can simple use `.overideAttrs` as usual, and this also makes
`checkPhase` a bit more conformant to `mkDerivation` naming, with respect to
phases generally being overridable attrs.
Co-authored-by: sterni <sternenseemann@systemli.org>
Co-authored-by: Naïm Favier <n@monade.li>
2021-06-14 14:06:23 +01:00
|
|
|
|
{ inherit text executable checkPhase;
|
2015-02-18 00:08:03 +00:00
|
|
|
|
passAsFile = [ "text" ];
|
2012-04-26 16:01:41 +01:00
|
|
|
|
# Pointless to do this on a remote machine.
|
|
|
|
|
preferLocalBuild = true;
|
2015-07-07 14:01:36 +01:00
|
|
|
|
allowSubstitutes = false;
|
2012-04-26 16:01:41 +01:00
|
|
|
|
}
|
2009-11-19 16:07:47 +00:00
|
|
|
|
''
|
|
|
|
|
n=$out${destination}
|
|
|
|
|
mkdir -p "$(dirname "$n")"
|
2015-12-31 21:14:44 +00:00
|
|
|
|
|
2015-02-18 00:08:03 +00:00
|
|
|
|
if [ -e "$textPath" ]; then
|
|
|
|
|
mv "$textPath" "$n"
|
|
|
|
|
else
|
|
|
|
|
echo -n "$text" > "$n"
|
|
|
|
|
fi
|
2015-12-31 21:14:44 +00:00
|
|
|
|
|
trivial-builders: refactor writeTextFile to be overridable
This fixes #126344, specifically with the goal of enabling overriding the
checkPhase argument. See `design notes` at the end for details.
This allows among other things, enabling bash extension for the `checkPhase`.
Previously using such bash extensions was prohibited by the `writeShellScript`
code because there was no way to enable the extension in the checker.
As an example:
```nix
(writeShellScript "foo" ''
shopt -s extglob
echo @(foo|bar)
'').overrideAttrs (old: {
checkPhase = ''
# use subshell to preserve outer environment
(
export BASHOPTS
shopt -s extglob
${old.checkPhase}
)
'';
})
```
This commit also adds tests for this feature to `pkgs/tests/default.nix`,
under `trivial-overriding`. The test code is located at
`pkgs/build-support/trivial-builders/test-overriding.nix`.
Design notes:
-------------
Per discussion with @sternenseemann, the original approach of just wrapping
`writeTextFile` in `makeOverridable` had the issue that combined with `callPackage`
in the following form, would shadow the `.override` attribute of the `writeTextFile`:
```nix
with import <nixpkgs>;
callPackage ({writeShellScript}: writeShellScript "foo" "echo foo")
```
A better approach can be seen in this commit, where `checkPhase` is moved
from an argument of `writeTextFile`, which is substituted into `buildCommand`,
into an `mkDerivation` argument, which is substituted from the environment
and `eval`-ed. (see the source)
This way we can simple use `.overideAttrs` as usual, and this also makes
`checkPhase` a bit more conformant to `mkDerivation` naming, with respect to
phases generally being overridable attrs.
Co-authored-by: sterni <sternenseemann@systemli.org>
Co-authored-by: Naïm Favier <n@monade.li>
2021-06-14 14:06:23 +01:00
|
|
|
|
eval "$checkPhase"
|
2016-01-27 22:26:40 +00:00
|
|
|
|
|
2009-11-19 16:07:47 +00:00
|
|
|
|
(test -n "$executable" && chmod +x "$n") || true
|
|
|
|
|
'';
|
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
|
|
|
|
* Writes a text file to nix store with no optional parameters available.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
* # Writes contents of file to /nix/store/<store path>
|
|
|
|
|
* writeText "my-file"
|
|
|
|
|
* ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
*
|
|
|
|
|
*/
|
2009-11-19 16:07:47 +00:00
|
|
|
|
writeText = name: text: writeTextFile {inherit name text;};
|
2019-05-06 18:08:23 +01:00
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
|
|
|
|
* Writes a text file to nix store in a specific directory with no
|
2019-07-07 20:18:37 +01:00
|
|
|
|
* optional parameters available.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*
|
|
|
|
|
* Example:
|
2019-07-07 20:18:37 +01:00
|
|
|
|
* # Writes contents of file to /nix/store/<store path>/share/my-file
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* writeTextDir "share/my-file"
|
|
|
|
|
* ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
*
|
|
|
|
|
*/
|
2019-07-07 20:18:37 +01:00
|
|
|
|
writeTextDir = path: text: writeTextFile {
|
|
|
|
|
inherit text;
|
|
|
|
|
name = builtins.baseNameOf path;
|
|
|
|
|
destination = "/${path}";
|
|
|
|
|
};
|
2019-05-06 18:08:23 +01:00
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
2019-06-07 17:28:01 +01:00
|
|
|
|
* Writes a text file to /nix/store/<store path> and marks the file as
|
|
|
|
|
* executable.
|
|
|
|
|
*
|
|
|
|
|
* If passed as a build input, will be used as a setup hook. This makes setup
|
|
|
|
|
* hooks more efficient to create: you don't need a derivation that copies
|
|
|
|
|
* them to $out/nix-support/setup-hook, instead you can use the file as is.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*
|
|
|
|
|
* Example:
|
2019-06-07 17:28:01 +01:00
|
|
|
|
* # Writes my-file to /nix/store/<store path> and makes executable
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* writeScript "my-file"
|
|
|
|
|
* ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
*
|
|
|
|
|
*/
|
2009-11-19 16:07:47 +00:00
|
|
|
|
writeScript = name: text: writeTextFile {inherit name text; executable = true;};
|
2019-05-06 18:08:23 +01:00
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
|
|
|
|
* Writes a text file to /nix/store/<store path>/bin/<name> and
|
|
|
|
|
* marks the file as executable.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
* # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
|
2019-05-06 18:08:23 +01:00
|
|
|
|
* writeScriptBin "my-file"
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
*
|
|
|
|
|
*/
|
2009-11-19 16:07:47 +00:00
|
|
|
|
writeScriptBin = name: text: writeTextFile {inherit name text; executable = true; destination = "/bin/${name}";};
|
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
2019-05-06 18:08:23 +01:00
|
|
|
|
* Similar to writeScript. Writes a Shell script and checks its syntax.
|
|
|
|
|
* Automatically includes interpreter above the contents passed.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
2019-06-29 15:50:02 +01:00
|
|
|
|
* # Writes my-file to /nix/store/<store path> and makes executable.
|
2019-05-06 18:08:23 +01:00
|
|
|
|
* writeShellScript "my-file"
|
|
|
|
|
* ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
writeShellScript = name: text:
|
|
|
|
|
writeTextFile {
|
|
|
|
|
inherit name;
|
|
|
|
|
executable = true;
|
|
|
|
|
text = ''
|
|
|
|
|
#!${runtimeShell}
|
|
|
|
|
${text}
|
|
|
|
|
'';
|
|
|
|
|
checkPhase = ''
|
|
|
|
|
${stdenv.shell} -n $out
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Similar to writeShellScript and writeScriptBin.
|
|
|
|
|
* Writes an executable Shell script to /nix/store/<store path>/bin/<name> and checks its syntax.
|
|
|
|
|
* Automatically includes interpreter above the contents passed.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
* # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
|
2019-05-06 18:08:23 +01:00
|
|
|
|
* writeShellScriptBin "my-file"
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* ''
|
|
|
|
|
* Contents of File
|
|
|
|
|
* '';
|
|
|
|
|
*
|
|
|
|
|
*/
|
2016-01-27 22:26:40 +00:00
|
|
|
|
writeShellScriptBin = name : text :
|
|
|
|
|
writeTextFile {
|
|
|
|
|
inherit name;
|
|
|
|
|
executable = true;
|
|
|
|
|
destination = "/bin/${name}";
|
|
|
|
|
text = ''
|
2019-02-26 11:45:54 +00:00
|
|
|
|
#!${runtimeShell}
|
2016-01-27 22:26:40 +00:00
|
|
|
|
${text}
|
|
|
|
|
'';
|
|
|
|
|
checkPhase = ''
|
2019-04-04 18:31:51 +01:00
|
|
|
|
${stdenv.shell} -n $out/bin/${name}
|
2016-01-27 22:26:40 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
2009-11-19 16:07:47 +00:00
|
|
|
|
|
2018-05-23 08:18:44 +01:00
|
|
|
|
# Create a C binary
|
|
|
|
|
writeCBin = name: code:
|
|
|
|
|
runCommandCC name
|
|
|
|
|
{
|
|
|
|
|
inherit name code;
|
|
|
|
|
executable = true;
|
|
|
|
|
passAsFile = ["code"];
|
|
|
|
|
# Pointless to do this on a remote machine.
|
|
|
|
|
preferLocalBuild = true;
|
|
|
|
|
allowSubstitutes = false;
|
|
|
|
|
}
|
|
|
|
|
''
|
|
|
|
|
n=$out/bin/$name
|
|
|
|
|
mkdir -p "$(dirname "$n")"
|
|
|
|
|
mv "$codePath" code.c
|
|
|
|
|
$CC -x c code.c -o "$n"
|
|
|
|
|
'';
|
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
2020-02-14 04:46:49 +00:00
|
|
|
|
* Create a forest of symlinks to the files in `paths'.
|
|
|
|
|
*
|
|
|
|
|
* This creates a single derivation that replicates the directory structure
|
|
|
|
|
* of all the input paths.
|
|
|
|
|
*
|
2020-08-16 09:14:21 +01:00
|
|
|
|
* BEWARE: it may not "work right" when the passed paths contain symlinks to directories.
|
|
|
|
|
*
|
2020-02-14 04:46:49 +00:00
|
|
|
|
* Examples:
|
|
|
|
|
* # adds symlinks of hello to current build.
|
|
|
|
|
* symlinkJoin { name = "myhello"; paths = [ pkgs.hello ]; }
|
|
|
|
|
*
|
|
|
|
|
* # adds symlinks of hello and stack to current build and prints "links added"
|
|
|
|
|
* symlinkJoin { name = "myexample"; paths = [ pkgs.hello pkgs.stack ]; postBuild = "echo links added"; }
|
|
|
|
|
*
|
|
|
|
|
* This creates a derivation with a directory structure like the following:
|
|
|
|
|
*
|
|
|
|
|
* /nix/store/sglsr5g079a5235hy29da3mq3hv8sjmm-myexample
|
|
|
|
|
* |-- bin
|
|
|
|
|
* | |-- hello -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10/bin/hello
|
|
|
|
|
* | `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/bin/stack
|
|
|
|
|
* `-- share
|
|
|
|
|
* |-- bash-completion
|
|
|
|
|
* | `-- completions
|
|
|
|
|
* | `-- stack -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/bash-completion/completions/stack
|
|
|
|
|
* |-- fish
|
|
|
|
|
* | `-- vendor_completions.d
|
|
|
|
|
* | `-- stack.fish -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1/share/fish/vendor_completions.d/stack.fish
|
|
|
|
|
* ...
|
|
|
|
|
*
|
|
|
|
|
* symlinkJoin and linkFarm are similar functions, but they output
|
|
|
|
|
* derivations with different structure.
|
|
|
|
|
*
|
|
|
|
|
* symlinkJoin is used to create a derivation with a familiar directory
|
|
|
|
|
* structure (top-level bin/, share/, etc), but with all actual files being symlinks to
|
|
|
|
|
* the files in the input derivations.
|
|
|
|
|
*
|
|
|
|
|
* symlinkJoin is used many places in nixpkgs to create a single derivation
|
|
|
|
|
* that appears to contain binaries, libraries, documentation, etc from
|
|
|
|
|
* multiple input derivations.
|
|
|
|
|
*
|
|
|
|
|
* linkFarm is instead used to create a simple derivation with symlinks to
|
|
|
|
|
* other derivations. A derivation created with linkFarm is often used in CI
|
|
|
|
|
* as a easy way to build multiple derivations at once.
|
|
|
|
|
*/
|
2016-04-26 13:10:42 +01:00
|
|
|
|
symlinkJoin =
|
2016-07-14 14:30:30 +01:00
|
|
|
|
args_@{ name
|
2016-05-27 11:38:06 +01:00
|
|
|
|
, paths
|
|
|
|
|
, preferLocalBuild ? true
|
|
|
|
|
, allowSubstitutes ? false
|
|
|
|
|
, postBuild ? ""
|
|
|
|
|
, ...
|
|
|
|
|
}:
|
2016-07-14 14:30:30 +01:00
|
|
|
|
let
|
|
|
|
|
args = removeAttrs args_ [ "name" "postBuild" ]
|
2020-02-17 10:45:44 +00:00
|
|
|
|
// {
|
|
|
|
|
inherit preferLocalBuild allowSubstitutes;
|
|
|
|
|
passAsFile = [ "paths" ];
|
|
|
|
|
}; # pass the defaults
|
2016-07-14 14:30:30 +01:00
|
|
|
|
in runCommand name args
|
2009-11-19 16:07:47 +00:00
|
|
|
|
''
|
|
|
|
|
mkdir -p $out
|
2020-02-17 10:45:44 +00:00
|
|
|
|
for i in $(cat $pathsPath); do
|
2017-05-27 21:17:35 +01:00
|
|
|
|
${lndir}/bin/lndir -silent $i $out
|
2009-11-19 16:07:47 +00:00
|
|
|
|
done
|
2016-04-26 13:10:42 +01:00
|
|
|
|
${postBuild}
|
2009-11-19 16:07:47 +00:00
|
|
|
|
'';
|
|
|
|
|
|
2020-02-14 04:46:49 +00:00
|
|
|
|
/*
|
|
|
|
|
* Quickly create a set of symlinks to derivations.
|
|
|
|
|
*
|
|
|
|
|
* This creates a simple derivation with symlinks to all inputs.
|
|
|
|
|
*
|
|
|
|
|
* entries is a list of attribute sets like
|
|
|
|
|
* { name = "name" ; path = "/nix/store/..."; }
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
*
|
|
|
|
|
* # Symlinks hello and stack paths in store to current $out/hello-test and
|
|
|
|
|
* # $out/foobar.
|
|
|
|
|
* linkFarm "myexample" [ { name = "hello-test"; path = pkgs.hello; } { name = "foobar"; path = pkgs.stack; } ]
|
|
|
|
|
*
|
|
|
|
|
* This creates a derivation with a directory structure like the following:
|
|
|
|
|
*
|
|
|
|
|
* /nix/store/qc5728m4sa344mbks99r3q05mymwm4rw-myexample
|
|
|
|
|
* |-- foobar -> /nix/store/6lzdpxshx78281vy056lbk553ijsdr44-stack-2.1.3.1
|
|
|
|
|
* `-- hello-test -> /nix/store/qy93dp4a3rqyn2mz63fbxjg228hffwyw-hello-2.10
|
|
|
|
|
*
|
|
|
|
|
* See the note on symlinkJoin for the difference between linkFarm and symlinkJoin.
|
|
|
|
|
*/
|
|
|
|
|
linkFarm = name: entries: runCommand name { preferLocalBuild = true; allowSubstitutes = false; }
|
|
|
|
|
''mkdir -p $out
|
|
|
|
|
cd $out
|
|
|
|
|
${lib.concatMapStrings (x: ''
|
|
|
|
|
mkdir -p "$(dirname ${lib.escapeShellArg x.name})"
|
|
|
|
|
ln -s ${lib.escapeShellArg x.path} ${lib.escapeShellArg x.name}
|
|
|
|
|
'') entries}
|
|
|
|
|
'';
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Easily create a linkFarm from a set of derivations.
|
|
|
|
|
*
|
|
|
|
|
* This calls linkFarm with a list of entries created from the list of input
|
|
|
|
|
* derivations. It turns each input derivation into an attribute set
|
|
|
|
|
* like { name = drv.name ; path = drv }, and passes this to linkFarm.
|
|
|
|
|
*
|
|
|
|
|
* Example:
|
|
|
|
|
*
|
|
|
|
|
* # Symlinks the hello, gcc, and ghc derivations in $out
|
|
|
|
|
* linkFarmFromDrvs "myexample" [ pkgs.hello pkgs.gcc pkgs.ghc ]
|
|
|
|
|
*
|
|
|
|
|
* This creates a derivation with a directory structure like the following:
|
|
|
|
|
*
|
|
|
|
|
* /nix/store/m3s6wkjy9c3wy830201bqsb91nk2yj8c-myexample
|
|
|
|
|
* |-- gcc-wrapper-9.2.0 -> /nix/store/fqhjxf9ii4w4gqcsx59fyw2vvj91486a-gcc-wrapper-9.2.0
|
|
|
|
|
* |-- ghc-8.6.5 -> /nix/store/gnf3s07bglhbbk4y6m76sbh42siym0s6-ghc-8.6.5
|
|
|
|
|
* `-- hello-2.10 -> /nix/store/k0ll91c4npk4lg8lqhx00glg2m735g74-hello-2.10
|
|
|
|
|
*/
|
|
|
|
|
linkFarmFromDrvs = name: drvs:
|
|
|
|
|
let mkEntryFromDrv = drv: { name = drv.name; path = drv; };
|
|
|
|
|
in linkFarm name (map mkEntryFromDrv drvs);
|
|
|
|
|
|
2009-11-19 16:07:47 +00:00
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/*
|
|
|
|
|
* Make a package that just contains a setup hook with the given contents.
|
|
|
|
|
* This setup hook will be invoked by any package that includes this package
|
|
|
|
|
* as a buildInput. Optionally takes a list of substitutions that should be
|
|
|
|
|
* applied to the resulting script.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
|
|
|
|
* # setup hook that depends on the hello package and runs ./myscript.sh
|
|
|
|
|
* myhellohook = makeSetupHook { deps = [ hello ]; } ./myscript.sh;
|
|
|
|
|
*
|
|
|
|
|
* # wrotes a setup hook where @bash@ myscript.sh is substituted for the
|
2019-02-26 11:45:54 +00:00
|
|
|
|
* # bash interpreter.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* myhellohookSub = makeSetupHook {
|
|
|
|
|
* deps = [ hello ];
|
|
|
|
|
* substitutions = { bash = "${pkgs.bash}/bin/bash"; };
|
|
|
|
|
* } ./myscript.sh;
|
|
|
|
|
*/
|
2017-12-19 01:41:31 +00:00
|
|
|
|
makeSetupHook = { name ? "hook", deps ? [], substitutions ? {} }: script:
|
|
|
|
|
runCommand name substitutions
|
2011-03-28 17:33:33 +01:00
|
|
|
|
(''
|
2012-01-18 20:16:00 +00:00
|
|
|
|
mkdir -p $out/nix-support
|
2009-11-19 16:07:47 +00:00
|
|
|
|
cp ${script} $out/nix-support/setup-hook
|
2014-10-27 09:25:35 +00:00
|
|
|
|
'' + lib.optionalString (deps != []) ''
|
2017-11-17 18:26:21 +00:00
|
|
|
|
printWords ${toString deps} > $out/nix-support/propagated-build-inputs
|
2014-10-27 09:25:35 +00:00
|
|
|
|
'' + lib.optionalString (substitutions != {}) ''
|
2011-03-29 16:19:59 +01:00
|
|
|
|
substituteAll ${script} $out/nix-support/setup-hook
|
2011-03-28 17:33:33 +01:00
|
|
|
|
'');
|
2009-11-19 16:07:47 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Write the references (i.e. the runtime dependencies in the Nix store) of `path' to a file.
|
2017-10-30 17:13:50 +00:00
|
|
|
|
|
2009-11-19 16:07:47 +00:00
|
|
|
|
writeReferencesToFile = path: runCommand "runtime-deps"
|
|
|
|
|
{
|
|
|
|
|
exportReferencesGraph = ["graph" path];
|
|
|
|
|
}
|
|
|
|
|
''
|
|
|
|
|
touch $out
|
|
|
|
|
while read path; do
|
|
|
|
|
echo $path >> $out
|
|
|
|
|
read dummy
|
|
|
|
|
read nrRefs
|
|
|
|
|
for ((i = 0; i < nrRefs; i++)); do read ref; done
|
|
|
|
|
done < graph
|
|
|
|
|
'';
|
|
|
|
|
|
2021-05-14 16:27:25 +01:00
|
|
|
|
/*
|
|
|
|
|
Write the set of references to a file, that is, their immediate dependencies.
|
|
|
|
|
|
|
|
|
|
This produces the equivalent of `nix-store -q --references`.
|
|
|
|
|
*/
|
|
|
|
|
writeDirectReferencesToFile = path: runCommand "runtime-references"
|
|
|
|
|
{
|
|
|
|
|
exportReferencesGraph = ["graph" path];
|
|
|
|
|
inherit path;
|
|
|
|
|
}
|
|
|
|
|
''
|
|
|
|
|
touch ./references
|
|
|
|
|
while read p; do
|
|
|
|
|
read dummy
|
|
|
|
|
read nrRefs
|
|
|
|
|
if [[ $p == $path ]]; then
|
|
|
|
|
for ((i = 0; i < nrRefs; i++)); do
|
|
|
|
|
read ref;
|
|
|
|
|
echo $ref >>./references
|
|
|
|
|
done
|
|
|
|
|
else
|
|
|
|
|
for ((i = 0; i < nrRefs; i++)); do
|
|
|
|
|
read ref;
|
|
|
|
|
done
|
|
|
|
|
fi
|
|
|
|
|
done < graph
|
|
|
|
|
sort ./references >$out
|
|
|
|
|
'';
|
|
|
|
|
|
2016-09-27 13:10:36 +01:00
|
|
|
|
|
2017-10-30 17:13:50 +00:00
|
|
|
|
/* Print an error message if the file with the specified name and
|
|
|
|
|
* hash doesn't exist in the Nix store. This function should only
|
|
|
|
|
* be used by non-redistributable software with an unfree license
|
|
|
|
|
* that we need to require the user to download manually. It produces
|
|
|
|
|
* packages that cannot be built automatically.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
2019-02-26 11:45:54 +00:00
|
|
|
|
*
|
2017-10-30 17:13:50 +00:00
|
|
|
|
* requireFile {
|
|
|
|
|
* name = "my-file";
|
|
|
|
|
* url = "http://example.com/download/";
|
|
|
|
|
* sha256 = "ffffffffffffffffffffffffffffffffffffffffffffffffffff";
|
|
|
|
|
* }
|
|
|
|
|
*/
|
2015-07-08 11:24:38 +01:00
|
|
|
|
requireFile = { name ? null
|
|
|
|
|
, sha256 ? null
|
|
|
|
|
, sha1 ? null
|
|
|
|
|
, url ? null
|
|
|
|
|
, message ? null
|
2018-05-16 07:41:13 +01:00
|
|
|
|
, hashMode ? "flat"
|
2015-07-08 11:24:38 +01:00
|
|
|
|
} :
|
2010-05-03 10:13:17 +01:00
|
|
|
|
assert (message != null) || (url != null);
|
2015-07-08 11:24:38 +01:00
|
|
|
|
assert (sha256 != null) || (sha1 != null);
|
|
|
|
|
assert (name != null) || (url != null);
|
2010-05-03 10:13:17 +01:00
|
|
|
|
let msg =
|
|
|
|
|
if message != null then message
|
|
|
|
|
else ''
|
2016-09-27 13:10:36 +01:00
|
|
|
|
Unfortunately, we cannot download file ${name_} automatically.
|
|
|
|
|
Please go to ${url} to download it yourself, and add it to the Nix store
|
2010-05-03 10:13:17 +01:00
|
|
|
|
using either
|
2015-07-08 11:24:38 +01:00
|
|
|
|
nix-store --add-fixed ${hashAlgo} ${name_}
|
2010-05-03 10:13:17 +01:00
|
|
|
|
or
|
2016-01-14 13:13:51 +00:00
|
|
|
|
nix-prefetch-url --type ${hashAlgo} file:///path/to/${name_}
|
2010-05-03 10:13:17 +01:00
|
|
|
|
'';
|
2015-07-08 11:24:38 +01:00
|
|
|
|
hashAlgo = if sha256 != null then "sha256" else "sha1";
|
|
|
|
|
hash = if sha256 != null then sha256 else sha1;
|
|
|
|
|
name_ = if name == null then baseNameOf (toString url) else name;
|
2010-05-03 10:13:17 +01:00
|
|
|
|
in
|
2018-05-22 00:19:29 +01:00
|
|
|
|
stdenvNoCC.mkDerivation {
|
2015-07-08 11:24:38 +01:00
|
|
|
|
name = name_;
|
2018-05-16 07:41:13 +01:00
|
|
|
|
outputHashMode = hashMode;
|
2015-07-08 11:24:38 +01:00
|
|
|
|
outputHashAlgo = hashAlgo;
|
|
|
|
|
outputHash = hash;
|
2016-02-19 12:46:21 +00:00
|
|
|
|
preferLocalBuild = true;
|
2018-06-27 02:47:24 +01:00
|
|
|
|
allowSubstitutes = false;
|
2010-05-03 10:13:17 +01:00
|
|
|
|
builder = writeScript "restrict-message" ''
|
2018-05-22 00:19:29 +01:00
|
|
|
|
source ${stdenvNoCC}/setup
|
2016-02-19 12:46:21 +00:00
|
|
|
|
cat <<_EOF_
|
2010-05-03 10:13:17 +01:00
|
|
|
|
|
2016-02-19 12:46:21 +00:00
|
|
|
|
***
|
|
|
|
|
${msg}
|
|
|
|
|
***
|
2010-05-03 10:13:17 +01:00
|
|
|
|
|
2016-02-19 12:46:21 +00:00
|
|
|
|
_EOF_
|
2018-04-15 13:58:05 +01:00
|
|
|
|
exit 1
|
2010-05-03 10:13:17 +01:00
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-27 13:10:36 +01:00
|
|
|
|
|
2015-12-16 21:00:44 +00:00
|
|
|
|
# Copy a path to the Nix store.
|
2016-03-01 14:26:01 +00:00
|
|
|
|
# Nix automatically copies files to the store before stringifying paths.
|
|
|
|
|
# If you need the store path of a file, ${copyPathToStore <path>} can be
|
|
|
|
|
# shortened to ${<path>}.
|
2015-12-16 21:00:44 +00:00
|
|
|
|
copyPathToStore = builtins.filterSource (p: t: true);
|
|
|
|
|
|
2016-09-27 13:10:36 +01:00
|
|
|
|
|
2015-12-16 21:00:44 +00:00
|
|
|
|
# Copy a list of paths to the Nix store.
|
|
|
|
|
copyPathsToStore = builtins.map copyPathToStore;
|
|
|
|
|
|
2019-09-02 10:13:19 +01:00
|
|
|
|
/* Applies a list of patches to a source directory.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
|
|
|
|
*
|
|
|
|
|
* # Patching nixpkgs:
|
|
|
|
|
* applyPatches {
|
|
|
|
|
* src = pkgs.path;
|
|
|
|
|
* patches = [
|
|
|
|
|
* (pkgs.fetchpatch {
|
|
|
|
|
* url = "https://github.com/NixOS/nixpkgs/commit/1f770d20550a413e508e081ddc08464e9d08ba3d.patch";
|
|
|
|
|
* sha256 = "1nlzx171y3r3jbk0qhvnl711kmdk57jlq4na8f8bs8wz2pbffymr";
|
|
|
|
|
* })
|
|
|
|
|
* ];
|
|
|
|
|
* }
|
|
|
|
|
*/
|
|
|
|
|
applyPatches =
|
|
|
|
|
{ src
|
|
|
|
|
, name ? (if builtins.typeOf src == "path"
|
|
|
|
|
then builtins.baseNameOf src
|
|
|
|
|
else
|
|
|
|
|
if builtins.isAttrs src && builtins.hasAttr "name" src
|
|
|
|
|
then src.name
|
|
|
|
|
else throw "applyPatches: please supply a `name` argument because a default name can only be computed when the `src` is a path or is an attribute set with a `name` attribute."
|
|
|
|
|
) + "-patched"
|
|
|
|
|
, patches ? []
|
|
|
|
|
, postPatch ? ""
|
|
|
|
|
}: stdenvNoCC.mkDerivation {
|
|
|
|
|
inherit name src patches postPatch;
|
|
|
|
|
preferLocalBuild = true;
|
|
|
|
|
allowSubstitutes = false;
|
|
|
|
|
phases = "unpackPhase patchPhase installPhase";
|
|
|
|
|
installPhase = "cp -R ./ $out";
|
|
|
|
|
};
|
2021-05-06 09:08:08 +01:00
|
|
|
|
|
2021-06-12 16:28:00 +01:00
|
|
|
|
/* An immutable file in the store with a length of 0 bytes. */
|
|
|
|
|
emptyFile = runCommand "empty-file" {
|
|
|
|
|
outputHashAlgo = "sha256";
|
|
|
|
|
outputHashMode = "recursive";
|
|
|
|
|
outputHash = "0ip26j2h11n1kgkz36rl4akv694yz65hr72q4kv4b3lxcbi65b3p";
|
|
|
|
|
preferLocalBuild = true;
|
|
|
|
|
} "touch $out";
|
|
|
|
|
|
|
|
|
|
/* An immutable empty directory in the store. */
|
|
|
|
|
emptyDirectory = runCommand "empty-directory" {
|
|
|
|
|
outputHashAlgo = "sha256";
|
|
|
|
|
outputHashMode = "recursive";
|
|
|
|
|
outputHash = "0sjjj9z1dhilhpc8pq4154czrb79z9cm044jvn75kxcjv6v5l2m5";
|
|
|
|
|
preferLocalBuild = true;
|
|
|
|
|
} "mkdir $out";
|
|
|
|
|
|
2021-05-06 09:08:08 +01:00
|
|
|
|
/* Checks the command output contains the specified version
|
|
|
|
|
*
|
|
|
|
|
* Although simplistic, this test assures that the main program
|
|
|
|
|
* can run. While there's no substitute for a real test case,
|
|
|
|
|
* it does catch dynamic linking errors and such. It also provides
|
|
|
|
|
* some protection against accidentally building the wrong version,
|
|
|
|
|
* for example when using an 'old' hash in a fixed-output derivation.
|
|
|
|
|
*
|
|
|
|
|
* Examples:
|
|
|
|
|
*
|
|
|
|
|
* passthru.tests.version = testVersion { package = hello; };
|
|
|
|
|
*
|
|
|
|
|
* passthru.tests.version = testVersion {
|
|
|
|
|
* package = seaweedfs;
|
|
|
|
|
* command = "weed version";
|
|
|
|
|
* };
|
|
|
|
|
*
|
|
|
|
|
* passthru.tests.version = testVersion {
|
|
|
|
|
* package = key;
|
|
|
|
|
* command = "KeY --help";
|
|
|
|
|
* # Wrong '2.5' version in the code. Drop on next version.
|
|
|
|
|
* version = "2.5";
|
|
|
|
|
* };
|
|
|
|
|
*/
|
|
|
|
|
testVersion =
|
|
|
|
|
{ package,
|
|
|
|
|
command ? "${package.meta.mainProgram or package.pname or package.name} --version",
|
|
|
|
|
version ? package.version,
|
|
|
|
|
}: runCommand "test-version" { nativeBuildInputs = [ package ]; meta.timeout = 60; } ''
|
|
|
|
|
${command} | grep -Fw ${version}
|
|
|
|
|
touch $out
|
|
|
|
|
'';
|
2009-11-19 16:07:47 +00:00
|
|
|
|
}
|