summary refs log tree commit diff
path: root/pkgs/build-support/setup-hooks
diff options
context:
space:
mode:
authorTobias Bergkvist <tobias@bergkv.ist>2021-08-23 23:44:57 +0200
committerTobias Bergkvist <tobias@bergkv.ist>2021-08-23 23:44:57 +0200
commitdcba4171d4a7150cbaf90cae7a3e12a8381067a7 (patch)
tree7b2b025acbf675b23b37d4b8c24bab23c2a9759d /pkgs/build-support/setup-hooks
parent1d6428140194b5bac68266ca11a441ed6f63571c (diff)
downloadnixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.tar
nixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.tar.gz
nixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.tar.bz2
nixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.tar.lz
nixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.tar.xz
nixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.tar.zst
nixpkgs-dcba4171d4a7150cbaf90cae7a3e12a8381067a7.zip
Add support for --add-flags, --prefix and --suffix
Diffstat (limited to 'pkgs/build-support/setup-hooks')
-rw-r--r--pkgs/build-support/setup-hooks/make-binary-wrapper.sh124
1 files changed, 109 insertions, 15 deletions
diff --git a/pkgs/build-support/setup-hooks/make-binary-wrapper.sh b/pkgs/build-support/setup-hooks/make-binary-wrapper.sh
index 33310948333..f19edd483cf 100644
--- a/pkgs/build-support/setup-hooks/make-binary-wrapper.sh
+++ b/pkgs/build-support/setup-hooks/make-binary-wrapper.sh
@@ -4,17 +4,21 @@
 
 # ARGS:
 # --argv0       NAME    : set name of executed process to NAME
-#                         (defaults to EXECUTABLE)
+#                         (otherwise it’s called …-wrapped)
 # --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
 # --unset       VAR     : remove VAR from the environment
-#
+# --add-flags   FLAGS   : add FLAGS to invocation of executable
+
+# --prefix          ENV SEP VAL   : suffix/prefix ENV with VAL, separated by SEP
+# --suffix
+
 # To troubleshoot a binary wrapper after you compiled it,
 # use the `strings` command or open the binary file in a text editor.
 makeBinaryWrapper() {
-    makeDocumentedCWrapper "$1" "${@:3}" | gcc -x c -o "$2" -
+    makeDocumentedCWrapper "$1" "${@:3}" | gcc -Os -x c -o "$2" -
 }
 
 # Generate source code for the wrapper in such a way that the wrapper source code
