Merge pull request #141400 from lovesegfault/writeShellApplication

writeShellApplication: init
This commit is contained in:
Bernardo Meurer 2021-11-09 10:44:11 -08:00 committed by GitHub
commit 342bd7ae59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 83 additions and 4 deletions

View file

@ -47,6 +47,28 @@ These functions write `text` to the Nix store. This is useful for creating scrip
Many more commands wrap `writeTextFile` including `writeText`, `writeTextDir`, `writeScript`, and `writeScriptBin`. These are convenience functions over `writeTextFile`.
## `writeShellApplication` {#trivial-builder-writeShellApplication}
This can be used to easily produce a shell script that has some dependencies (`runtimeInputs`). It automatically sets the `PATH` of the script to contain all of the listed inputs, sets some sanity shellopts (`errexit`, `nounset`, `pipefail`), and checks the resulting script with [`shellcheck`](https://github.com/koalaman/shellcheck).
For example, look at the following code:
```nix
writeShellApplication {
name = "show-nixos-org";
runtimeInputs = [ curl w3m ];
text = ''
curl -s 'https://nixos.org' | w3m -dump -T text/html
'';
}
```
Unlike with normal `writeShellScriptBin`, there is no need to manually write out `${curl}/bin/curl`, setting the PATH
was handled by `writeShellApplication`. Moreover, the script is being checked with `shellcheck` for more strict
validation.
## `symlinkJoin` {#trivial-builder-symlinkJoin}
This can be used to put many derivations into the same directory structure. It works by creating a new derivation and adding symlinks to each of the paths listed. It expects two arguments, `name`, and `paths`. `name` is the name used in the Nix store path for the created derivation. `paths` is a list of paths that will be symlinked. These paths can be to Nix store derivations or any other subdirectory contained within.

View file

@ -1,4 +1,4 @@
{ lib, stdenv, stdenvNoCC, lndir, runtimeShell }:
{ lib, stdenv, stdenvNoCC, lndir, runtimeShell, shellcheck }:
rec {
@ -111,9 +111,10 @@ rec {
, executable ? false # run chmod +x ?
, destination ? "" # relative path appended to $out eg "/bin/foo"
, checkPhase ? "" # syntax checks, e.g. for scripts
, meta ? { }
}:
runCommand name
{ inherit text executable checkPhase;
{ inherit text executable checkPhase meta;
passAsFile = [ "text" ];
# Pointless to do this on a remote machine.
preferLocalBuild = true;
@ -249,6 +250,60 @@ rec {
'';
};
/*
* Similar to writeShellScriptBin and writeScriptBin.
* Writes an executable Shell script to /nix/store/<store path>/bin/<name> and
* checks its syntax with shellcheck and the shell's -n option.
* Automatically includes sane set of shellopts (errexit, nounset, pipefail)
* and handles creation of PATH based on runtimeInputs
*
* Note that the checkPhase uses stdenv.shell for the test run of the script,
* while the generated shebang uses runtimeShell. If, for whatever reason,
* those were to mismatch you might lose fidelity in the default checks.
*
* Example:
* # Writes my-file to /nix/store/<store path>/bin/my-file and makes executable.
* writeShellApplication {
* name = "my-file";
* runtimeInputs = [ curl w3m ];
* text = ''
* curl -s 'https://nixos.org' | w3m -dump -T text/html
* '';
* }
*/
writeShellApplication =
{ name
, text
, runtimeInputs ? [ ]
, checkPhase ? null
}:
writeTextFile {
inherit name;
executable = true;
destination = "/bin/${name}";
text = ''
#!${runtimeShell}
set -o errexit
set -o nounset
set -o pipefail
export PATH="${lib.makeBinPath runtimeInputs}:$PATH"
${text}
'';
checkPhase =
if checkPhase == null then ''
runHook preCheck
${stdenv.shell} -n $out/bin/${name}
${shellcheck}/bin/shellcheck $out/bin/${name}
runHook postCheck
''
else checkPhase;
meta.mainProgram = name;
};
# Create a C binary
writeCBin = name: code:
runCommandCC name

View file

@ -76,8 +76,10 @@ let
trivialBuilders = self: super:
import ../build-support/trivial-builders.nix {
inherit lib; inherit (self) stdenv stdenvNoCC; inherit (self.pkgsBuildHost.xorg) lndir;
inherit (self) runtimeShell;
inherit lib;
inherit (self) runtimeShell stdenv stdenvNoCC;
inherit (self.pkgsBuildHost) shellcheck;
inherit (self.pkgsBuildHost.xorg) lndir;
};
stdenvBootstappingAndPlatforms = self: super: let