Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at python-updates 507 lines 16 kB view raw
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{ 9 name ? "", 10 lib, 11 stdenvNoCC, 12 runtimeShell, 13 bintools ? null, 14 libc ? null, 15 coreutils ? null, 16 gnugrep ? null, 17 apple-sdk ? null, 18 netbsd ? null, 19 sharedLibraryLoader ? 20 if libc == null then 21 null 22 else if stdenvNoCC.targetPlatform.isNetBSD then 23 if !(targetPackages ? netbsd) then 24 netbsd.ld_elf_so 25 else if libc != targetPackages.netbsd.headers then 26 targetPackages.netbsd.ld_elf_so 27 else 28 null 29 else 30 lib.getLib libc, 31 nativeTools, 32 noLibc ? false, 33 nativeLibc, 34 nativePrefix ? "", 35 propagateDoc ? bintools != null && bintools ? man, 36 extraPackages ? [ ], 37 extraBuildCommands ? "", 38 isGNU ? bintools.isGNU or false, 39 isLLVM ? bintools.isLLVM or false, 40 isCCTools ? bintools.isCCTools or false, 41 expand-response-params, 42 targetPackages ? { }, 43 wrapGas ? false, 44 45 # Note: the hardening flags are part of the bintools-wrapper, rather than 46 # the cc-wrapper, because a few of them are handled by the linker. 47 defaultHardeningFlags ? [ 48 "bindnow" 49 "format" 50 "fortify" 51 "fortify3" 52 "pic" 53 "relro" 54 "stackclashprotection" 55 "stackprotector" 56 "strictoverflow" 57 "zerocallusedregs" 58 ] 59 ++ lib.optional ( 60 with stdenvNoCC; 61 lib.any (x: x) [ 62 # OpenBSD static linking requires PIE 63 (with targetPlatform; isOpenBSD && isStatic) 64 (lib.all (x: x) [ 65 # Musl-based platforms will keep "pie", other platforms will not. 66 # If you change this, make sure to update section `{#sec-hardening-in-nixpkgs}` 67 # in the nixpkgs manual to inform users about the defaults. 68 (targetPlatform.libc == "musl") 69 # Except when: 70 # - static aarch64, where compilation works, but produces segfaulting dynamically linked binaries. 71 # - static armv7l, where compilation fails. 72 (!(targetPlatform.isAarch && targetPlatform.isStatic)) 73 ]) 74 ] 75 ) "pie", 76}: 77 78assert propagateDoc -> bintools ? man; 79assert nativeTools -> !propagateDoc && nativePrefix != ""; 80assert !nativeTools -> bintools != null && coreutils != null && gnugrep != null; 81assert !(nativeLibc && noLibc); 82assert (noLibc || nativeLibc) == (libc == null); 83 84let 85 inherit (lib) 86 attrByPath 87 concatStringsSep 88 getBin 89 getDev 90 getLib 91 getName 92 getVersion 93 hasSuffix 94 optional 95 optionalAttrs 96 optionals 97 optionalString 98 platforms 99 removePrefix 100 replaceStrings 101 ; 102 103 inherit (stdenvNoCC) hostPlatform targetPlatform; 104 105 # Prefix for binaries. Customarily ends with a dash separator. 106 # 107 # TODO(@Ericson2314) Make unconditional, or optional but always true by 108 # default. 109 targetPrefix = optionalString (targetPlatform != hostPlatform) (targetPlatform.config + "-"); 110 111 bintoolsVersion = getVersion bintools; 112 bintoolsName = removePrefix targetPrefix (getName bintools); 113 114 libc_bin = optionalString (libc != null) (getBin libc); 115 libc_dev = optionalString (libc != null) (getDev libc); 116 libc_lib = optionalString (libc != null) (getLib libc); 117 bintools_bin = optionalString (!nativeTools) (getBin bintools); 118 # The wrapper scripts use 'cat' and 'grep', so we may need coreutils. 119 coreutils_bin = optionalString (!nativeTools) (getBin coreutils); 120 121 # See description in cc-wrapper. 122 suffixSalt = 123 replaceStrings [ "-" "." ] [ "_" "_" ] targetPlatform.config 124 + lib.optionalString (targetPlatform.isDarwin && targetPlatform.isStatic) "_static"; 125 126 # The dynamic linker has different names on different platforms. This is a 127 # shell glob that ought to match it. 128 dynamicLinker = 129 if sharedLibraryLoader == null then 130 "" 131 else if targetPlatform.libc == "musl" then 132 "${sharedLibraryLoader}/lib/ld-musl-*" 133 else if targetPlatform.libc == "uclibc" then 134 "${sharedLibraryLoader}/lib/ld*-uClibc.so.1" 135 else if (targetPlatform.libc == "bionic" && targetPlatform.is32bit) then 136 "/system/bin/linker" 137 else if (targetPlatform.libc == "bionic" && targetPlatform.is64bit) then 138 "/system/bin/linker64" 139 else if targetPlatform.libc == "nblibc" then 140 "${sharedLibraryLoader}/libexec/ld.elf_so" 141 else if targetPlatform.system == "i686-linux" then 142 "${sharedLibraryLoader}/lib/ld-linux.so.2" 143 else if targetPlatform.system == "x86_64-linux" then 144 "${sharedLibraryLoader}/lib/ld-linux-x86-64.so.2" 145 else if targetPlatform.system == "s390x-linux" then 146 "${sharedLibraryLoader}/lib/ld64.so.1" 147 # ELFv1 (.1) or ELFv2 (.2) ABI 148 else if targetPlatform.isPower64 then 149 "${sharedLibraryLoader}/lib/ld64.so.*" 150 # ARM with a wildcard, which can be "" or "-armhf". 151 else if (with targetPlatform; isAarch32 && isLinux) then 152 "${sharedLibraryLoader}/lib/ld-linux*.so.3" 153 else if targetPlatform.system == "aarch64-linux" then 154 "${sharedLibraryLoader}/lib/ld-linux-aarch64.so.1" 155 else if targetPlatform.system == "powerpc-linux" then 156 "${sharedLibraryLoader}/lib/ld.so.1" 157 else if targetPlatform.system == "s390-linux" then 158 "${sharedLibraryLoader}/lib/ld.so.1" 159 else if targetPlatform.system == "s390x-linux" then 160 "${sharedLibraryLoader}/lib/ld64.so.1" 161 else if targetPlatform.isMips then 162 "${sharedLibraryLoader}/lib/ld.so.1" 163 # `ld-linux-riscv{32,64}-<abi>.so.1` 164 else if targetPlatform.isRiscV then 165 "${sharedLibraryLoader}/lib/ld-linux-riscv*.so.1" 166 else if targetPlatform.isLoongArch64 then 167 "${sharedLibraryLoader}/lib/ld-linux-loongarch*.so.1" 168 else if targetPlatform.isDarwin then 169 "/usr/lib/dyld" 170 else if targetPlatform.isFreeBSD then 171 "${sharedLibraryLoader}/libexec/ld-elf.so.1" 172 else if targetPlatform.isOpenBSD then 173 "${sharedLibraryLoader}/libexec/ld.so" 174 else if hasSuffix "pc-gnu" targetPlatform.config then 175 "ld.so.1" 176 else 177 ""; 178 179in 180 181stdenvNoCC.mkDerivation { 182 pname = targetPrefix + (if name != "" then name else "${bintoolsName}-wrapper"); 183 version = optionalString (bintools != null) bintoolsVersion; 184 185 preferLocalBuild = true; 186 187 outputs = [ "out" ] ++ optionals propagateDoc ([ "man" ] ++ optional (bintools ? info) "info"); 188 189 passthru = { 190 inherit targetPrefix suffixSalt; 191 inherit 192 bintools 193 libc 194 nativeTools 195 nativeLibc 196 nativePrefix 197 isGNU 198 isLLVM 199 ; 200 201 emacsBufferSetup = pkgs: '' 202 ; We should handle propagation here too 203 (mapc 204 (lambda (arg) 205 (when (file-directory-p (concat arg "/lib")) 206 (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib"))) 207 (when (file-directory-p (concat arg "/lib64")) 208 (setenv "NIX_LDFLAGS_${suffixSalt}" (concat (getenv "NIX_LDFLAGS_${suffixSalt}") " -L" arg "/lib64")))) 209 '(${concatStringsSep " " (map (pkg: "\"${pkg}\"") pkgs)})) 210 ''; 211 212 inherit defaultHardeningFlags; 213 }; 214 215 dontBuild = true; 216 dontConfigure = true; 217 218 enableParallelBuilding = true; 219 220 unpackPhase = '' 221 src=$PWD 222 ''; 223 224 installPhase = '' 225 mkdir -p $out/bin $out/nix-support 226 227 wrap() { 228 local dst="$1" 229 local wrapper="$2" 230 export prog="$3" 231 export use_response_file_by_default=${if isCCTools then "1" else "0"} 232 substituteAll "$wrapper" "$out/bin/$dst" 233 chmod +x "$out/bin/$dst" 234 } 235 '' 236 237 + ( 238 if nativeTools then 239 '' 240 echo ${nativePrefix} > $out/nix-support/orig-bintools 241 242 ldPath="${nativePrefix}/bin" 243 '' 244 else 245 '' 246 echo $bintools_bin > $out/nix-support/orig-bintools 247 248 ldPath="${bintools_bin}/bin" 249 '' 250 251 # Solaris needs an additional ld wrapper. 252 + optionalString (targetPlatform.isSunOS && nativePrefix != "") '' 253 ldPath="${nativePrefix}/bin" 254 exec="$ldPath/${targetPrefix}ld" 255 wrap ld-solaris ${./ld-solaris-wrapper.sh} 256 '' 257 ) 258 259 # If we are asked to wrap `gas` and this bintools has it, 260 # then symlink it (`as` will be symlinked next). 261 # This is mainly for the wrapped gnat-bootstrap on x86-64 Darwin, 262 # as it must have both the GNU assembler from cctools (installed as `gas`) 263 # and the Clang integrated assembler (installed as `as`). 264 # See pkgs/os-specific/darwin/binutils/default.nix for details. 265 + optionalString wrapGas '' 266 if [ -e $ldPath/${targetPrefix}gas ]; then 267 ln -s $ldPath/${targetPrefix}gas $out/bin/${targetPrefix}gas 268 fi 269 '' 270 271 # Create symlinks for rest of the binaries. 272 + '' 273 for binary in objdump objcopy size strings as ar nm gprof dwp c++filt addr2line \ 274 ranlib readelf elfedit dlltool dllwrap windmc windres; do 275 if [ -e $ldPath/${targetPrefix}''${binary} ]; then 276 ln -s $ldPath/${targetPrefix}''${binary} $out/bin/${targetPrefix}''${binary} 277 fi 278 done 279 280 if [ -e ''${ld:-$ldPath/${targetPrefix}ld} ]; then 281 wrap ${targetPrefix}ld ${./ld-wrapper.sh} ''${ld:-$ldPath/${targetPrefix}ld} 282 fi 283 284 for variant in $ldPath/${targetPrefix}ld.*; do 285 basename=$(basename "$variant") 286 wrap $basename ${./ld-wrapper.sh} $variant 287 done 288 ''; 289 290 strictDeps = true; 291 depsTargetTargetPropagated = extraPackages; 292 293 setupHooks = [ 294 ../setup-hooks/role.bash 295 ./setup-hook.sh 296 ]; 297 298 postFixup = 299 ## 300 ## General libc support 301 ## 302 optionalString (libc != null) ( 303 '' 304 touch "$out/nix-support/libc-ldflags" 305 echo "-L${libc_lib}${libc.libdir or "/lib"}" >> $out/nix-support/libc-ldflags 306 307 echo "${libc_lib}" > $out/nix-support/orig-libc 308 echo "${libc_dev}" > $out/nix-support/orig-libc-dev 309 '' 310 311 ## 312 ## Dynamic linker support 313 ## 314 + optionalString (sharedLibraryLoader != null) '' 315 if [[ -z ''${dynamicLinker+x} ]]; then 316 echo "Don't know the name of the dynamic linker for platform '${targetPlatform.config}', so guessing instead." >&2 317 local dynamicLinker="${sharedLibraryLoader}/lib/ld*.so.?" 318 fi 319 '' 320 321 # Expand globs to fill array of options 322 + '' 323 dynamicLinker=($dynamicLinker) 324 325 case ''${#dynamicLinker[@]} in 326 0) echo "No dynamic linker found for platform '${targetPlatform.config}'." >&2;; 327 1) echo "Using dynamic linker: '$dynamicLinker'" >&2;; 328 *) echo "Multiple dynamic linkers found for platform '${targetPlatform.config}'." >&2;; 329 esac 330 331 if [ -n "''${dynamicLinker-}" ]; then 332 echo $dynamicLinker > $out/nix-support/dynamic-linker 333 334 ${ 335 if targetPlatform.isDarwin then 336 '' 337 printf "export LD_DYLD_PATH=%q\n" "$dynamicLinker" >> $out/nix-support/setup-hook 338 '' 339 else 340 optionalString (sharedLibraryLoader != null) '' 341 if [ -e ${sharedLibraryLoader}/lib/32/ld-linux.so.2 ]; then 342 echo ${sharedLibraryLoader}/lib/32/ld-linux.so.2 > $out/nix-support/dynamic-linker-m32 343 fi 344 touch $out/nix-support/ld-set-dynamic-linker 345 '' 346 } 347 fi 348 '' 349 ) 350 351 ## 352 ## User env support 353 ## 354 355 # Propagate the underling unwrapped bintools so that if you 356 # install the wrapper, you get tools like objdump (same for any 357 # binaries of libc). 358 + optionalString (!nativeTools) '' 359 printWords ${bintools_bin} ${ 360 optionalString (libc != null) libc_bin 361 } > $out/nix-support/propagated-user-env-packages 362 '' 363 364 ## 365 ## Man page and info support 366 ## 367 + optionalString propagateDoc ( 368 '' 369 ln -s ${bintools.man} $man 370 '' 371 + optionalString (bintools ? info) '' 372 ln -s ${bintools.info} $info 373 '' 374 ) 375 376 ## 377 ## Hardening support 378 ## 379 380 # some linkers on some platforms don't support specific -z flags 381 + '' 382 export hardening_unsupported_flags="" 383 if [[ "$($ldPath/${targetPrefix}ld -z now 2>&1 || true)" =~ un(recognized|known)\ option ]]; then 384 hardening_unsupported_flags+=" bindnow" 385 fi 386 if [[ "$($ldPath/${targetPrefix}ld -z relro 2>&1 || true)" =~ un(recognized|known)\ option ]]; then 387 hardening_unsupported_flags+=" relro" 388 fi 389 '' 390 391 + optionalString hostPlatform.isCygwin '' 392 hardening_unsupported_flags+=" pic" 393 '' 394 395 + optionalString (targetPlatform.isAvr || targetPlatform.isWindows) '' 396 hardening_unsupported_flags+=" relro bindnow" 397 '' 398 399 + optionalString (libc != null && targetPlatform.isAvr) '' 400 for isa in avr5 avr3 avr4 avr6 avr25 avr31 avr35 avr51 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack; do 401 echo "-L${getLib libc}/avr/lib/$isa" >> $out/nix-support/libc-cflags 402 done 403 '' 404 405 ## 406 ## GNU specific extra strip flags 407 ## 408 409 # TODO(@sternenseemann): make a generic strip wrapper? 410 + 411 optionalString (bintools.isGNU or false || bintools.isLLVM or false || bintools.isCCTools or false) 412 '' 413 wrap ${targetPrefix}strip ${./gnu-binutils-strip-wrapper.sh} \ 414 "${bintools_bin}/bin/${targetPrefix}strip" 415 '' 416 417 ### 418 ### Remove certain timestamps from final binaries 419 ### 420 + optionalString (targetPlatform.isDarwin && !(bintools.isGNU or false)) '' 421 echo "export ZERO_AR_DATE=1" >> $out/nix-support/setup-hook 422 '' 423 424 + '' 425 for flags in "$out/nix-support"/*flags*; do 426 substituteInPlace "$flags" --replace $'\n' ' ' 427 done 428 429 substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh 430 substituteAll ${./add-hardening.sh} $out/nix-support/add-hardening.sh 431 substituteAll ${../wrapper-common/utils.bash} $out/nix-support/utils.bash 432 substituteAll ${../wrapper-common/darwin-sdk-setup.bash} $out/nix-support/darwin-sdk-setup.bash 433 '' 434 435 ### 436 ### Ensure consistent LC_VERSION_MIN_MACOSX 437 ### 438 + optionalString targetPlatform.isDarwin '' 439 substituteAll ${./add-darwin-ldflags-before.sh} $out/nix-support/add-local-ldflags-before.sh 440 '' 441 442 ## 443 ## LLVM ranlab lacks -t option that libtool expects. We can just 444 ## skip it 445 ## 446 447 + optionalString (isLLVM && targetPlatform.isOpenBSD) '' 448 rm $out/bin/${targetPrefix}ranlib 449 wrap \ 450 ${targetPrefix}ranlib ${./llvm-ranlib-wrapper.sh} \ 451 "${bintools_bin}/bin/${targetPrefix}ranlib" 452 '' 453 454 ## 455 ## Extra custom steps 456 ## 457 + extraBuildCommands; 458 459 env = { 460 # for substitution in utils.bash 461 # TODO(@sternenseemann): invent something cleaner than passing in "" in case of absence 462 expandResponseParams = "${expand-response-params}/bin/expand-response-params"; 463 # TODO(@sternenseemann): rename env var via stdenv rebuild 464 shell = (getBin runtimeShell + runtimeShell.shellPath or ""); 465 gnugrep_bin = optionalString (!nativeTools) gnugrep; 466 rm = if nativeTools then "rm" else lib.getExe' coreutils "rm"; 467 mktemp = if nativeTools then "mktemp" else lib.getExe' coreutils "mktemp"; 468 wrapperName = "BINTOOLS_WRAPPER"; 469 inherit 470 dynamicLinker 471 targetPrefix 472 suffixSalt 473 coreutils_bin 474 ; 475 inherit 476 bintools_bin 477 libc_bin 478 libc_dev 479 libc_lib 480 ; 481 default_hardening_flags_str = builtins.toString defaultHardeningFlags; 482 } 483 // lib.mapAttrs (_: lib.optionalString targetPlatform.isDarwin) { 484 # These will become empty strings when not targeting Darwin. 485 inherit (targetPlatform) 486 darwinPlatform 487 darwinSdkVersion 488 darwinMinVersion 489 darwinMinVersionVariable 490 ; 491 } 492 // lib.optionalAttrs (stdenvNoCC.targetPlatform.isDarwin && apple-sdk != null) { 493 # Wrapped compilers should do something useful even when no SDK is provided at `DEVELOPER_DIR`. 494 fallback_sdk = apple-sdk.__spliced.buildTarget or apple-sdk; 495 }; 496 497 meta = 498 let 499 bintools_ = optionalAttrs (bintools != null) bintools; 500 in 501 (optionalAttrs (bintools_ ? meta) (removeAttrs bintools.meta [ "priority" ])) 502 // { 503 description = 504 attrByPath [ "meta" "description" ] "System binary utilities" bintools_ + " (wrapper script)"; 505 priority = 10; 506 }; 507}