summary refs log tree commit diff
path: root/pkgs/build-support/setup-hooks/auto-patchelf.sh
blob: 0625565606f3ced9623900f727cf9d6b77f19868 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# shellcheck shell=bash

declare -a autoPatchelfLibs
declare -a extraAutoPatchelfLibs

gatherLibraries() {
    autoPatchelfLibs+=("$1/lib")
}

# shellcheck disable=SC2154
# (targetOffset is referenced but not assigned.)
addEnvHooks "$targetOffset" gatherLibraries

# Can be used to manually add additional directories with shared object files
# to be included for the next autoPatchelf invocation.
addAutoPatchelfSearchPath() {
    local -a findOpts=()

    while [ $# -gt 0 ]; do
        case "$1" in
            --) shift; break;;
            --no-recurse) shift; findOpts+=("-maxdepth" 1);;
            --*)
                echo "addAutoPatchelfSearchPath: ERROR: Invalid command line" \
                     "argument: $1" >&2
                return 1;;
            *) break;;
        esac
    done

    local dir=
    while IFS= read -r -d '' dir; do
        extraAutoPatchelfLibs+=("$dir")
    done <  <(find "$@" "${findOpts[@]}" \! -type d \
            \( -name '*.so' -o -name '*.so.*' \) -print0 \
            | sed -z 's#/[^/]*$##' \
            | uniq -z
        )
}


autoPatchelf() {
    local norecurse=
    while [ $# -gt 0 ]; do
        case "$1" in
            --) shift; break;;
            --no-recurse) shift; norecurse=1;;
            --*)
                echo "autoPatchelf: ERROR: Invalid command line" \
                     "argument: $1" >&2
                return 1;;
            *) break;;
        esac
    done

    readarray -td' ' ignoreMissingDepsArray < <(echo -n "$autoPatchelfIgnoreMissingDeps")
    if [ "$autoPatchelfIgnoreMissingDeps" == "1" ]; then
        echo "autoPatchelf: WARNING: setting 'autoPatchelfIgnoreMissingDeps" \
             "= true;' is deprecated and will be removed in a future release." \
             "Use 'autoPatchelfIgnoreMissingDeps = [ \"*\" ];' instead." >&2
        ignoreMissingDepsArray=( "*" )
    fi

    local appendRunpathsArray=($appendRunpaths)
    local runtimeDependenciesArray=($runtimeDependencies)
    @pythonInterpreter@ @autoPatchelfScript@                            \
        ${norecurse:+--no-recurse}                                      \
        --ignore-missing "${ignoreMissingDepsArray[@]}"                 \
        --paths "$@"                                                    \
        --libs "${autoPatchelfLibs[@]}"                                 \
               "${extraAutoPatchelfLibs[@]}"                            \
        --runtime-dependencies "${runtimeDependenciesArray[@]/%//lib}"  \
        --append-rpaths "${appendRunpathsArray[@]}"
}

# XXX: This should ultimately use fixupOutputHooks but we currently don't have
# a way to enforce the order. If we have $runtimeDependencies set, the setup
# hook of patchelf is going to ruin everything and strip out those additional
# RPATHs.
#
# So what we do here is basically run in postFixup and emulate the same
# behaviour as fixupOutputHooks because the setup hook for patchelf is run in
# fixupOutput and the postFixup hook runs later.
#
# shellcheck disable=SC2016
# (Expressions don't expand in single quotes, use double quotes for that.)
postFixupHooks+=('
    if [ -z "${dontAutoPatchelf-}" ]; then
        autoPatchelf -- $(for output in $(getAllOutputNames); do
            [ -e "${!output}" ] || continue
            echo "${!output}"
        done)
    fi
')