139 lines
4.1 KiB
Markdown
139 lines
4.1 KiB
Markdown
|
# Using resholve's Nix API
|
||
|
|
||
|
resholve converts bare executable references in shell scripts to absolute
|
||
|
paths. This will hopefully make its way into the Nixpkgs manual soon, but
|
||
|
until then I'll outline how to use the `resholvePackage` function.
|
||
|
|
||
|
> Fair warning: resholve does *not* aspire to resolving all valid Shell
|
||
|
> scripts. It depends on the OSH/Oil parser, which aims to support most (but
|
||
|
> not all) Bash, and aims to be a ~90% sort of solution.
|
||
|
|
||
|
Let's start with a simple example from one of my own projects:
|
||
|
|
||
|
```nix
|
||
|
{ stdenv, lib, resholvePackage, fetchFromGitHub, bashup-events44, bashInteractive_5, doCheck ? true, shellcheck }:
|
||
|
|
||
|
resholvePackage rec {
|
||
|
pname = "shellswain";
|
||
|
version = "unreleased";
|
||
|
|
||
|
src = fetchFromGitHub {
|
||
|
# ...
|
||
|
};
|
||
|
|
||
|
solutions = {
|
||
|
profile = {
|
||
|
# the only *required* arguments
|
||
|
scripts = [ "bin/shellswain.bash" ];
|
||
|
interpreter = "none";
|
||
|
inputs = [ bashup-events44 ];
|
||
|
};
|
||
|
};
|
||
|
|
||
|
makeFlags = [ "prefix=${placeholder "out"}" ];
|
||
|
|
||
|
inherit doCheck;
|
||
|
checkInputs = [ shellcheck ];
|
||
|
|
||
|
# ...
|
||
|
}
|
||
|
```
|
||
|
|
||
|
I'll focus on the `solutions` attribute, since this is the only part
|
||
|
that differs from other derivations.
|
||
|
|
||
|
Each "solution" (k=v pair)
|
||
|
describes one resholve invocation. For most shell packages, one
|
||
|
invocation will probably be enough. resholve will make you be very
|
||
|
explicit about your script's dependencies, and it may also need your
|
||
|
help sorting out some references or problems that it can't safely
|
||
|
handle on its own.
|
||
|
|
||
|
If you have more than one script, and your scripts need conflicting
|
||
|
directives, you can specify more than one solution to resolve the
|
||
|
scripts separately, but still produce a single package.
|
||
|
|
||
|
Let's take a closer look:
|
||
|
|
||
|
```nix
|
||
|
solutions = {
|
||
|
# each solution has a short name; this is what you'd use to
|
||
|
# override the settings of this solution, and it may also show up
|
||
|
# in (some) error messages.
|
||
|
profile = {
|
||
|
# specify one or more $out-relative script paths (unlike many
|
||
|
# builders, resholve will modify the output files during fixup
|
||
|
# to correctly resolve scripts that source within the package)
|
||
|
scripts = [ "bin/shellswain.bash" ];
|
||
|
# "none" for no shebang, "${bash}/bin/bash" for bash, etc.
|
||
|
interpreter = "none";
|
||
|
# packages resholve should resolve executables from
|
||
|
inputs = [ bashup-events44 ];
|
||
|
};
|
||
|
};
|
||
|
```
|
||
|
|
||
|
resholve has a (growing) number of options for handling more complex
|
||
|
scripts. I won't cover these in excruciating detail here. You can find
|
||
|
more information about these in `man resholve` via `nixpkgs.resholve`.
|
||
|
|
||
|
Instead, we'll look at the general form of the solutions attrset:
|
||
|
|
||
|
```nix
|
||
|
solutions = {
|
||
|
shortname = {
|
||
|
# required
|
||
|
# $out-relative paths to try resolving
|
||
|
scripts = [ "bin/shunit2" ];
|
||
|
# packages to resolve executables from
|
||
|
inputs = [ coreutils gnused gnugrep findutils ];
|
||
|
# path for shebang, or 'none' to omit shebang
|
||
|
interpreter = "${bash}/bin/bash";
|
||
|
|
||
|
# optional
|
||
|
fake = { fake directives };
|
||
|
fix = { fix directives };
|
||
|
keep = { keep directives };
|
||
|
# file to inject before first code-line of script
|
||
|
prologue = file;
|
||
|
# file to inject after last code-line of script
|
||
|
epilogue = file;
|
||
|
# extra command-line flags passed to resholve; generally this API
|
||
|
# should align with what resholve supports, but flags may help if
|
||
|
# you need to override the version of resholve.
|
||
|
flags = [ ];
|
||
|
};
|
||
|
};
|
||
|
```
|
||
|
|
||
|
The main way you'll adjust how resholve handles your scripts are the
|
||
|
fake, fix, and keep directives. The manpage covers their purpose and
|
||
|
how to format them on the command-line, so I'll focus on how you'll
|
||
|
need to translate them into Nix types.
|
||
|
|
||
|
```nix
|
||
|
# --fake 'f:setUp;tearDown builtin:setopt source:/etc/bashrc'
|
||
|
fake = {
|
||
|
function = [ "setUp" "tearDown" ];
|
||
|
builtin = [ "setopt" ];
|
||
|
source = [ "/etc/bashrc" ];
|
||
|
};
|
||
|
|
||
|
# --fix 'aliases xargs:ls $GIT:gix'
|
||
|
fix = {
|
||
|
# all single-word directives use `true` as value
|
||
|
aliases = true;
|
||
|
xargs = [ "ls" ];
|
||
|
"$GIT" = [ "gix" ];
|
||
|
};
|
||
|
|
||
|
# --keep 'which:git;ls .:$HOME $LS:exa /etc/bashrc ~/.bashrc'
|
||
|
keep = {
|
||
|
which = [ "git" "ls" ];
|
||
|
"." = [ "$HOME" ];
|
||
|
"$LS" = [ "exa" ];
|
||
|
"/etc/bashrc" = true;
|
||
|
"~/.bashrc" = true;
|
||
|
};
|
||
|
```
|