Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1# The Nixpkgs CC is not directly usable, since it doesn't know where
2# the C library and standard header files are. Therefore the compiler
3# produced by that package cannot be installed directly in a user
4# environment and used from the command line. So we use a wrapper
5# script that sets up the right environment variables so that the
6# compiler and the linker just "work".
7
8{ name ? ""
9, lib
10, stdenvNoCC
11, bintools ? null, libc ? null, coreutils ? null, shell ? stdenvNoCC.shell, gnugrep ? null
12, netbsd ? null, netbsdCross ? null
13, sharedLibraryLoader ?
14 if libc == null then
15 null
16 else if stdenvNoCC.targetPlatform.isNetBSD then
17 if !(targetPackages ? netbsdCross) then
18 netbsd.ld_elf_so
19 else if libc != targetPackages.netbsdCross.headers then
20 targetPackages.netbsdCross.ld_elf_so
21 else
22 null
23 else
24 lib.getLib libc
25, nativeTools, noLibc ? false, nativeLibc, nativePrefix ? ""
26, propagateDoc ? bintools != null && bintools ? man
27, extraPackages ? [], extraBuildCommands ? ""
28, isGNU ? bintools.isGNU or false
29, isLLVM ? bintools.isLLVM or false
30, isCCTools ? bintools.isCCTools or false
31, buildPackages ? {}
32, targetPackages ? {}
33, useMacosReexportHack ? false
34, wrapGas ? false
35
36# Darwin code signing support utilities
37, postLinkSignHook ? null, signingUtils ? null
38}:
39
40with lib;
41
42assert nativeTools -> !propagateDoc && nativePrefix != "";
43assert !nativeTools ->
44 bintools != null && coreutils != null && gnugrep != null;
45assert !(nativeLibc && noLibc);
46assert (noLibc || nativeLibc) == (libc == null);
47
48let
49 stdenv = stdenvNoCC;
50 inherit (stdenv) hostPlatform targetPlatform;
51
52 # Prefix for binaries. Customarily ends with a dash separator.
53 #
54 # TODO(@Ericson2314) Make unconditional, or optional but always true by
55 # default.
56 targetPrefix = lib.optionalString (targetPlatform != hostPlatform)
57 (targetPlatform.config + "-");
58
59 bintoolsVersion = lib.getVersion bintools;
60 bintoolsName = lib.removePrefix targetPrefix (lib.getName bintools);
61
62 libc_bin = if libc == null then "" else getBin libc;
63 libc_dev = if libc == null then "" else getDev libc;
64 libc_lib = if libc == null then "" else getLib libc;
65 bintools_bin = if nativeTools then "" else getBin bintools;
66 # The wrapper scripts use 'cat' and 'grep', so we may need coreutils.
67 coreutils_bin = if nativeTools then "" else getBin coreutils;
68
69 # See description in cc-wrapper.
70 suffixSalt = replaceStrings ["-" "."] ["_" "_"] targetPlatform.config;
71
72 # The dynamic linker has different names on different platforms. This is a
73 # shell glob that ought to match it.
74 dynamicLinker =
75 /**/ if sharedLibraryLoader == null then ""
76 else if targetPlatform.libc == "musl" then "${sharedLibraryLoader}/lib/ld-musl-*"
77 else if targetPlatform.libc == "uclibc" then "${sharedLibraryLoader}/lib/ld*-uClibc.so.1"
78 else if (targetPlatform.libc == "bionic" && targetPlatform.is32bit) then "/system/bin/linker"
79 else if (targetPlatform.libc == "bionic" && targetPlatform.is64bit) then "/system/bin/linker64"
80 else if targetPlatform.libc == "nblibc" then "${sharedLibraryLoader}/libexec/ld.elf_so"
81 else if targetPlatform.system == "i686-linux" then "${sharedLibraryLoader}/lib/ld-linux.so.2"
82 else if targetPlatform.system == "x86_64-linux" then "${sharedLibraryLoader}/lib/ld-linux-x86-64.so.2"
83 else if targetPlatform.system == "powerpc64le-linux" then "${sharedLibraryLoader}/lib/ld64.so.2"
84 # ARM with a wildcard, which can be "" or "-armhf".
85 else if (with targetPlatform; isAarch32 && isLinux) then "${sharedLibraryLoader}/lib/ld-linux*.so.3"
86 else if targetPlatform.system == "aarch64-linux" then "${sharedLibraryLoader}/lib/ld-linux-aarch64.so.1"
87 else if targetPlatform.system == "powerpc-linux" then "${sharedLibraryLoader}/lib/ld.so.1"
88 else if targetPlatform.isMips then "${sharedLibraryLoader}/lib/ld.so.1"
89 # `ld-linux-riscv{32,64}-<abi>.so.1`
90 else if targetPlatform.isRiscV then "${sharedLibraryLoader}/lib/ld-linux-riscv*.so.1"
91 else if targetPlatform.isLoongArch64 then "${sharedLibraryLoader}/lib/ld-linux-loongarch*.so.1"
92 else if targetPlatform.isDarwin then "/usr/lib/dyld"
93 else if targetPlatform.isFreeBSD then "/libexec/ld-elf.so.1"
94 else if lib.hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1"
95 else "";
96
97 expand-response-params =
98 lib.optionalString (buildPackages ? stdenv && buildPackages.stdenv.hasCC && buildPackages.stdenv.cc != "/dev/null")
99 (import ../expand-response-params { inherit (buildPackages) stdenv; });
100
101in
102
103stdenv.mkDerivation {
104 pname = targetPrefix
105 + (if name != "" then name else "${bintoolsName}-wrapper");
106 version = if bintools == null then "" else bintoolsVersion;
107
108 preferLocalBuild = true;
109
110 outputs = [ "out" ] ++ optionals propagateDoc ([ "man" ] ++ optional (bintools ? info) "info");
111
112 passthru = {
113 inherit targetPrefix suffixSalt;
114 inherit bintools libc nativeTools nativeLibc nativePrefix isGNU isLLVM;
115
116 emacsBufferSetup = pkgs: ''
117 ; We should handle propagation here too
118 (mapc
119 (lambda (arg)
120 (when (file-directory-p (concat arg "/lib"))
121 (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib")))
122 (when (file-directory-p (concat arg "/lib64"))
123 (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib64"))))
124 '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)}))
125 '';
126 };
127
128 dontBuild = true;
129 dontConfigure = true;
130
131 enableParallelBuilding = true;
132
133 unpackPhase = ''
134 src=$PWD
135 '';
136
137 installPhase =
138 ''
139 mkdir -p $out/bin $out/nix-support
140
141 wrap() {
142 local dst="$1"
143 local wrapper="$2"
144 export prog="$3"
145 export use_response_file_by_default=${if isCCTools then "1" else "0"}
146 substituteAll "$wrapper" "$out/bin/$dst"
147 chmod +x "$out/bin/$dst"
148 }
149 ''
150
151 + (if nativeTools then ''
152 echo ${nativePrefix} > $out/nix-support/orig-bintools
153
154 ldPath="${nativePrefix}/bin"
155 '' else ''
156 echo $bintools_bin > $out/nix-support/orig-bintools
157
158 ldPath="${bintools_bin}/bin"
159 ''
160
161 # Solaris needs an additional ld wrapper.
162 + optionalString (targetPlatform.isSunOS && nativePrefix != "") ''
163 ldPath="${nativePrefix}/bin"
164 exec="$ldPath/${targetPrefix}ld"
165 wrap ld-solaris ${./ld-solaris-wrapper.sh}
166 '')
167
168 # If we are asked to wrap `gas` and this bintools has it,
169 # then symlink it (`as` will be symlinked next).
170 # This is mainly for the wrapped gnat-bootstrap on x86-64 Darwin,
171 # as it must have both the GNU assembler from cctools (installed as `gas`)
172 # and the Clang integrated assembler (installed as `as`).
173 # See pkgs/os-specific/darwin/binutils/default.nix for details.
174 + lib.optionalString wrapGas ''
175 if [ -e $ldPath/${targetPrefix}gas ]; then
176 ln -s $ldPath/${targetPrefix}gas $out/bin/${targetPrefix}gas
177 fi
178 ''
179
180 # Create symlinks for rest of the binaries.
181 + ''
182 for binary in objdump objcopy size strings as ar nm gprof dwp c++filt addr2line \
183 ranlib readelf elfedit dlltool dllwrap windmc windres; do
184 if [ -e $ldPath/${targetPrefix}''${binary} ]; then
185 ln -s $ldPath/${targetPrefix}''${binary} $out/bin/${targetPrefix}''${binary}
186 fi
187 done
188
189 '' + (if !useMacosReexportHack then ''
190 if [ -e ''${ld:-$ldPath/${targetPrefix}ld} ]; then
191 wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld}
192 fi
193 '' else ''
194 ldInner="${targetPrefix}ld-reexport-delegate"
195 wrap "$ldInner" ${./macos-sierra-reexport-hack.bash} ''${ld:-$ldPath/${targetPrefix}ld}
196 wrap "${targetPrefix}ld" ${./ld-wrapper.sh} "$out/bin/$ldInner"
197 unset ldInner
198 '') + ''
199
200 for variant in $ldPath/${targetPrefix}ld.*; do
201 basename=$(basename "$variant")
202 wrap $basename ${./ld-wrapper.sh} $variant
203 done
204 '';
205
206 strictDeps = true;
207 depsTargetTargetPropagated = extraPackages;
208
209 setupHooks = [
210 ../setup-hooks/role.bash
211 ./setup-hook.sh
212 ];
213
214 postFixup =
215 ##
216 ## General libc support
217 ##
218 optionalString (libc != null) (''
219 touch "$out/nix-support/libc-ldflags"
220 echo "-L${libc_lib}${libc.libdir or "/lib"}" >> $out/nix-support/libc-ldflags
221
222 echo "${libc_lib}" > $out/nix-support/orig-libc
223 echo "${libc_dev}" > $out/nix-support/orig-libc-dev
224 ''
225
226 ##
227 ## Dynamic linker support
228 ##
229 + optionalString (sharedLibraryLoader != null) ''
230 if [[ -z ''${dynamicLinker+x} ]]; then
231 echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2
232 local dynamicLinker="${sharedLibraryLoader}/lib/ld*.so.?"
233 fi
234 ''
235
236 # Expand globs to fill array of options
237 + ''
238 dynamicLinker=($dynamicLinker)
239
240 case ''${#dynamicLinker[@]} in
241 0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;;
242 1) echo "Using dynamic linker: '$dynamicLinker'" >&2;;
243 *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;;
244 esac
245
246 if [ -n "''${dynamicLinker-}" ]; then
247 echo $dynamicLinker > $out/nix-support/dynamic-linker
248
249 ${if targetPlatform.isDarwin then ''
250 printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook
251 '' else lib.optionalString (sharedLibraryLoader != null) ''
252 if [ -e ${sharedLibraryLoader}/lib/32/ld-linux.so.2 ]; then
253 echo ${sharedLibraryLoader}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32
254 fi
255 touch $out/nix-support/ld-set-dynamic-linker
256 ''}
257 fi
258 '')
259
260 ##
261 ## User env support
262 ##
263
264 # Propagate the underling unwrapped bintools so that if you
265 # install the wrapper, you get tools like objdump (same for any
266 # binaries of libc).
267 + optionalString (!nativeTools) ''
268 printWords ${bintools_bin} ${if libc == null then "" else libc_bin} > $out/nix-support/propagated-user-env-packages
269 ''
270
271 ##
272 ## Man page and info support
273 ##
274 + optionalString propagateDoc (''
275 ln -s ${bintools.man} $man
276 '' + optionalString (bintools ? info) ''
277 ln -s ${bintools.info} $info
278 '')
279
280 ##
281 ## Hardening support
282 ##
283
284 # some linkers on some platforms don't support specific -z flags
285 + ''
286 export hardening_unsupported_flags=""
287 if [[ "$($ldPath/${targetPrefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
288 hardening_unsupported_flags+=" bindnow"
289 fi
290 if [[ "$($ldPath/${targetPrefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then
291 hardening_unsupported_flags+=" relro"
292 fi
293 ''
294
295 + optionalString hostPlatform.isCygwin ''
296 hardening_unsupported_flags+=" pic"
297 ''
298
299 + optionalString targetPlatform.isAvr ''
300 hardening_unsupported_flags+=" relro bindnow"
301 ''
302
303 + optionalString (libc != null && targetPlatform.isAvr) ''
304 for isa in avr5 avr3 avr4 avr6 avr25 avr31 avr35 avr51 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack; do
305 echo "-L${getLib libc}/avr/lib/$isa" >> $out/nix-support/libc-cflags
306 done
307 ''
308
309 + optionalString stdenv.targetPlatform.isDarwin ''
310 echo "-arch ${targetPlatform.darwinArch}" >> $out/nix-support/libc-ldflags
311 ''
312
313 ##
314 ## GNU specific extra strip flags
315 ##
316
317 # TODO(@sternenseemann): make a generic strip wrapper?
318 + optionalString (bintools.isGNU or false) ''
319 wrap ${targetPrefix}strip ${./gnu-binutils-strip-wrapper.sh} \
320 "${bintools_bin}/bin/${targetPrefix}strip"
321 ''
322
323 ###
324 ### Remove LC_UUID
325 ###
326 + optionalString (stdenv.targetPlatform.isDarwin && !(bintools.isGNU or false)) ''
327 echo "-no_uuid" >> $out/nix-support/libc-ldflags-before
328 ''
329
330 + ''
331 for flags in "$out/nix-support"/*flags*; do
332 substituteInPlace "$flags" --replace $'\n' ' '
333 done
334
335 substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
336 substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh
337 substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash
338 ''
339
340 ###
341 ### Ensure consistent LC_VERSION_MIN_MACOSX
342 ###
343 + optionalString stdenv.targetPlatform.isDarwin (
344 let
345 inherit (stdenv.targetPlatform)
346 darwinPlatform darwinSdkVersion
347 darwinMinVersion darwinMinVersionVariable;
348 in ''
349 export darwinPlatform=${darwinPlatform}
350 export darwinMinVersion=${darwinMinVersion}
351 export darwinSdkVersion=${darwinSdkVersion}
352 export darwinMinVersionVariable=${darwinMinVersionVariable}
353 substituteAll ${./add-darwin-ldflags-before.sh} $out/nix-support/add-local-ldflags-before.sh
354 ''
355 )
356
357 ##
358 ## Code signing on Apple Silicon
359 ##
360 + optionalString (targetPlatform.isDarwin && targetPlatform.isAarch64) ''
361 echo 'source ${postLinkSignHook}' >> $out/nix-support/post-link-hook
362
363 export signingUtils=${signingUtils}
364
365 wrap \
366 ${targetPrefix}install_name_tool \
367 ${./darwin-install_name_tool-wrapper.sh} \
368 "${bintools_bin}/bin/${targetPrefix}install_name_tool"
369
370 wrap \
371 ${targetPrefix}strip ${./darwin-strip-wrapper.sh} \
372 "${bintools_bin}/bin/${targetPrefix}strip"
373 ''
374
375 ##
376 ## Extra custom steps
377 ##
378 + extraBuildCommands;
379
380 env = {
381 # for substitution in utils.bash
382 expandResponseParams = "${expand-response-params}/bin/expand-response-params";
383 shell = getBin shell + shell.shellPath or "";
384 gnugrep_bin = if nativeTools then "" else gnugrep;
385 wrapperName = "BINTOOLS_WRAPPER";
386 inherit dynamicLinker targetPrefix suffixSalt coreutils_bin;
387 inherit bintools_bin libc_bin libc_dev libc_lib;
388 };
389
390 meta =
391 let bintools_ = if bintools != null then bintools else {}; in
392 (if bintools_ ? meta then removeAttrs bintools.meta ["priority"] else {}) //
393 { description =
394 lib.attrByPath ["meta" "description"] "System binary utilities" bintools_
395 + " (wrapper script)";
396 priority = 10;
397 } // optionalAttrs useMacosReexportHack {
398 platforms = lib.platforms.darwin;
399 };
400}