Skip to content
128 changes: 62 additions & 66 deletions pkgs/development/compilers/gcc/common/builder.nix
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
{ lib
, stdenv
, enableMultilib
, staticCompiler
}:

originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs //
(let
inherit (finalAttrs) targetConfig;
ifNullThen = val: default: if val==null then default else val;
targetConfigSlash = if targetConfig==null then "" else "${targetConfig}/";
in {
preUnpack = ''
oldOpts="$(shopt -po nounset)" || true
set -euo pipefail

export NIX_FIXINC_DUMMY="$NIX_BUILD_TOP/dummy"
mkdir "$NIX_FIXINC_DUMMY"

if test "$staticCompiler" = "1"; then
EXTRA_LDFLAGS="-static"
else
EXTRA_LDFLAGS="-Wl,-rpath,''${!outputLib}/lib"
fi
EXTRA_LDFLAGS="${if staticCompiler then "-static" else "-Wl,-rpath,${builtins.placeholder "lib"}/lib"}"

# GCC interprets empty paths as ".", which we don't want.
if test -z "''${CPATH-}"; then unset CPATH; fi
Expand Down Expand Up @@ -96,7 +98,7 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
declare -g EXTRA_FLAGS''${post}="''${extraFlags[*]}"
done

if test -z "''${targetConfig-}"; then
if test -z "${ifNullThen targetConfig ""}"; then
# host = target, so the flags are the same
EXTRA_FLAGS_FOR_TARGET="$EXTRA_FLAGS"
EXTRA_LDFLAGS_FOR_TARGET="$EXTRA_LDFLAGS"
Expand Down Expand Up @@ -128,37 +130,31 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
"FLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET"
)

if test -z "''${targetConfig-}"; then
if test -z "${ifNullThen targetConfig ""}"; then
makeFlagsArray+=(
"BOOT_CFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS"
"BOOT_LDFLAGS=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET"
)
fi

if test "$withoutTargetLibc" == 1; then
# We don't want the gcc build to assume there will be a libc providing
# limits.h in this stage
makeFlagsArray+=(
'LIMITS_H_TEST=false'
)
else
makeFlagsArray+=(
'LIMITS_H_TEST=true'
)
fi
# We don't want the gcc build to assume there will be a libc providing
# limits.h in this stage
makeFlagsArray+=(
'LIMITS_H_TEST=${lib.boolToString (!finalAttrs.withoutTargetLibc)}'
)
fi

eval "$oldOpts"
'';

preConfigure = (originalAttrs.preConfigure or "") + ''
if test -n "$newlibSrc"; then
tar xvf "$newlibSrc" -C ..
ln -s ../newlib-*/newlib newlib
# Patch to get armvt5el working:
sed -i -e 's/ arm)/ arm*)/' newlib/configure.host
fi
'' + lib.optionalString (finalAttrs.newlibSrc or false) ''
tar xvf "$newlibSrc" -C ..
ln -s ../newlib-*/newlib newlib
# Patch to get armvt5el working:
sed -i -e 's/ arm)/ arm*)/' newlib/configure.host

'' + ''
# Bug - they packaged zlib
if test -d "zlib"; then
# This breaks the build without-headers, which should build only
Expand All @@ -167,33 +163,33 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
rm -Rf zlib
fi

if test -n "$crossMingw" -a -n "$withoutTargetLibc"; then
mkdir -p ../mingw
# --with-build-sysroot expects that:
cp -R $libcCross/include ../mingw
configureFlags="$configureFlags --with-build-sysroot=`pwd`/.."
fi
'' + lib.optionalString (finalAttrs.crossMingw && finalAttrs.withoutTargetLibc) ''
mkdir -p ../mingw
# --with-build-sysroot expects that:
cp -R $libcCross/include ../mingw
configureFlags="$configureFlags --with-build-sysroot=`pwd`/.."

'' + ''
# Perform the build in a different directory.
mkdir ../build
cd ../build
configureScript=../$sourceRoot/configure
'';

# Avoid store paths when embedding ./configure flags into gcc.
# Mangled arguments are still useful when reporting bugs upstream.
postConfigure = ''
# Avoid store paths when embedding ./configure flags into gcc.
# Mangled arguments are still useful when reporting bugs upstream.
sed -e "/TOPLEVEL_CONFIGURE_ARGUMENTS=/ s|$NIX_STORE/[a-z0-9]\{32\}-|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-|g" -i Makefile
'';

preInstall = ''
mkdir -p "$out/''${targetConfig}/lib"
mkdir -p "''${!outputLib}/''${targetConfig}/lib"
mkdir -p "$out/${ifNullThen targetConfig ""}/lib"
mkdir -p "${builtins.placeholder "lib"}/${ifNullThen targetConfig ""}/lib"
'' +
# Make `lib64` symlinks to `lib`.
lib.optionalString (!enableMultilib && stdenv.hostPlatform.is64bit && !stdenv.hostPlatform.isMips64n32) ''
ln -s lib "$out/''${targetConfig}/lib64"
ln -s lib "''${!outputLib}/''${targetConfig}/lib64"
ln -s lib "$out/${ifNullThen targetConfig ""}/lib64"
ln -s lib "${builtins.placeholder "lib"}/${ifNullThen targetConfig ""}/lib64"
'' +
# On mips platforms, gcc follows the IRIX naming convention:
#
Expand All @@ -203,35 +199,35 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
#
# Make `lib32` symlinks to `lib`.
lib.optionalString (!enableMultilib && stdenv.targetPlatform.isMips64n32) ''
ln -s lib "$out/''${targetConfig}/lib32"
ln -s lib "''${!outputLib}/''${targetConfig}/lib32"
ln -s lib "$out/${ifNullThen targetConfig ""}/lib32"
ln -s lib "${builtins.placeholder "lib"}/${ifNullThen targetConfig ""}/lib32"
'';

# Move runtime libraries to lib output.
postInstall = ''
# Move runtime libraries to lib output.
moveToOutput "''${targetConfig+$targetConfig/}lib/lib*.so*" "''${!outputLib}"
moveToOutput "''${targetConfig+$targetConfig/}lib/lib*.la" "''${!outputLib}"
moveToOutput "''${targetConfig+$targetConfig/}lib/lib*.dylib" "''${!outputLib}"
moveToOutput "''${targetConfig+$targetConfig/}lib/lib*.dll.a" "''${!outputLib}"
moveToOutput "share/gcc-*/python" "''${!outputLib}"

if [ -z "$enableShared" ]; then
moveToOutput "''${targetConfig+$targetConfig/}lib/lib*.a" "''${!outputLib}"
fi

for i in "''${!outputLib}/''${targetConfig}"/lib/*.{la,py}; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
moveToOutput "${targetConfigSlash}lib/lib*.so*" "${builtins.placeholder "lib"}"
moveToOutput "${targetConfigSlash}lib/lib*.la" "${builtins.placeholder "lib"}"
moveToOutput "${targetConfigSlash}lib/lib*.dylib" "${builtins.placeholder "lib"}"
moveToOutput "${targetConfigSlash}lib/lib*.dll.a" "${builtins.placeholder "lib"}"
moveToOutput "share/gcc-*/python" "${builtins.placeholder "lib"}"

'' + lib.optionalString (!finalAttrs.enableShared) ''
moveToOutput "${targetConfigSlash}lib/lib*.a" "${builtins.placeholder "lib"}"
'' + ''

for i in "${builtins.placeholder "lib"}/${ifNullThen targetConfig ""}"/lib/*.{la,py}; do
substituteInPlace "$i" --replace "$out" "${builtins.placeholder "lib"}"
done

if [ -n "$enableMultilib" ]; then
moveToOutput "''${targetConfig+$targetConfig/}lib64/lib*.so*" "''${!outputLib}"
moveToOutput "''${targetConfig+$targetConfig/}lib64/lib*.la" "''${!outputLib}"
moveToOutput "''${targetConfig+$targetConfig/}lib64/lib*.dylib" "''${!outputLib}"
'' + lib.optionalString (finalAttrs.enableMultilib) ''
moveToOutput "${targetConfigSlash}lib64/lib*.so*" "${builtins.placeholder "lib"}"
moveToOutput "${targetConfigSlash}lib64/lib*.la" "${builtins.placeholder "lib"}"
moveToOutput "${targetConfigSlash}lib64/lib*.dylib" "${builtins.placeholder "lib"}"

for i in "''${!outputLib}/''${targetConfig}"/lib64/*.{la,py}; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
fi
for i in "${builtins.placeholder "lib"}/${ifNullThen targetConfig ""}"/lib64/*.{la,py}; do
substituteInPlace "$i" --replace "$out" "${builtins.placeholder "lib"}"
done
'' + ''

# Remove `fixincl' to prevent a retained dependency on the
# previous gcc.
Expand All @@ -242,10 +238,10 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
rm -rf $out/bin/gccbug

if type "install_name_tool"; then
for i in "''${!outputLib}"/lib/*.*.dylib "''${!outputLib}"/lib/*.so.[0-9]; do
for i in "${builtins.placeholder "lib"}"/lib/*.*.dylib "${builtins.placeholder "lib"}"/lib/*.so.[0-9]; do
install_name_tool -id "$i" "$i" || true
for old_path in $(otool -L "$i" | grep "$out" | awk '{print $1}'); do
new_path=`echo "$old_path" | sed "s,$out,''${!outputLib},"`
new_path=`echo "$old_path" | sed "s,$out,${builtins.placeholder "lib"},"`
install_name_tool -change "$old_path" "$new_path" "$i" || true
done
done
Expand All @@ -256,10 +252,10 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
# of $dir headers and use it later as `-isysroot`. This prevents
# cc-wrapper from overriding libc headers with `-idirafter`.
# It should be safe to drop it and rely solely on the cc-wrapper.
local sysinc_dir=$out/''${targetConfig+$targetConfig/}sys-include
local sysinc_dir=$out/${targetConfigSlash}sys-include
if [ -d "$sysinc_dir" ]; then
chmod -R u+w "$out/''${targetConfig+$targetConfig/}sys-include"
rm -rfv "$out/''${targetConfig+$targetConfig/}sys-include"
chmod -R u+w "$out/${targetConfigSlash}sys-include"
rm -rfv "$out/${targetConfigSlash}sys-include"
fi

# Get rid of some "fixed" header files
Expand All @@ -286,4 +282,4 @@ originalAttrs: (stdenv.mkDerivation (finalAttrs: originalAttrs // {
fi
done
'';
}))
})))