at master 15 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 # We include `-fmacro-prefix-map` in `cc-wrapper` for nonGCC 130 # platforms only, but they get picked up and passed down to 131 # e.g. GFortran calls that complain about the option not 132 # applying to the language. Hack around it by asking GCC not 133 # to complain. 134 # 135 # TODO: Someone please fix this to do things that make sense. 136 if [[ $EXTRA_FLAGS_FOR_BUILD == *-fmacro-prefix-map* ]]; then 137 EXTRA_FLAGS_FOR_BUILD+=" -Wno-complain-wrong-lang" 138 fi 139 if [[ $EXTRA_FLAGS_FOR_TARGET == *-fmacro-prefix-map* ]]; then 140 EXTRA_FLAGS_FOR_TARGET+=" -Wno-complain-wrong-lang" 141 fi 142 143 # CFLAGS_FOR_TARGET are needed for the libstdc++ configure script to find 144 # the startfiles. 145 # FLAGS_FOR_TARGET are needed for the target libraries to receive the -Bxxx 146 # for the startfiles. 147 makeFlagsArray+=( 148 "BUILD_SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY_FOR_BUILD" 149 "SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY_FOR_BUILD" 150 "NATIVE_SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY" 151 152 "LDFLAGS_FOR_BUILD=$EXTRA_LDFLAGS_FOR_BUILD" 153 #"LDFLAGS=$EXTRA_LDFLAGS" 154 "LDFLAGS_FOR_TARGET=$EXTRA_LDFLAGS_FOR_TARGET" 155 156 "CFLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD" 157 "CXXFLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD" 158 "FLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD" 159 160 # It seems there is a bug in GCC 5 161 #"CFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS" 162 #"CXXFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS" 163 164 "CFLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 165 "CXXFLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 166 "FLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 167 ) 168 169 if test -z "''${targetConfig-}"; then 170 makeFlagsArray+=( 171 "BOOT_CFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS" 172 "BOOT_LDFLAGS=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET" 173 ) 174 fi 175 176 if test "$withoutTargetLibc" == 1; then 177 # We don't want the gcc build to assume there will be a libc providing 178 # limits.h in this stage 179 makeFlagsArray+=( 180 'LIMITS_H_TEST=false' 181 ) 182 else 183 makeFlagsArray+=( 184 'LIMITS_H_TEST=true' 185 ) 186 fi 187 fi 188 189 eval "$oldOpts" 190 ''; 191 192 preConfigure = (originalAttrs.preConfigure or "") + '' 193 if test -n "$newlibSrc"; then 194 tar xvf "$newlibSrc" -C .. 195 ln -s ../newlib-*/newlib newlib 196 # Patch to get armvt5el working: 197 sed -i -e 's/ arm)/ arm*)/' newlib/configure.host 198 fi 199 200 # Bug - they packaged zlib 201 if test -d "zlib"; then 202 # This breaks the build without-headers, which should build only 203 # the target libgcc as target libraries. 204 # See 'configure:5370' 205 rm -Rf zlib 206 fi 207 208 if test -n "$crossMingw" -a -n "$withoutTargetLibc"; then 209 mkdir -p ../mingw 210 # --with-build-sysroot expects that: 211 cp -R $libcCross/include ../mingw 212 appendToVar configureFlags "--with-build-sysroot=`pwd`/.." 213 fi 214 215 # Perform the build in a different directory. 216 mkdir ../build 217 cd ../build 218 configureScript=../$sourceRoot/configure 219 ''; 220 221 postConfigure = '' 222 # Avoid store paths when embedding ./configure flags into gcc. 223 # Mangled arguments are still useful when reporting bugs upstream. 224 sed -e "/TOPLEVEL_CONFIGURE_ARGUMENTS=/ s|$NIX_STORE/[a-z0-9]\{32\}-|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-|g" -i Makefile 225 ''; 226 227 preInstall = 228 # What follows is a horribly cursed hack. 229 # 230 # GCC will install its libraries to $out/lib, $out/lib32, $out/lib64, 231 # $out/$targetConfig/lib, $out/$targetConfig/lib32 or $out/$targetConfig/lib64, 232 # depending on whether it's built as native or cross, and the exact target spec. 233 # 234 # We can't predict what it's actually going to do, and we also can't just tell it 235 # to always install to lib, but we want everything to end up in lib 236 # for consistency (multilib weirdness aside). 237 # 238 # So, we create a bunch of symlinks before we run GCC's install phase, 239 # redirecting every possible directory it may want to write to to the place 240 # we actually want things to be installed. 241 # We will then nuke the symlinks in postInstall. 242 # 243 # FIXME: there must be a better way to do this. 244 '' 245 declare -ga compatibilitySymlinks=() 246 247 makeCompatibilitySymlink() { 248 declare -a outputsToLink=("$out") 249 250 if [ -n "$lib" ]; then 251 outputsToLink+=("$lib") 252 fi 253 254 for output in "''${outputsToLink[@]}"; do 255 local linkTarget="$1" 256 local linkName="$output/$2" 257 258 echo "Creating compatibility symlink: $linkTarget -> $linkName" 259 260 mkdir -p "$(dirname "$linkName")" 261 ln -s "$linkTarget" "$linkName" 262 compatibilitySymlinks+=("$linkName") 263 done 264 } 265 '' 266 + 267 # This will redirect $output/lib{32,64} to $output/lib. 268 # Multilib is special, because it creates $out/lib (for 32-bit) 269 # and $out/lib64 (for 64-bit). No other targets can have both. 270 lib.optionalString (!enableMultilib) '' 271 makeCompatibilitySymlink lib lib32 272 makeCompatibilitySymlink lib lib64 273 '' 274 + 275 # This will redirect $output/$targetConfig/lib{,32,64} to $output/$targetConfig/lib. 276 lib.optionalString isCross '' 277 makeCompatibilitySymlink lib $targetConfig/lib32 278 makeCompatibilitySymlink lib $targetConfig/lib64 279 ''; 280 281 postInstall = '' 282 # Clean up our compatibility symlinks (see above) 283 for link in "''${compatibilitySymlinks[@]}"; do 284 echo "Removing compatibility symlink: $link" 285 rm -f "$link" 286 done 287 288 # Move target runtime libraries to lib output. 289 # For non-cross, they're in $out/lib; for cross, they're in $out/$targetConfig/lib. 290 targetLibDir="''${targetConfig+$targetConfig/}lib" 291 292 moveToOutput "$targetLibDir/lib*.so*" "''${!outputLib}" 293 moveToOutput "$targetLibDir/lib*.dylib" "''${!outputLib}" 294 moveToOutput "$targetLibDir/lib*.dll.a" "''${!outputLib}" 295 moveToOutput "$targetLibDir/lib*.dll" "''${!outputLib}" 296 moveToOutput "share/gcc-*/python" "''${!outputLib}" 297 298 if [ -z "$enableShared" ]; then 299 moveToOutput "$targetLibDir/lib*.a" "''${!outputLib}" 300 fi 301 302 for i in "''${!outputLib}"/$targetLibDir/*.py; do 303 substituteInPlace "$i" --replace "$out" "''${!outputLib}" 304 done 305 306 # Multilib and cross can't exist at the same time, so just use lib64 here 307 if [ -n "$enableMultilib" ]; then 308 moveToOutput "lib64/lib*.so*" "''${!outputLib}" 309 moveToOutput "lib64/lib*.dylib" "''${!outputLib}" 310 moveToOutput "lib64/lib*.dll.a" "''${!outputLib}" 311 moveToOutput "lib64/lib*.dll" "''${!outputLib}" 312 313 for i in "''${!outputLib}"/lib64/*.py; do 314 substituteInPlace "$i" --replace "$out" "''${!outputLib}" 315 done 316 fi 317 318 # Remove `fixincl' to prevent a retained dependency on the 319 # previous gcc. 320 rm -rf $out/libexec/gcc/*/*/install-tools 321 rm -rf $out/lib/gcc/*/*/install-tools 322 323 # More dependencies with the previous gcc or some libs (gccbug stores the build command line) 324 rm -rf $out/bin/gccbug 325 326 # Remove .la files, they're not adjusted for the makeCompatibilitySymlink magic, 327 # which confuses libtool and leads to weird linking errors. 328 # Removing the files just makes libtool link .so files directly, which is usually 329 # what we want anyway. 330 find $out -name '*.la' -delete 331 332 if type "install_name_tool"; then 333 for i in "''${!outputLib}"/lib/*.*.dylib "''${!outputLib}"/lib/*.so.[0-9]; do 334 install_name_tool -id "$i" "$i" || true 335 for old_path in $(otool -L "$i" | grep "$out" | awk '{print $1}'); do 336 new_path=`echo "$old_path" | sed "s,$out,''${!outputLib},"` 337 install_name_tool -change "$old_path" "$new_path" "$i" || true 338 done 339 done 340 fi 341 342 # Get rid of some "fixed" header files 343 rm -rfv $out/lib/gcc/*/*/include-fixed/{root,linux,sys/mount.h,bits/statx.h,pthread.h} 344 345 # Replace hard links for i686-pc-linux-gnu-gcc etc. with symlinks. 346 for i in $out/bin/*-gcc*; do 347 if cmp -s $out/bin/gcc $i; then 348 ln -sfn gcc $i 349 fi 350 done 351 352 for i in $out/bin/c++ $out/bin/*-c++* $out/bin/*-g++*; do 353 if cmp -s $out/bin/g++ $i; then 354 ln -sfn g++ $i 355 fi 356 done 357 358 # Two identical man pages are shipped (moving and compressing is done later) 359 for i in "$out"/share/man/man1/*g++.1; do 360 if test -e "$i"; then 361 man_prefix=`echo "$i" | sed "s,.*/\(.*\)g++.1,\1,"` 362 ln -sf "$man_prefix"gcc.1 "$i" 363 fi 364 done 365 '' 366 # if cross-compiling, link from $lib/lib to $lib/${targetConfig}. 367 # since native-compiles have $lib/lib as a directory (not a 368 # symlink), this ensures that in every case we can assume that 369 # $lib/lib contains the .so files 370 + lib.optionalString isCross '' 371 if [ -e "$lib/$targetConfig/lib" ]; then 372 ln -s "$lib/$targetConfig/lib" "$lib/lib" 373 fi 374 ''; 375 } 376))