@@ -31,27 +35,39 @@ makeDocumentedCWrapper() {
 # makeCWrapper EXECUTABLE ARGS
 # ARGS: same as makeBinaryWrapper
 makeCWrapper() {
-    local argv0 n params cmd
+    local argv0 n params cmd main flagsBefore flags
     local executable=$(escapeStringLiteral "$1")
     local params=("$@")
 
-    printf "%s\n" "#include <unistd.h>"
-    printf "%s\n" "#include <stdlib.h>"
-    printf "\n%s\n" "int main(int argc, char **argv) {"
-
     for ((n = 1; n < ${#params[*]}; n += 1)); do
         p="${params[$n]}"
         if [[ "$p" == "--set" ]]; then
             cmd=$(setEnv "${params[$((n + 1))]}" "${params[$((n + 2))]}")
+            main="$main    $cmd"$'\n'
             n=$((n + 2))
-            printf "%s\n" "    $cmd"
         elif [[ "$p" == "--set-default" ]]; then
             cmd=$(setDefaultEnv "${params[$((n + 1))]}" "${params[$((n + 2))]}")
+            main="$main    $cmd"$'\n'
             n=$((n + 2))
-            printf "%s\n" "    $cmd"
         elif [[ "$p" == "--unset" ]]; then
             cmd=$(unsetEnv "${params[$((n + 1))]}")
-            printf "%s\n" "    $cmd"
+            main="$main    $cmd"$'\n'
+            n=$((n + 1))
+        elif [[ "$p" == "--prefix" ]]; then
+            cmd=$(setEnvPrefix "${params[$((n + 1))]}" "${params[$((n + 2))]}" "${params[$((n + 3))]}")
+            main="$main    $cmd"$'\n'
+            uses_prefix=1
+            uses_concat3=1
+            n=$((n + 3))
+        elif [[ "$p" == "--suffix" ]]; then
+            cmd=$(setEnvSuffix "${params[$((n + 1))]}" "${params[$((n + 2))]}" "${params[$((n + 3))]}")
+            main="$main    $cmd"$'\n'
+            uses_suffix=1
+            uses_concat3=1
+            n=$((n + 3))
+        elif [[ "$p" == "--add-flags" ]]; then
+            flags="${params[$((n + 1))]}"
+            flagsBefore="$flagsBefore $flags"
             n=$((n + 1))
         elif [[ "$p" == "--argv0" ]]; then
             argv0=$(escapeStringLiteral "${params[$((n + 1))]}")
@@ -61,17 +77,63 @@ makeCWrapper() {
             printf "%s\n" "    #error makeCWrapper did not understand argument ${p}"
         fi
     done
+    [ -z ${flagsBefore+"1"} ] || {
+        flagsBefore=("$flagsBefore")
+        main="$main"$'\n'$(addFlags $flagsBefore)$'\n'$'\n'
+    }
 
-    printf "%s\n" "    argv[0] = \"${argv0:-${executable}}\";"
-    printf "%s\n" "    return execv(\"${executable}\", argv);"
-    printf "%s\n" "}"
+    main="$main    argv[0] = \"${argv0:-${executable}}\";"$'\n'
+    main="$main    return execv(\"${executable}\", argv);"$'\n'
+
+    printf "%s\n" "#include <unistd.h>"
+    printf "%s\n" "#include <stdlib.h>"
+    [ -z "$uses_concat3" ] || printf "\n%s\n" "$(concat3Fn)"
+    [ -z "$uses_prefix" ]  || printf "\n%s\n" "$(setEnvPrefixFn)"
+    [ -z "$uses_suffix" ]  || printf "\n%s\n" "$(setEnvSuffixFn)"
+    printf "\n%s" "int main(int argc, char **argv) {"
+    printf "\n%s" "$main"
+    printf "%s" "}"
+}
+
+addFlags() {
+    local result n flag flags
+    local var="argv_tmp"
+    flags=("$@")
+    for ((n = 0; n < ${#flags[*]}; n += 1)); do
+        flag=$(escapeStringLiteral "${flags[((n))]}")
+        result="$result    $var[$((n+1))] = \"$flag\";"$'\n'
+    done
+    printf "    %s\n" "char **$var = malloc(sizeof(*$var) * ($((n+1)) + argc));"
+    printf "    %s\n" "$var[0] = argv[0];"
+    printf "%s" "$result"
+    printf "    %s\n" "for (int i = 1; i < argc; ++i) {"
+    printf "    %s\n" "    $var[$n + i] = argv[i];"
+    printf "    %s\n" "}"
+    printf "    %s\n" "$var[$n + argc] = NULL;"
+    printf "    %s\n" "argv = $var;"
+}
+
+# prefix ENV SEP VAL
+setEnvPrefix() {
+    local env=$(escapeStringLiteral "$1")
+    local sep=$(escapeStringLiteral "$2")
+    local val=$(escapeStringLiteral "$3")
+    printf "%s" "set_env_prefix(\"$env\", \"$sep\", \"$val\");"
+}
+
+# suffix ENV SEP VAL
+setEnvSuffix() {
+    local env=$(escapeStringLiteral "$1")
+    local sep=$(escapeStringLiteral "$2")
+    local val=$(escapeStringLiteral "$3")
+    printf "%s" "set_env_suffix(\"$env\", \"$sep\", \"$val\");"
 }
 
 # setEnv KEY VALUE
 setEnv() {
     local key=$(escapeStringLiteral "$1")
     local value=$(escapeStringLiteral "$2")
-    printf "%s" "putenv(\"${key}=${value}\");"
+    printf "%s" "putenv(\"$key=$value\");"
 }
 
 # setDefaultEnv KEY VALUE
@@ -104,3 +166,35 @@ escapeStringLiteral() {
     result=${result//$'\r'/"\r"}
     printf "%s" "$result"
 }
+
+concat3Fn() {
+    printf "%s\n" 'char *concat3(char *x, char *y, char *z) {'
+    printf "%s\n" '    int xn = 0; while(x[++xn]);'
+    printf "%s\n" '    int yn = 0; while(y[++yn]);'
+    printf "%s\n" '    int zn = 0; while(z[++zn]);'
+    printf "%s\n" '    char *res = malloc(sizeof(*res)*(xn + yn + zn + 1));'
+    printf "%s\n" '    for (int i = 0; i < xn; ++i) res[i] = x[i];'
+    printf "%s\n" '    for (int i = 0; i < yn; ++i) res[xn+i] = y[i];'
+    printf "%s\n" '    for (int i = 0; i < zn; ++i) res[xn+yn+i] = z[i];'
+    printf "%s\n" "    res[xn+yn+zn] = '\0';"
+    printf "%s\n" '    return res;'
+    printf "%s\n" '}'
+}
+
+setEnvPrefixFn() {
+    printf "%s\n" 'void set_env_prefix(char *env, char *sep, char *val) {'
+    printf "%s\n" '    char *existing = getenv(env);'
+    printf "%s\n" '    if (existing) val = concat3(val, sep, existing);'
+    printf "%s\n" '    setenv(env, val, 1);'
+    printf "%s\n" '    if (existing) free(val);'
+    printf "%s\n" '}'
+}
+
+setEnvSuffixFn() {
+    printf "%s\n" 'void set_env_suffix(char *env, char *sep, char *val) {'
+    printf "%s\n" '    char *existing = getenv(env);'
+    printf "%s\n" '    if (existing) val = concat3(existing, sep, val);'
+    printf "%s\n" '    setenv(env, val, 1);'
+    printf "%s\n" '    if (existing) free(val);'
+    printf "%s\n" '}'
+}