Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion doc/stdenv/stdenv.chapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -1279,7 +1279,8 @@ someVar=$(stripHash $name)

### `wrapProgram` \<executable\> \<makeWrapperArgs\> {#fun-wrapProgram}

Convenience function for `makeWrapper` that replaces `<executable>` with a wrapper that executes the original program. It takes all the same arguments as `makeWrapper`, except for `--inherit-argv0` (used by the `makeBinaryWrapper` implementation) and `--argv0` (used by both `makeWrapper` and `makeBinaryWrapper` wrapper implementations).
Convenience function for `makeWrapper` that replaces `<executable>` with a wrapper that executes the original program. It takes all the same arguments as `makeWrapper`, except for `--inherit-argv0` (used by the `makeBinaryWrapper` implementation), `--resolve-argv0`
(also used by `makeBinaryWrapper`), and `--argv0` (used by both `makeWrapper` and `makeBinaryWrapper` wrapper implementations).

If you will apply it multiple times, it will overwrite the wrapper file and you will end up with double wrapping, which should be avoided.

Expand Down
4 changes: 0 additions & 4 deletions pkgs/build-support/setup-hooks/make-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ assertExecutable() {
# (if unset or empty, defaults to EXECUTABLE)
# --inherit-argv0 : the executable inherits argv0 from the wrapper.
# (use instead of --argv0 '$0')
# --resolve-argv0 : if argv0 doesn't include a / character, resolve it against PATH
# --set VAR VAL : add VAR with value VAL to the executable's environment
# --set-default VAR VAL : like --set, but only adds VAR if not already set in
# the environment
Expand Down Expand Up @@ -188,9 +187,6 @@ makeShellWrapper() {
elif [[ "$p" == "--inherit-argv0" ]]; then
# Whichever comes last of --argv0 and --inherit-argv0 wins
argv0='$0'
elif [[ "$p" == "--resolve-argv0" ]]; then
# this is noop in shell wrappers, since bash will always resolve $0
resolve_argv0=1
else
die "makeWrapper doesn't understand the arg $p"
fi
Expand Down
52 changes: 44 additions & 8 deletions pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ assertExecutable() {
# ARGS:
# --argv0 NAME : set the name of the executed process to NAME
# (if unset or empty, defaults to EXECUTABLE)
# --inherit-argv0 : the executable inherits argv0 from the wrapper.
# --inherit-argv0 : the executable inherits argv0 from the wrapper
# (use instead of --argv0 '$0')
# --resolve-argv0 : if argv0 doesn't include a / character, resolve it against PATH
# --resolve-argv0 : if argv0 doesn't include a / character, resolve it against PATH; then
# always replace its directory with the canonical real path
# --set VAR VAL : add VAR with value VAL to the executable's environment
# --set-default VAR VAL : like --set, but only adds VAR if not already set in
# the environment
Expand Down Expand Up @@ -189,6 +190,9 @@ makeCWrapper() {
# this gets processed after other argv0 flags
uses_stdio=1
uses_string=1
uses_libgen=1
uses_limits=1
uses_unistd=1
resolve_argv0=1
;;
*) # Using an error macro, we will make sure the compiler gives an understandable error message
Expand All @@ -207,6 +211,9 @@ makeCWrapper() {
[ -z "$uses_assert" ] || printf '%s\n' "#include <assert.h>"
[ -z "$uses_stdio" ] || printf '%s\n' "#include <stdio.h>"
[ -z "$uses_string" ] || printf '%s\n' "#include <string.h>"
[ -z "$uses_libgen" ] || printf '%s\n' "#include <libgen.h>"
[ -z "$uses_limits" ] || printf '%s\n' "#include <limits.h>"
[ -z "$uses_unistd" ] || printf '%s\n' "#include <unistd.h>"
[ -z "$uses_assert_success" ] || printf '\n%s\n' "#define assert_success(e) do { if ((e) < 0) { perror(#e); abort(); } } while (0)"
[ -z "$uses_prefix" ] || printf '\n%s\n' "$(setEnvPrefixFn)"
[ -z "$uses_suffix" ] || printf '\n%s\n' "$(setEnvSuffixFn)"
Expand Down Expand Up @@ -352,35 +359,64 @@ void set_env_suffix(char *env, char *sep, char *suffix) {

resolveArgv0Fn() {
printf '%s' "\
char *canonicalize_path(char *path)
{
char *tmp1 = strdup(path);
char *tmp2 = strdup(path);
if (tmp1 == NULL || tmp2 == NULL) {
free(tmp1);
free(tmp2);
return path;
}

char *base = basename(tmp1);
char *dir = dirname(tmp2);

char realdir[PATH_MAX];
const char *dir_final = realpath(dir, realdir) ? realdir : dir;

char *res = malloc(strlen(dir_final) + strlen(base) + 2);
if (res == NULL) {
free(tmp1);
free(tmp2);
return path;
}
sprintf(res, \"%s/%s\", dir_final, base);

free(tmp1);
free(tmp2);
return res;
}

char *resolve_argv0(char *argv0) {
if (strchr(argv0, '/') != NULL) {
return argv0;
return canonicalize_path(argv0);
}
char *path = getenv(\"PATH\");
if (path == NULL) {
return argv0;
return canonicalize_path(argv0);
}
char *path_copy = strdup(path);
if (path_copy == NULL) {
return argv0;
return canonicalize_path(argv0);
}
char *dir = strtok(path_copy, \":\");
while (dir != NULL) {
char *candidate = malloc(strlen(dir) + strlen(argv0) + 2);
if (candidate == NULL) {
free(path_copy);
return argv0;
return canonicalize_path(argv0);
}
sprintf(candidate, \"%s/%s\", dir, argv0);
if (access(candidate, X_OK) == 0) {
free(path_copy);
return candidate;
return canonicalize_path(candidate);
}
free(candidate);
dir = strtok(NULL, \":\");
}
free(path_copy);
return argv0;
return canonicalize_path(argv0);
}
"
}
Expand Down
33 changes: 22 additions & 11 deletions pkgs/development/interpreters/python/wrapper.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
lib,
stdenv,
buildEnv,
runCommand,
makeBinaryWrapper,

# manually pased
Expand All @@ -22,7 +23,11 @@
let
env =
let
paths = requiredPythonModules (extraLibs ++ [ python ]);
paths = requiredPythonModules (extraLibs ++ [ python ]) ++ [
(runCommand "bin" { } ''
mkdir -p $out/bin
'')
];
pythonPath = "${placeholder "out"}/${python.sitePackages}";
pythonExecutable = "${placeholder "out"}/bin/${python.executable}";
in
Expand All @@ -36,21 +41,27 @@ let
nativeBuildInputs = [ makeBinaryWrapper ];

postBuild = ''
if [ -L "$out/bin" ]; then
unlink "$out/bin"
fi
mkdir -p "$out/bin"

for path in ${lib.concatStringsSep " " paths}; do
if [ -d "$path/bin" ]; then
cd "$path/bin"
for prg in *; do
if [ -f "$prg" ]; then
if [ -f "$prg" ] && [ -x "$prg" ]; then
rm -f "$out/bin/$prg"
if [ -x "$prg" ]; then
makeWrapper "$path/bin/$prg" "$out/bin/$prg" --set NIX_PYTHONPREFIX "$out" --set NIX_PYTHONEXECUTABLE ${pythonExecutable} --set NIX_PYTHONPATH ${pythonPath} ${
lib.optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''
} ${lib.concatStringsSep " " makeWrapperArgs}
if [ "$prg" = "${python.executable}" ]; then
makeWrapper "${python.interpreter}" "$out/bin/$prg" \
--inherit-argv0 \
--resolve-argv0 \
${lib.optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''} \
${lib.concatStringsSep " " makeWrapperArgs}
elif [ "$(readlink "$prg")" = "${python.executable}" ]; then
ln -s "${python.executable}" "$out/bin/$prg"
else
makeWrapper "$path/bin/$prg" "$out/bin/$prg" \
--set NIX_PYTHONPREFIX "$out" \
--set NIX_PYTHONEXECUTABLE ${pythonExecutable} \
--set NIX_PYTHONPATH ${pythonPath} \
${lib.optionalString (!permitUserSite) ''--set PYTHONNOUSERSITE "true"''} \
${lib.concatStringsSep " " makeWrapperArgs}
fi
fi
done
Expand Down
Loading