biome: 1.9.2 -> 1.9.3
[NixPkgs.git] / pkgs / build-support / setup-hooks / multiple-outputs.sh
blob45096d833b4277b55d1e404c942d03fbee3c3618
1 # The base package for automatic multiple-output splitting. Used in stdenv as well.
2 preConfigureHooks+=(_multioutConfig)
3 preFixupHooks+=(_multioutDocs)
4 preFixupHooks+=(_multioutDevs)
5 postFixupHooks+=(_multioutPropagateDev)
7 # _assignFirst varName otherVarNames*
9 # Set the value of the variable named $varName to the first of otherVarNames
10 # that refers to a non-empty variable name.
12 # If none of otherVarNames refers to a non-empty variable, the error message is
13 # specific to this function's use case, which is setting up the output variables.
14 _assignFirst() {
15 local varName="$1"
16 local _var
17 local REMOVE=REMOVE # slightly hacky - we allow REMOVE (i.e. not a variable name)
18 shift
19 for _var in "$@"; do
20 if [ -n "${!_var-}" ]; then eval "${varName}"="${_var}"; return; fi
21 done
22 echo
23 echo "error: _assignFirst: could not find a non-empty variable whose name to assign to ${varName}."
24 echo " The following variables were all unset or empty:"
25 echo " $*"
26 if [ -z "${out:-}" ]; then
27 echo ' If you do not want an "out" output in your derivation, make sure to define'
28 echo ' the other specific required outputs. This can be achieved by picking one'
29 echo " of the above as an output."
30 echo ' You do not have to remove "out" if you want to have a different default'
31 echo ' output, because the first output is taken as a default.'
32 echo
34 return 1 # none found
37 # Same as _assignFirst, but only if "$1" = ""
38 _overrideFirst() {
39 if [ -z "${!1-}" ]; then
40 _assignFirst "$@"
45 # Setup chains of sane default values with easy overridability.
46 # The variables are global to be usable anywhere during the build.
47 # Typical usage in package is defining outputBin = "dev";
49 _overrideFirst outputDev "dev" "out"
50 _overrideFirst outputBin "bin" "out"
52 _overrideFirst outputInclude "$outputDev"
54 # so-libs are often among the main things to keep, and so go to $out
55 _overrideFirst outputLib "lib" "out"
57 _overrideFirst outputDoc "doc" "out"
58 _overrideFirst outputDevdoc "devdoc" REMOVE # documentation for developers
59 # man and info pages are small and often useful to distribute with binaries
60 _overrideFirst outputMan "man" "$outputBin"
61 _overrideFirst outputDevman "devman" "devdoc" "$outputMan"
62 _overrideFirst outputInfo "info" "$outputBin"
65 # Add standard flags to put files into the desired outputs.
66 _multioutConfig() {
67 if [ "$(getAllOutputNames)" = "out" ] || [ -z "${setOutputFlags-1}" ]; then return; fi;
69 # try to detect share/doc/${shareDocName}
70 # Note: sadly, $configureScript detection comes later in configurePhase,
71 # and reordering would cause more trouble than worth.
72 if [ -z "${shareDocName:-}" ]; then
73 local confScript="${configureScript:-}"
74 if [ -z "$confScript" ] && [ -x ./configure ]; then
75 confScript=./configure
77 if [ -f "$confScript" ]; then
78 local shareDocName="$(sed -n "s/^PACKAGE_TARNAME='\(.*\)'$/\1/p" < "$confScript")"
80 # PACKAGE_TARNAME sometimes contains garbage.
81 if [ -z "$shareDocName" ] || echo "$shareDocName" | grep -q '[^a-zA-Z0-9_-]'; then
82 shareDocName="$(echo "$name" | sed 's/-[^a-zA-Z].*//')"
86 prependToVar configureFlags \
87 --bindir="${!outputBin}"/bin --sbindir="${!outputBin}"/sbin \
88 --includedir="${!outputInclude}"/include --oldincludedir="${!outputInclude}"/include \
89 --mandir="${!outputMan}"/share/man --infodir="${!outputInfo}"/share/info \
90 --docdir="${!outputDoc}"/share/doc/"${shareDocName}" \
91 --libdir="${!outputLib}"/lib --libexecdir="${!outputLib}"/libexec \
92 --localedir="${!outputLib}"/share/locale
94 prependToVar installFlags \
95 pkgconfigdir="${!outputDev}"/lib/pkgconfig \
96 m4datadir="${!outputDev}"/share/aclocal aclocaldir="${!outputDev}"/share/aclocal
100 # Add rpath prefixes to library paths, and avoid stdenv doing it for $out.
101 _addRpathPrefix "${!outputLib}"
102 NIX_NO_SELF_RPATH=1
105 # Move subpaths that match pattern $1 from under any output/ to the $2 output/
106 # Beware: only globbing patterns are accepted, e.g.: * ? [abc]
107 # A special target "REMOVE" is allowed: moveToOutput foo REMOVE
108 moveToOutput() {
109 local patt="$1"
110 local dstOut="$2"
111 local output
112 for output in $(getAllOutputNames); do
113 if [ "${!output}" = "$dstOut" ]; then continue; fi
114 local srcPath
115 for srcPath in "${!output}"/$patt; do
116 # apply to existing files/dirs, *including* broken symlinks
117 if [ ! -e "$srcPath" ] && [ ! -L "$srcPath" ]; then continue; fi
119 if [ "$dstOut" = REMOVE ]; then
120 echo "Removing $srcPath"
121 rm -r "$srcPath"
122 else
123 local dstPath="$dstOut${srcPath#${!output}}"
124 echo "Moving $srcPath to $dstPath"
126 if [ -d "$dstPath" ] && [ -d "$srcPath" ]
127 then # attempt directory merge
128 # check the case of trying to move an empty directory
129 rmdir "$srcPath" --ignore-fail-on-non-empty
130 if [ -d "$srcPath" ]; then
131 mv -t "$dstPath" "$srcPath"/*
132 rmdir "$srcPath"
134 else # usual move
135 mkdir -p "$(readlink -m "$dstPath/..")"
136 mv "$srcPath" "$dstPath"
140 # remove empty directories, printing iff at least one gets removed
141 local srcParent="$(readlink -m "$srcPath/..")"
142 if [ -n "$(find "$srcParent" -maxdepth 0 -type d -empty 2>/dev/null)" ]; then
143 echo "Removing empty $srcParent/ and (possibly) its parents"
144 rmdir -p --ignore-fail-on-non-empty "$srcParent" \
145 2> /dev/null || true # doesn't ignore failure for some reason
147 done
148 done
151 # Move documentation to the desired outputs.
152 _multioutDocs() {
153 local REMOVE=REMOVE # slightly hacky - we expand ${!outputFoo}
155 moveToOutput share/info "${!outputInfo}"
156 moveToOutput share/doc "${!outputDoc}"
157 moveToOutput share/gtk-doc "${!outputDevdoc}"
158 moveToOutput share/devhelp/books "${!outputDevdoc}"
160 # the default outputMan is in $bin
161 moveToOutput share/man "${!outputMan}"
162 moveToOutput share/man/man3 "${!outputDevman}"
165 # Move development-only stuff to the desired outputs.
166 _multioutDevs() {
167 if [ "$(getAllOutputNames)" = "out" ] || [ -z "${moveToDev-1}" ]; then return; fi;
168 moveToOutput include "${!outputInclude}"
169 # these files are sometimes provided even without using the corresponding tool
170 moveToOutput lib/pkgconfig "${!outputDev}"
171 moveToOutput share/pkgconfig "${!outputDev}"
172 moveToOutput lib/cmake "${!outputDev}"
173 moveToOutput share/aclocal "${!outputDev}"
174 # don't move *.la, as libtool needs them in the directory of the library
176 for f in "${!outputDev}"/{lib,share}/pkgconfig/*.pc; do
177 echo "Patching '$f' includedir to output ${!outputInclude}"
178 sed -i "/^includedir=/s,=\${prefix},=${!outputInclude}," "$f"
179 done
182 # Make the "dev" propagate other outputs needed for development.
183 _multioutPropagateDev() {
184 if [ "$(getAllOutputNames)" = "out" ]; then return; fi;
186 local outputFirst
187 for outputFirst in $(getAllOutputNames); do
188 break
189 done
190 local propagaterOutput="$outputDev"
191 if [ -z "$propagaterOutput" ]; then
192 propagaterOutput="$outputFirst"
195 # Default value: propagate binaries, includes and libraries
196 if [ -z "${propagatedBuildOutputs+1}" ]; then
197 local po_dirty="$outputBin $outputInclude $outputLib"
198 set +o pipefail
199 propagatedBuildOutputs=`echo "$po_dirty" \
200 | tr -s ' ' '\n' | grep -v -F "$propagaterOutput" \
201 | sort -u | tr '\n' ' ' `
202 set -o pipefail
205 # The variable was explicitly set to empty or we resolved it so
206 if [ -z "$propagatedBuildOutputs" ]; then
207 return
210 mkdir -p "${!propagaterOutput}"/nix-support
211 for output in $propagatedBuildOutputs; do
212 echo -n " ${!output}" >> "${!propagaterOutput}"/nix-support/propagated-build-inputs
213 done