diff options
Diffstat (limited to 'pkgs/build-support/trivial-builders.nix')
-rw-r--r-- | pkgs/build-support/trivial-builders.nix | 160 |
1 files changed, 137 insertions, 23 deletions
diff --git a/pkgs/build-support/trivial-builders.nix b/pkgs/build-support/trivial-builders.nix index eab5366e183..6f51ba512c1 100644 --- a/pkgs/build-support/trivial-builders.nix +++ b/pkgs/build-support/trivial-builders.nix @@ -1,27 +1,12 @@ { lib, stdenv, stdenvNoCC, lndir, runtimeShell }: -let - - runCommand' = runLocal: stdenv: name: env: buildCommand: - stdenv.mkDerivation ({ - name = lib.strings.sanitizeDerivationName name; - inherit buildCommand; - passAsFile = [ "buildCommand" ]; - } - // (lib.optionalAttrs runLocal { - preferLocalBuild = true; - allowSubstitutes = false; - }) - // env); - -in - rec { /* Run the shell command `buildCommand' to produce a store path named * `name'. The attributes in `env' are added to the environment - * prior to running the command. By default `runCommand' runs using - * stdenv with no compiler environment. `runCommandCC` + * prior to running the command. By default `runCommand` runs in a + * stdenv with no compiler environment. `runCommandCC` uses the default + * stdenv, `pkgs.stdenv`. * * Examples: * runCommand "name" {envVariable = true;} ''echo hello > $out'' @@ -42,13 +27,64 @@ rec { runCommand = runCommandNoCC; runCommandLocal = runCommandNoCCLocal; - runCommandNoCC = runCommand' false stdenvNoCC; - runCommandNoCCLocal = runCommand' true stdenvNoCC; + runCommandNoCC = name: env: runCommandWith { + stdenv = stdenvNoCC; + runLocal = false; + inherit name; + derivationArgs = env; + }; + runCommandNoCCLocal = name: env: runCommandWith { + stdenv = stdenvNoCC; + runLocal = true; + inherit name; + derivationArgs = env; + }; - runCommandCC = runCommand' false stdenv; + runCommandCC = name: env: runCommandWith { + stdenv = stdenv; + runLocal = false; + inherit name; + derivationArgs = env; + }; # `runCommandCCLocal` left out on purpose. # We shouldn’t force the user to have a cc in scope. + /* 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" ]); + + /* Writes a text file to the nix store. * The contents of text is added to the file in the store. * @@ -80,7 +116,7 @@ rec { , checkPhase ? "" # syntax checks, e.g. for scripts }: runCommand name - { inherit text executable; + { inherit text executable checkPhase; passAsFile = [ "text" ]; # Pointless to do this on a remote machine. preferLocalBuild = true; @@ -96,7 +132,7 @@ rec { echo -n "$text" > "$n" fi - ${checkPhase} + eval "$checkPhase" (test -n "$executable" && chmod +x "$n") || true ''; @@ -402,6 +438,35 @@ rec { done < graph ''; + /* + 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 + ''; + /* Print an error message if the file with the specified name and * hash doesn't exist in the Nix store. This function should only @@ -505,4 +570,53 @@ rec { phases = "unpackPhase patchPhase installPhase"; installPhase = "cp -R ./ $out"; }; + + /* 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"; + + /* 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 + ''; } |