Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at flake-libs 365 lines 14 kB view raw
1{ 2 lib, 3 stdenv, 4 enableMultilib, 5 targetConfig, 6}: 7 8let 9 forceLibgccToBuildCrtStuff = import ./libgcc-buildstuff.nix { inherit lib stdenv; }; 10 isCross = !lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform; 11in 12 13# We don't support multilib and cross at the same time 14assert !(enableMultilib && isCross); 15 16originalAttrs: 17(stdenv.mkDerivation ( 18 finalAttrs: 19 originalAttrs 20 // { 21 passthru = (originalAttrs.passthru or { }) // { 22 inherit forceLibgccToBuildCrtStuff; 23 }; 24 preUnpack = '' 25 oldOpts="$(shopt -po nounset)" || true 26 set -euo pipefail 27 28 export NIX_FIXINC_DUMMY="$NIX_BUILD_TOP/dummy" 29 mkdir "$NIX_FIXINC_DUMMY" 30 31 if test "$staticCompiler" = "1"; then 32 EXTRA_LDFLAGS="-static" 33 elif test "''${NIX_DONT_SET_RPATH-}" != "1"; then 34 EXTRA_LDFLAGS="-Wl,-rpath,''${!outputLib}/lib" 35 else 36 EXTRA_LDFLAGS="" 37 fi 38 39 # GCC interprets empty paths as ".", which we don't want. 40 if test -z "''${CPATH-}"; then unset CPATH; fi 41 if test -z "''${LIBRARY_PATH-}"; then unset LIBRARY_PATH; fi 42 echo "\$CPATH is \`''${CPATH-}'" 43 echo "\$LIBRARY_PATH is \`''${LIBRARY_PATH-}'" 44 45 if test "$noSysDirs" = "1"; then 46 47 declare -g \ 48 EXTRA_FLAGS_FOR_BUILD EXTRA_FLAGS EXTRA_FLAGS_FOR_TARGET \ 49 EXTRA_LDFLAGS_FOR_BUILD EXTRA_LDFLAGS_FOR_TARGET 50 51 # Extract flags from Bintools Wrappers 52 for post in '_FOR_BUILD' ""; do 53 curBintools="NIX_BINTOOLS''${post}" 54 55 declare -a extraLDFlags=() 56 if [[ -e "''${!curBintools}/nix-support/orig-libc" ]]; then 57 # Figure out what extra flags when linking to pass to the gcc 58 # compilers being generated to make sure that they use our libc. 59 extraLDFlags=($(< "''${!curBintools}/nix-support/libc-ldflags") $(< "''${!curBintools}/nix-support/libc-ldflags-before" || true)) 60 if [ -e ''${!curBintools}/nix-support/ld-set-dynamic-linker ]; then 61 extraLDFlags=-dynamic-linker=$(< ''${!curBintools}/nix-support/dynamic-linker) 62 fi 63 64 # The path to the Libc binaries such as `crti.o'. 65 libc_libdir="$(< "''${!curBintools}/nix-support/orig-libc")/lib" 66 else 67 # Hack: support impure environments. 68 extraLDFlags=("-L/usr/lib64" "-L/usr/lib") 69 libc_libdir="/usr/lib" 70 fi 71 declare -a prefixExtraLDFlags=() 72 prefixExtraLDFlags=("-L$libc_libdir") 73 nixDontSetRpathVar=NIX_DONT_SET_RPATH''${post} 74 if test "''${!nixDontSetRpathVar-}" != "1"; then 75 prefixExtraLDFlags+=("-rpath" "$libc_libdir") 76 fi 77 extraLDFlags=("''${prefixExtraLDFlags[@]}" "''${extraLDFlags[@]}") 78 for i in "''${extraLDFlags[@]}"; do 79 declare -g EXTRA_LDFLAGS''${post}+=" -Wl,$i" 80 done 81 done 82 83 # Extract flags from CC Wrappers 84 for post in '_FOR_BUILD' ""; do 85 curCC="NIX_CC''${post}" 86 curFIXINC="NIX_FIXINC_DUMMY''${post}" 87 88 declare -a extraFlags=() 89 if [[ -e "''${!curCC}/nix-support/orig-libc" ]]; then 90 # Figure out what extra compiling flags to pass to the gcc compilers 91 # being generated to make sure that they use our libc. 92 extraFlags=($(< "''${!curCC}/nix-support/libc-crt1-cflags") $(< "''${!curCC}/nix-support/libc-cflags")) 93 94 # The path to the Libc headers 95 libc_devdir="$(< "''${!curCC}/nix-support/orig-libc-dev")" 96 97 # Use *real* header files, otherwise a limits.h is generated that 98 # does not include Libc's limits.h (notably missing SSIZE_MAX, 99 # which breaks the build). 100 declare -g NIX_FIXINC_DUMMY''${post}="$libc_devdir/include" 101 else 102 # Hack: support impure environments. 103 extraFlags=("-isystem" "/usr/include") 104 declare -g NIX_FIXINC_DUMMY''${post}=/usr/include 105 fi 106 107 extraFlags=("-I''${!curFIXINC}" "''${extraFlags[@]}") 108 109 # BOOT_CFLAGS defaults to `-g -O2'; since we override it below, make 110 # sure to explictly add them so that files compiled with the bootstrap 111 # compiler are optimized and (optionally) contain debugging information 112 # (info "(gccinstall) Building"). 113 if test -n "''${dontStrip-}"; then 114 extraFlags=("-O2" "-g" "''${extraFlags[@]}") 115 else 116 # Don't pass `-g' at all; this saves space while building. 117 extraFlags=("-O2" "''${extraFlags[@]}") 118 fi 119 120 declare -g EXTRA_FLAGS''${post}="''${extraFlags[*]}" 121 done 122 123 if test -z "''${targetConfig-}"; then 124 # host = target, so the flags are the same 125 EXTRA_FLAGS_FOR_TARGET="$EXTRA_FLAGS" 126 EXTRA_LDFLAGS_FOR_TARGET="$EXTRA_LDFLAGS" 127 fi 128 129 # CFLAGS_FOR_TARGET are needed for the libstdc++ configure script to find 130 # the startfiles. 131 # FLAGS_FOR_TARGET are needed for the target libraries to receive the -Bxxx 132 # for the startfiles. 133 makeFlagsArray+=( 134 "BUILD_SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY_FOR_BUILD" 135 "SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY_FOR_BUILD" 136 "NATIVE_SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY" 137 138 "LDFLAGS_FOR_BUILD=$EXTRA_LDFLAGS_FOR_BUILD" 139 #"LDFLAGS=$EXTRA_LDFLAGS" 140 "LDFLAGS_FOR_TARGET=$EXTRA_LDFLAGS_FOR_TARGET" 141 142 "CFLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD" 143 "CXXFLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD" 144 "FLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD" 145 146 # It seems there is a bug in GCC 5 147 #"CFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS" 148 #"CXXFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS" 149 150 "CFLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 151 "CXXFLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 152 "FLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 153 ) 154 155 if test -z "''${targetConfig-}"; then 156 makeFlagsArray+=( 157 "BOOT_CFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS" 158 "BOOT_LDFLAGS=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 159 ) 160 fi 161 162 if test "$withoutTargetLibc" == 1; then 163 # We don't want the gcc build to assume there will be a libc providing 164 # limits.h in this stage 165 makeFlagsArray+=( 166 'LIMITS_H_TEST=false' 167 ) 168 else 169 makeFlagsArray+=( 170 'LIMITS_H_TEST=true' 171 ) 172 fi 173 fi 174 175 eval "$oldOpts" 176 ''; 177 178 preConfigure = 179 (originalAttrs.preConfigure or "") 180 + '' 181 if test -n "$newlibSrc"; then 182 tar xvf "$newlibSrc" -C .. 183 ln -s ../newlib-*/newlib newlib 184 # Patch to get armvt5el working: 185 sed -i -e 's/ arm)/ arm*)/' newlib/configure.host 186 fi 187 188 # Bug - they packaged zlib 189 if test -d "zlib"; then 190 # This breaks the build without-headers, which should build only 191 # the target libgcc as target libraries. 192 # See 'configure:5370' 193 rm -Rf zlib 194 fi 195 196 if test -n "$crossMingw" -a -n "$withoutTargetLibc"; then 197 mkdir -p ../mingw 198 # --with-build-sysroot expects that: 199 cp -R $libcCross/include ../mingw 200 appendToVar configureFlags "--with-build-sysroot=`pwd`/.." 201 fi 202 203 # Perform the build in a different directory. 204 mkdir ../build 205 cd ../build 206 configureScript=../$sourceRoot/configure 207 ''; 208 209 postConfigure = '' 210 # Avoid store paths when embedding ./configure flags into gcc. 211 # Mangled arguments are still useful when reporting bugs upstream. 212 sed -e "/TOPLEVEL_CONFIGURE_ARGUMENTS=/ s|$NIX_STORE/[a-z0-9]\{32\}-|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-|g" -i Makefile 213 ''; 214 215 preInstall = 216 # What follows is a horribly cursed hack. 217 # 218 # GCC will install its libraries to $out/lib, $out/lib32, $out/lib64, 219 # $out/$targetConfig/lib, $out/$targetConfig/lib32 or $out/$targetConfig/lib64, 220 # depending on whether it's built as native or cross, and the exact target spec. 221 # 222 # We can't predict what it's actually going to do, and we also can't just tell it 223 # to always install to lib, but we want everything to end up in lib 224 # for consistency (multilib weirdness aside). 225 # 226 # So, we create a bunch of symlinks before we run GCC's install phase, 227 # redirecting every possible directory it may want to write to to the place 228 # we actually want things to be installed. 229 # We will then nuke the symlinks in postInstall. 230 # 231 # FIXME: there must be a better way to do this. 232 '' 233 declare -ga compatibilitySymlinks=() 234 235 makeCompatibilitySymlink() { 236 declare -a outputsToLink=("$out") 237 238 if [ -n "$lib" ]; then 239 outputsToLink+=("$lib") 240 fi 241 242 for output in "''${outputsToLink[@]}"; do 243 local linkTarget="$1" 244 local linkName="$output/$2" 245 246 echo "Creating compatibility symlink: $linkTarget -> $linkName" 247 248 mkdir -p "$(dirname "$linkName")" 249 ln -s "$linkTarget" "$linkName" 250 compatibilitySymlinks+=("$linkName") 251 done 252 } 253 '' 254 + 255 # This will redirect $output/lib{32,64} to $output/lib. 256 # Multilib is special, because it creates $out/lib (for 32-bit) 257 # and $out/lib64 (for 64-bit). No other targets can have both. 258 lib.optionalString (!enableMultilib) '' 259 makeCompatibilitySymlink lib lib32 260 makeCompatibilitySymlink lib lib64 261 '' 262 + 263 # This will redirect $output/$targetConfig/lib{,32,64} to $output/$targetConfig/lib. 264 lib.optionalString isCross '' 265 makeCompatibilitySymlink lib $targetConfig/lib32 266 makeCompatibilitySymlink lib $targetConfig/lib64 267 ''; 268 269 postInstall = 270 '' 271 # Clean up our compatibility symlinks (see above) 272 for link in "''${compatibilitySymlinks[@]}"; do 273 echo "Removing compatibility symlink: $link" 274 rm -f "$link" 275 done 276 277 # Move target runtime libraries to lib output. 278 # For non-cross, they're in $out/lib; for cross, they're in $out/$targetConfig/lib. 279 targetLibDir="''${targetConfig+$targetConfig/}lib" 280 281 moveToOutput "$targetLibDir/lib*.so*" "''${!outputLib}" 282 moveToOutput "$targetLibDir/lib*.dylib" "''${!outputLib}" 283 moveToOutput "$targetLibDir/lib*.dll.a" "''${!outputLib}" 284 moveToOutput "$targetLibDir/lib*.dll" "''${!outputLib}" 285 moveToOutput "share/gcc-*/python" "''${!outputLib}" 286 287 if [ -z "$enableShared" ]; then 288 moveToOutput "$targetLibDir/lib*.a" "''${!outputLib}" 289 fi 290 291 for i in "''${!outputLib}"/$targetLibDir/*.py; do 292 substituteInPlace "$i" --replace "$out" "''${!outputLib}" 293 done 294 295 # Multilib and cross can't exist at the same time, so just use lib64 here 296 if [ -n "$enableMultilib" ]; then 297 moveToOutput "lib64/lib*.so*" "''${!outputLib}" 298 moveToOutput "lib64/lib*.dylib" "''${!outputLib}" 299 moveToOutput "lib64/lib*.dll.a" "''${!outputLib}" 300 moveToOutput "lib64/lib*.dll" "''${!outputLib}" 301 302 for i in "''${!outputLib}"/lib64/*.py; do 303 substituteInPlace "$i" --replace "$out" "''${!outputLib}" 304 done 305 fi 306 307 # Remove `fixincl' to prevent a retained dependency on the 308 # previous gcc. 309 rm -rf $out/libexec/gcc/*/*/install-tools 310 rm -rf $out/lib/gcc/*/*/install-tools 311 312 # More dependencies with the previous gcc or some libs (gccbug stores the build command line) 313 rm -rf $out/bin/gccbug 314 315 # Remove .la files, they're not adjusted for the makeCompatibilitySymlink magic, 316 # which confuses libtool and leads to weird linking errors. 317 # Removing the files just makes libtool link .so files directly, which is usually 318 # what we want anyway. 319 find $out -name '*.la' -delete 320 321 if type "install_name_tool"; then 322 for i in "''${!outputLib}"/lib/*.*.dylib "''${!outputLib}"/lib/*.so.[0-9]; do 323 install_name_tool -id "$i" "$i" || true 324 for old_path in $(otool -L "$i" | grep "$out" | awk '{print $1}'); do 325 new_path=`echo "$old_path" | sed "s,$out,''${!outputLib},"` 326 install_name_tool -change "$old_path" "$new_path" "$i" || true 327 done 328 done 329 fi 330 331 # Get rid of some "fixed" header files 332 rm -rfv $out/lib/gcc/*/*/include-fixed/{root,linux,sys/mount.h,bits/statx.h,pthread.h} 333 334 # Replace hard links for i686-pc-linux-gnu-gcc etc. with symlinks. 335 for i in $out/bin/*-gcc*; do 336 if cmp -s $out/bin/gcc $i; then 337 ln -sfn gcc $i 338 fi 339 done 340 341 for i in $out/bin/c++ $out/bin/*-c++* $out/bin/*-g++*; do 342 if cmp -s $out/bin/g++ $i; then 343 ln -sfn g++ $i 344 fi 345 done 346 347 # Two identical man pages are shipped (moving and compressing is done later) 348 for i in "$out"/share/man/man1/*g++.1; do 349 if test -e "$i"; then 350 man_prefix=`echo "$i" | sed "s,.*/\(.*\)g++.1,\1,"` 351 ln -sf "$man_prefix"gcc.1 "$i" 352 fi 353 done 354 '' 355 # if cross-compiling, link from $lib/lib to $lib/${targetConfig}. 356 # since native-compiles have $lib/lib as a directory (not a 357 # symlink), this ensures that in every case we can assume that 358 # $lib/lib contains the .so files 359 + lib.optionalString isCross '' 360 if [ -e "$lib/$targetConfig/lib" ]; then 361 ln -s "$lib/$targetConfig/lib" "$lib/lib" 362 fi 363 ''; 364 } 365))