makeWrapper: --add-flag and --append-flag arguments

also:

manual: differences in makeWrapper implementations better explained

Update pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/build-support/setup-hooks/make-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/build-support/setup-hooks/make-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/build-support/setup-hooks/make-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/build-support/setup-hooks/make-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>

Update pkgs/build-support/setup-hooks/make-wrapper.sh

Co-authored-by: Naïm Camille Favier <n@monade.li>
This commit is contained in:
BirdeeHub 2025-04-21 14:18:21 -07:00
parent f378b788da
commit 7b9c6346ff
7 changed files with 97 additions and 41 deletions

View file

@ -1129,12 +1129,15 @@ They cannot be overridden without rebuilding the package.
If dependencies should be resolved at runtime, use `--suffix` to append fallback values to `PATH`.
Theres many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/build-support/setup-hooks/make-binary-wrapper/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
Theres many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
`wrapProgram` is a convenience function you probably want to use most of the time, implemented by both `makeWrapper` and `makeBinaryWrapper`.
Using the `makeBinaryWrapper` implementation is usually preferred, as it creates a tiny _compiled_ wrapper executable, that can be used as a shebang interpreter. This is needed mostly on Darwin, where shebangs cannot point to scripts, [due to a limitation with the `execve`-syscall](https://stackoverflow.com/questions/67100831/macos-shebang-with-absolute-path-not-working). Compiled wrappers generated by `makeBinaryWrapper` can be inspected with `less <path-to-wrapper>` - by scrolling past the binary data you should be able to see the shell command that generated the executable and there see the environment variables that were injected into the wrapper.
However, `makeWrapper` is more flexible and implements more arguments.
Use `makeWrapper` if you need the wrapper to use shell features (e.g. look up environment variables) at runtime.
### `remove-references-to -t` \<storepath\> [ `-t` \<storepath\> ... ] \<file\> ... {#fun-remove-references-to}
Removes the references of the specified files to the specified store files. This is done without changing the size of the file by replacing the hash by `eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`, and should work on compiled executables. This is meant to be used to remove the dependency of the output on inputs that are known to be unnecessary at runtime. Of course, reckless usage will break the patched programs.

View file

@ -22,10 +22,12 @@ assertExecutable() {
# --unset VAR : remove VAR from the environment
# --chdir DIR : change working directory (use instead of --run "cd DIR")
# --run COMMAND : run command before the executable
# --add-flags ARGS : prepend ARGS to the invocation of the executable
# --add-flag ARG : prepend the single argument ARG to the invocation of the executable
# (that is, *before* any arguments passed on the command line)
# --append-flags ARGS : append ARGS to the invocation of the executable
# --append-flag ARG : append the single argument ARG to the invocation of the executable
# (that is, *after* any arguments passed on the command line)
# --add-flags ARGS : prepend ARGS verbatim to the Bash-interpreted invocation of the executable
# --append-flags ARGS : append ARGS verbatim to the Bash-interpreted invocation of the executable
# --prefix ENV SEP VAL : suffix/prefix ENV with VAL, separated by SEP
# --suffix
@ -164,6 +166,14 @@ makeShellWrapper() {
contents="$(cat "$fileName")"
addValue "$p" "$varName" "$separator" "$contents"
done
elif [[ "$p" == "--add-flag" ]]; then
flags=${params[n + 1]@Q}
n=$((n + 1))
flagsBefore="${flagsBefore-} $flags"
elif [[ "$p" == "--append-flag" ]]; then
flags=${params[n + 1]@Q}
n=$((n + 1))
flagsAfter="${flagsAfter-} $flags"
elif [[ "$p" == "--add-flags" ]]; then
flags="${params[$((n + 1))]}"
n=$((n + 1))

View file

@ -25,10 +25,12 @@ assertExecutable() {
# the environment
# --unset VAR : remove VAR from the environment
# --chdir DIR : change working directory (use instead of --run "cd DIR")
# --add-flags ARGS : prepend ARGS to the invocation of the executable
# --add-flag ARG : prepend the single argument ARG to the invocation of the executable
# (that is, *before* any arguments passed on the command line)
# --append-flags ARGS : append ARGS to the invocation of the executable
# --append-flag ARG : append the single argument ARG to the invocation of the executable
# (that is, *after* any arguments passed on the command line)
# --add-flags ARGS : prepend the whitespace-separated list of arguments ARGS to the invocation of the executable
# --append-flags ARGS : append the whitespace-separated list of arguments ARGS to the invocation of the executable
# --prefix ENV SEP VAL : suffix/prefix ENV with VAL, separated by SEP
# --suffix
@ -86,9 +88,9 @@ makeDocumentedCWrapper() {
# makeCWrapper EXECUTABLE ARGS
# ARGS: same as makeWrapper
makeCWrapper() {
local argv0 inherit_argv0 n params cmd main flagsBefore flagsAfter flags executable length
local argv0 inherit_argv0 n params cmd main flags executable length
local uses_prefix uses_suffix uses_assert uses_assert_success uses_stdio uses_asprintf
local resolve_path
local flagsBefore=() flagsAfter=()
executable=$(escapeStringLiteral "$1")
params=("$@")
length=${#params[*]}
@ -147,16 +149,28 @@ makeCWrapper() {
n=$((n + 1))
[ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
;;
--add-flag)
flagsBefore+=("${params[n + 1]}")
uses_assert=1
n=$((n + 1))
[ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
;;
--append-flag)
flagsAfter+=("${params[n + 1]}")
uses_assert=1
n=$((n + 1))
[ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
;;
--add-flags)
flags="${params[n + 1]}"
flagsBefore="$flagsBefore $flags"
read -ra flags <<< "${params[n + 1]}"
flagsBefore+=("${flags[@]}")
uses_assert=1
n=$((n + 1))
[ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
;;
--append-flags)
flags="${params[n + 1]}"
flagsAfter="$flagsAfter $flags"
read -ra flags <<< "${params[n + 1]}"
flagsAfter+=("${flags[@]}")
uses_assert=1
n=$((n + 1))
[ $n -ge "$length" ] && main="$main#error makeCWrapper: $p takes 1 argument"$'\n'
@ -182,7 +196,7 @@ makeCWrapper() {
;;
esac
done
[[ -z "$flagsBefore" && -z "$flagsAfter" ]] || main="$main"${main:+$'\n'}$(addFlags "$flagsBefore" "$flagsAfter")$'\n'$'\n'
(( ${#flagsBefore[@]} + ${#flagsAfter[@]} > 0 )) && main="$main"${main:+$'\n'}$(addFlags flagsBefore flagsAfter)$'\n'$'\n'
[ -z "$inherit_argv0" ] && main="${main}argv[0] = \"${argv0:-${executable}}\";"$'\n'
[ -z "$resolve_argv0" ] || main="${main}argv[0] = resolve_argv0(argv[0]);"$'\n'
main="${main}return execv(\"${executable}\", argv);"$'\n'
@ -203,23 +217,10 @@ makeCWrapper() {
}
addFlags() {
local n flag before after var
local n flag var
# Disable file globbing, since bash will otherwise try to find
# filenames matching the the value to be prefixed/suffixed if
# it contains characters considered wildcards, such as `?` and
# `*`. We want the value as is, except we also want to split
# it on on the separator; hence we can't quote it.
local reenableGlob=0
if [[ ! -o noglob ]]; then
reenableGlob=1
fi
set -o noglob
# shellcheck disable=SC2086
before=($1) after=($2)
if (( reenableGlob )); then
set +o noglob
fi
local -n before=$1
local -n after=$2
var="argv_tmp"
printf '%s\n' "char **$var = calloc(${#before[@]} + argc + ${#after[@]} + 1, sizeof(*$var));"
@ -435,6 +436,14 @@ formatArgs() {
formatArgsLine 1 "$@"
shift 1
;;
--add-flag)
formatArgsLine 1 "$@"
shift 1
;;
--append-flag)
formatArgsLine 1 "$@"
shift 1
;;
--add-flags)
formatArgsLine 1 "$@"
shift 1

View file

@ -3,21 +3,25 @@
#include <assert.h>
int main(int argc, char **argv) {
char **argv_tmp = calloc(6 + argc + 2 + 1, sizeof(*argv_tmp));
char **argv_tmp = calloc(9 + argc + 3 + 1, sizeof(*argv_tmp));
assert(argv_tmp != NULL);
argv_tmp[0] = argv[0];
argv_tmp[1] = "-x";
argv_tmp[2] = "-y";
argv_tmp[3] = "-z";
argv_tmp[4] = "-abc";
argv_tmp[5] = "-g";
argv_tmp[6] = "*.txt";
argv_tmp[5] = "test var here";
argv_tmp[6] = "-g";
argv_tmp[7] = "*.txt";
argv_tmp[8] = "-a";
argv_tmp[9] = "*";
for (int i = 1; i < argc; ++i) {
argv_tmp[6 + i] = argv[i];
argv_tmp[9 + i] = argv[i];
}
argv_tmp[6 + argc + 0] = "-foo";
argv_tmp[6 + argc + 1] = "-bar";
argv_tmp[6 + argc + 2] = NULL;
argv_tmp[9 + argc + 0] = "-foo";
argv_tmp[9 + argc + 1] = "-bar";
argv_tmp[9 + argc + 2] = "test var 2 here";
argv_tmp[9 + argc + 3] = NULL;
argv = argv_tmp;
argv[0] = "/send/me/flags";

View file

@ -1,4 +1,7 @@
--append-flags "-foo -bar" \
--add-flags "-x -y -z" \
--add-flags -abc \
--add-flags "-g *.txt"
--add-flag 'test var here' \
--add-flags "-g *.txt" \
--add-flags "-a *" \
--append-flag 'test var 2 here'

View file

@ -4,7 +4,11 @@ SUBST_ARGV0
-y
-z
-abc
test var here
-g
*.txt
-a
*
-foo
-bar
test var 2 here

View file

@ -28,7 +28,7 @@ let
echo "VAR=$VAR"
'';
wrappedBinaryArgs = writeShellScript "wrapped-args" ''
echo "$@"
printf '%s\n' "$@"
'';
mkWrapperBinary =
@ -46,10 +46,11 @@ let
makeWrapper "${wrapped}" "$out/bin/${name}" ${lib.escapeShellArgs args}
'';
mkArgTest = cmd: toExpect: mkTest cmd (builtins.concatStringsSep "\n" toExpect);
mkTest = cmd: toExpect: ''
output="$(${cmd})"
if [[ "$output" != '${toExpect}' ]]; then
echo "test failed: the output of ${cmd} was '$output', expected '${toExpect}'"
if [[ "$output" != ${lib.escapeShellArg toExpect} ]]; then
echo "test failed: the output of ${cmd} was '$output', expected ${lib.escapeShellArg toExpect}"
echo "the wrapper contents:"
for i in ${cmd}; do
if [[ $i =~ ^test- ]]; then
@ -122,6 +123,16 @@ runCommand "make-wrapper-test"
];
wrapped = wrappedBinaryArgs;
})
(mkWrapperBinary {
name = "test-arg";
args = [
"--add-flag"
"abc 'aaaaa' jkhhjk"
"--append-flag"
"xyz ggg"
];
wrapped = wrappedBinaryArgs;
})
(mkWrapperBinary {
name = "test-prefix";
args = [
@ -225,9 +236,21 @@ runCommand "make-wrapper-test"
+ mkTest "VAR=foo test-unset" "VAR="
# --add-flags and --append-flags work
+ mkTest "test-args" "abc xyz"
+ mkArgTest "test-args" [
"abc"
"xyz"
]
# --add-flag and --append-flag work
+ mkArgTest "test-arg" [
"abc 'aaaaa' jkhhjk"
"xyz ggg"
]
# given flags are kept
+ mkTest "test-args foo" "abc foo xyz"
+ mkArgTest "test-args foo" [
"abc"
"foo"
"xyz"
]
# --run works
+ mkTest "test-run" "bar\nVAR="