push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,376 @@
{
lib,
stdenv,
enableMultilib,
targetConfig,
}:
let
forceLibgccToBuildCrtStuff = import ./libgcc-buildstuff.nix { inherit lib stdenv; };
isCross = !lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform;
in
# We don't support multilib and cross at the same time
assert !(enableMultilib && isCross);
originalAttrs:
(stdenv.mkDerivation (
finalAttrs:
originalAttrs
// {
passthru = (originalAttrs.passthru or { }) // {
inherit forceLibgccToBuildCrtStuff;
};
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"
elif test "''${NIX_DONT_SET_RPATH-}" != "1"; then
EXTRA_LDFLAGS="-Wl,-rpath,''${!outputLib}/lib"
else
EXTRA_LDFLAGS=""
fi
# GCC interprets empty paths as ".", which we don't want.
if test -z "''${CPATH-}"; then unset CPATH; fi
if test -z "''${LIBRARY_PATH-}"; then unset LIBRARY_PATH; fi
echo "\$CPATH is \`''${CPATH-}'"
echo "\$LIBRARY_PATH is \`''${LIBRARY_PATH-}'"
if test "$noSysDirs" = "1"; then
declare -g \
EXTRA_FLAGS_FOR_BUILD EXTRA_FLAGS EXTRA_FLAGS_FOR_TARGET \
EXTRA_LDFLAGS_FOR_BUILD EXTRA_LDFLAGS_FOR_TARGET
# Extract flags from Bintools Wrappers
for post in '_FOR_BUILD' ""; do
curBintools="NIX_BINTOOLS''${post}"
declare -a extraLDFlags=()
if [[ -e "''${!curBintools}/nix-support/orig-libc" ]]; then
# Figure out what extra flags when linking to pass to the gcc
# compilers being generated to make sure that they use our libc.
extraLDFlags=($(< "''${!curBintools}/nix-support/libc-ldflags") $(< "''${!curBintools}/nix-support/libc-ldflags-before" || true))
if [ -e ''${!curBintools}/nix-support/ld-set-dynamic-linker ]; then
extraLDFlags=-dynamic-linker=$(< ''${!curBintools}/nix-support/dynamic-linker)
fi
# The path to the Libc binaries such as `crti.o'.
libc_libdir="$(< "''${!curBintools}/nix-support/orig-libc")/lib"
else
# Hack: support impure environments.
extraLDFlags=("-L/usr/lib64" "-L/usr/lib")
libc_libdir="/usr/lib"
fi
declare -a prefixExtraLDFlags=()
prefixExtraLDFlags=("-L$libc_libdir")
nixDontSetRpathVar=NIX_DONT_SET_RPATH''${post}
if test "''${!nixDontSetRpathVar-}" != "1"; then
prefixExtraLDFlags+=("-rpath" "$libc_libdir")
fi
extraLDFlags=("''${prefixExtraLDFlags[@]}" "''${extraLDFlags[@]}")
for i in "''${extraLDFlags[@]}"; do
declare -g EXTRA_LDFLAGS''${post}+=" -Wl,$i"
done
done
# Extract flags from CC Wrappers
for post in '_FOR_BUILD' ""; do
curCC="NIX_CC''${post}"
curFIXINC="NIX_FIXINC_DUMMY''${post}"
declare -a extraFlags=()
if [[ -e "''${!curCC}/nix-support/orig-libc" ]]; then
# Figure out what extra compiling flags to pass to the gcc compilers
# being generated to make sure that they use our libc.
extraFlags=($(< "''${!curCC}/nix-support/libc-crt1-cflags") $(< "''${!curCC}/nix-support/libc-cflags"))
# The path to the Libc headers
libc_devdir="$(< "''${!curCC}/nix-support/orig-libc-dev")"
# Use *real* header files, otherwise a limits.h is generated that
# does not include Libc's limits.h (notably missing SSIZE_MAX,
# which breaks the build).
declare -g NIX_FIXINC_DUMMY''${post}="$libc_devdir/include"
else
# Hack: support impure environments.
extraFlags=("-isystem" "/usr/include")
declare -g NIX_FIXINC_DUMMY''${post}=/usr/include
fi
extraFlags=("-I''${!curFIXINC}" "''${extraFlags[@]}")
# BOOT_CFLAGS defaults to `-g -O2'; since we override it below, make
# sure to explictly add them so that files compiled with the bootstrap
# compiler are optimized and (optionally) contain debugging information
# (info "(gccinstall) Building").
if test -n "''${dontStrip-}"; then
extraFlags=("-O2" "-g" "''${extraFlags[@]}")
else
# Don't pass `-g' at all; this saves space while building.
extraFlags=("-O2" "''${extraFlags[@]}")
fi
declare -g EXTRA_FLAGS''${post}="''${extraFlags[*]}"
done
if test -z "''${targetConfig-}"; then
# host = target, so the flags are the same
EXTRA_FLAGS_FOR_TARGET="$EXTRA_FLAGS"
EXTRA_LDFLAGS_FOR_TARGET="$EXTRA_LDFLAGS"
fi
# We include `-fmacro-prefix-map` in `cc-wrapper` for nonGCC
# platforms only, but they get picked up and passed down to
# e.g. GFortran calls that complain about the option not
# applying to the language. Hack around it by asking GCC not
# to complain.
#
# TODO: Someone please fix this to do things that make sense.
if [[ $EXTRA_FLAGS_FOR_BUILD == *-fmacro-prefix-map* ]]; then
EXTRA_FLAGS_FOR_BUILD+=" -Wno-complain-wrong-lang"
fi
if [[ $EXTRA_FLAGS_FOR_TARGET == *-fmacro-prefix-map* ]]; then
EXTRA_FLAGS_FOR_TARGET+=" -Wno-complain-wrong-lang"
fi
# CFLAGS_FOR_TARGET are needed for the libstdc++ configure script to find
# the startfiles.
# FLAGS_FOR_TARGET are needed for the target libraries to receive the -Bxxx
# for the startfiles.
makeFlagsArray+=(
"BUILD_SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY_FOR_BUILD"
"SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY_FOR_BUILD"
"NATIVE_SYSTEM_HEADER_DIR=$NIX_FIXINC_DUMMY"
"LDFLAGS_FOR_BUILD=$EXTRA_LDFLAGS_FOR_BUILD"
#"LDFLAGS=$EXTRA_LDFLAGS"
"LDFLAGS_FOR_TARGET=$EXTRA_LDFLAGS_FOR_TARGET"
"CFLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD"
"CXXFLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD"
"FLAGS_FOR_BUILD=$EXTRA_FLAGS_FOR_BUILD $EXTRA_LDFLAGS_FOR_BUILD"
# It seems there is a bug in GCC 5
#"CFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS"
#"CXXFLAGS=$EXTRA_FLAGS $EXTRA_LDFLAGS"
"CFLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET"
"CXXFLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET"
"FLAGS_FOR_TARGET=$EXTRA_FLAGS_FOR_TARGET $EXTRA_LDFLAGS_FOR_TARGET"
)
if test -z "''${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
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
# Bug - they packaged zlib
if test -d "zlib"; then
# This breaks the build without-headers, which should build only
# the target libgcc as target libraries.
# See 'configure:5370'
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
appendToVar configureFlags "--with-build-sysroot=`pwd`/.."
fi
# Perform the build in a different directory.
mkdir ../build
cd ../build
configureScript=../$sourceRoot/configure
'';
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 =
# What follows is a horribly cursed hack.
#
# GCC will install its libraries to $out/lib, $out/lib32, $out/lib64,
# $out/$targetConfig/lib, $out/$targetConfig/lib32 or $out/$targetConfig/lib64,
# depending on whether it's built as native or cross, and the exact target spec.
#
# We can't predict what it's actually going to do, and we also can't just tell it
# to always install to lib, but we want everything to end up in lib
# for consistency (multilib weirdness aside).
#
# So, we create a bunch of symlinks before we run GCC's install phase,
# redirecting every possible directory it may want to write to to the place
# we actually want things to be installed.
# We will then nuke the symlinks in postInstall.
#
# FIXME: there must be a better way to do this.
''
declare -ga compatibilitySymlinks=()
makeCompatibilitySymlink() {
declare -a outputsToLink=("$out")
if [ -n "$lib" ]; then
outputsToLink+=("$lib")
fi
for output in "''${outputsToLink[@]}"; do
local linkTarget="$1"
local linkName="$output/$2"
echo "Creating compatibility symlink: $linkTarget -> $linkName"
mkdir -p "$(dirname "$linkName")"
ln -s "$linkTarget" "$linkName"
compatibilitySymlinks+=("$linkName")
done
}
''
+
# This will redirect $output/lib{32,64} to $output/lib.
# Multilib is special, because it creates $out/lib (for 32-bit)
# and $out/lib64 (for 64-bit). No other targets can have both.
lib.optionalString (!enableMultilib) ''
makeCompatibilitySymlink lib lib32
makeCompatibilitySymlink lib lib64
''
+
# This will redirect $output/$targetConfig/lib{,32,64} to $output/$targetConfig/lib.
lib.optionalString isCross ''
makeCompatibilitySymlink lib $targetConfig/lib32
makeCompatibilitySymlink lib $targetConfig/lib64
'';
postInstall = ''
# Clean up our compatibility symlinks (see above)
for link in "''${compatibilitySymlinks[@]}"; do
echo "Removing compatibility symlink: $link"
rm -f "$link"
done
# Move target runtime libraries to lib output.
# For non-cross, they're in $out/lib; for cross, they're in $out/$targetConfig/lib.
targetLibDir="''${targetConfig+$targetConfig/}lib"
moveToOutput "$targetLibDir/lib*.so*" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dylib" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dll.a" "''${!outputLib}"
moveToOutput "$targetLibDir/lib*.dll" "''${!outputLib}"
moveToOutput "share/gcc-*/python" "''${!outputLib}"
if [ -z "$enableShared" ]; then
moveToOutput "$targetLibDir/lib*.a" "''${!outputLib}"
fi
for i in "''${!outputLib}"/$targetLibDir/*.py; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
# Multilib and cross can't exist at the same time, so just use lib64 here
if [ -n "$enableMultilib" ]; then
moveToOutput "lib64/lib*.so*" "''${!outputLib}"
moveToOutput "lib64/lib*.dylib" "''${!outputLib}"
moveToOutput "lib64/lib*.dll.a" "''${!outputLib}"
moveToOutput "lib64/lib*.dll" "''${!outputLib}"
for i in "''${!outputLib}"/lib64/*.py; do
substituteInPlace "$i" --replace "$out" "''${!outputLib}"
done
fi
# Remove `fixincl' to prevent a retained dependency on the
# previous gcc.
rm -rf $out/libexec/gcc/*/*/install-tools
rm -rf $out/lib/gcc/*/*/install-tools
# More dependencies with the previous gcc or some libs (gccbug stores the build command line)
rm -rf $out/bin/gccbug
# Remove .la files, they're not adjusted for the makeCompatibilitySymlink magic,
# which confuses libtool and leads to weird linking errors.
# Removing the files just makes libtool link .so files directly, which is usually
# what we want anyway.
find $out -name '*.la' -delete
if type "install_name_tool"; then
for i in "''${!outputLib}"/lib/*.*.dylib "''${!outputLib}"/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},"`
install_name_tool -change "$old_path" "$new_path" "$i" || true
done
done
fi
# Get rid of some "fixed" header files
rm -rfv $out/lib/gcc/*/*/include-fixed/{root,linux,sys/mount.h,bits/statx.h,pthread.h}
# Replace hard links for i686-pc-linux-gnu-gcc etc. with symlinks.
for i in $out/bin/*-gcc*; do
if cmp -s $out/bin/gcc $i; then
ln -sfn gcc $i
fi
done
for i in $out/bin/c++ $out/bin/*-c++* $out/bin/*-g++*; do
if cmp -s $out/bin/g++ $i; then
ln -sfn g++ $i
fi
done
# Two identical man pages are shipped (moving and compressing is done later)
for i in "$out"/share/man/man1/*g++.1; do
if test -e "$i"; then
man_prefix=`echo "$i" | sed "s,.*/\(.*\)g++.1,\1,"`
ln -sf "$man_prefix"gcc.1 "$i"
fi
done
''
# if cross-compiling, link from $lib/lib to $lib/${targetConfig}.
# since native-compiles have $lib/lib as a directory (not a
# symlink), this ensures that in every case we can assume that
# $lib/lib contains the .so files
+ lib.optionalString isCross ''
if [ -e "$lib/$targetConfig/lib" ]; then
ln -s "$lib/$targetConfig/lib" "$lib/lib"
fi
'';
}
))

View File

@@ -0,0 +1,54 @@
{
lib,
stdenv,
nukeReferences,
langC,
langCC,
runtimeShell,
}:
let
enableChecksum =
(
with stdenv;
lib.systems.equals buildPlatform hostPlatform && lib.systems.equals hostPlatform targetPlatform
)
&& langC
&& langCC
&& !stdenv.hostPlatform.isDarwin;
in
(
pkg:
pkg.overrideAttrs (
previousAttrs:
lib.optionalAttrs enableChecksum {
outputs = previousAttrs.outputs ++ lib.optionals enableChecksum [ "checksum" ];
# This is a separate phase because gcc assembles its phase scripts
# in bash instead of nix (we should fix that).
preFixupPhases = (previousAttrs.preFixupPhases or [ ]) ++ [ "postInstallSaveChecksumPhase" ];
#
# gcc uses an auxiliary utility `genchecksum` to md5-hash (most of) its
# `.o` and `.a` files prior to linking (in case the linker is
# nondeterministic). Since we want to compare across gccs built from two
# separate derivations, we wrap `genchecksum` with a `nuke-references`
# call. We also stash copies of the inputs to `genchecksum` in
# `$checksum/inputs/` -- this is extremely helpful for debugging since
# it's hard to get Nix to not delete the $NIX_BUILD_TOP of a successful
# build.
#
postInstallSaveChecksumPhase = ''
mv gcc/build/genchecksum gcc/build/.genchecksum-wrapped
cat > gcc/build/genchecksum <<\EOF
#!${runtimeShell}
${nukeReferences}/bin/nuke-refs $@
for INPUT in "$@"; do install -Dt $INPUT $checksum/inputs/; done
exec build/.genchecksum-wrapped $@
EOF
chmod +x gcc/build/genchecksum
rm gcc/*-checksum.*
make -C gcc cc1-checksum.o cc1plus-checksum.o
install -Dt $checksum/checksums/ gcc/cc*-checksum.o
'';
}
)
)

View File

@@ -0,0 +1,296 @@
{
lib,
stdenv,
targetPackages,
withoutTargetLibc,
libcCross,
threadsCross,
version,
apple-sdk,
binutils,
gmp,
mpfr,
libmpc,
isl,
enableLTO,
enableMultilib,
enablePlugin,
disableGdbPlugin ? !enablePlugin,
enableShared,
enableDefaultPie,
targetPrefix,
langC,
langCC,
langFortran,
langAda ? false,
langGo,
langObjC,
langObjCpp,
langJit,
langRust ? false,
disableBootstrap ? (!lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform),
}:
assert !enablePlugin -> disableGdbPlugin;
# Note [Windows Exception Handling]
# sjlj (short jump long jump) exception handling makes no sense on x86_64,
# it's forcibly slowing programs down as it produces a constant overhead.
# On x86_64 we have SEH (Structured Exception Handling) and we should use
# that. On i686, we do not have SEH, and have to use sjlj with dwarf2.
# Hence it's now conditional on x86_32 (i686 is 32bit).
#
# ref: https://stackoverflow.com/questions/15670169/what-is-difference-between-sjlj-vs-dwarf-vs-seh
let
inherit (stdenv)
buildPlatform
hostPlatform
targetPlatform
;
# See https://github.com/NixOS/nixpkgs/pull/209870#issuecomment-1500550903
disableBootstrap' = disableBootstrap && !langFortran && !langGo;
crossMingw = (!lib.systems.equals targetPlatform hostPlatform) && targetPlatform.isMinGW;
crossDarwin =
(!lib.systems.equals targetPlatform hostPlatform) && targetPlatform.libc == "libSystem";
crossConfigureFlags =
# Ensure that -print-prog-name is able to find the correct programs.
[
"--with-as=${
if targetPackages.stdenv.cc.bintools.isLLVM then binutils else targetPackages.stdenv.cc.bintools
}/bin/${targetPlatform.config}-as"
]
++ (
if withoutTargetLibc then
[
"--disable-libssp"
"--disable-nls"
"--without-headers"
"--disable-threads"
"--disable-libgomp"
"--disable-libquadmath"
(lib.enableFeature enableShared "shared")
"--disable-libatomic" # requires libc
"--disable-decimal-float" # requires libc
"--disable-libmpx" # requires libc
"--disable-hosted-libstdcxx" # requires libc
"--disable-libstdcxx-backtrace"
"--disable-linux-futex"
"--disable-libvtv"
"--disable-libitm"
]
++ lib.optionals crossMingw [
"--with-headers=${lib.getDev libcCross}/include"
"--with-gcc"
"--with-gnu-as"
"--with-gnu-ld"
"--disable-debug"
"--disable-win32-registry"
"--enable-hash-synchronization"
"--enable-libssp"
"--disable-nls"
# To keep ABI compatibility with upstream mingw-w64
"--enable-fully-dynamic-string"
]
++ lib.optionals (crossMingw && targetPlatform.isx86_32) [
# See Note [Windows Exception Handling]
"--enable-sjlj-exceptions"
"--with-dwarf2"
]
else
[
(
if crossDarwin then
"--with-sysroot=${lib.getLib libcCross}/share/sysroot"
else
"--with-headers=${lib.getDev libcCross}${libcCross.incdir or "/include"}"
)
"--enable-__cxa_atexit"
"--enable-long-long"
"--enable-threads=${
if targetPlatform.isUnix then
"posix"
else if targetPlatform.isWindows then
(threadsCross.model or "win32")
else
"single"
}"
"--enable-nls"
]
++ lib.optionals (targetPlatform.libc == "uclibc" || targetPlatform.libc == "musl") [
# libsanitizer requires netrom/netrom.h which is not
# available in uclibc.
"--disable-libsanitizer"
]
++ lib.optional (
targetPlatform.libc == "newlib" || targetPlatform.libc == "newlib-nano"
) "--with-newlib"
++ lib.optional (targetPlatform.libc == "avrlibc") "--with-avrlibc"
);
configureFlags =
# Basic dependencies
[
"--with-gmp-include=${gmp.dev}/include"
"--with-gmp-lib=${gmp.out}/lib"
"--with-mpfr-include=${mpfr.dev}/include"
"--with-mpfr-lib=${mpfr.out}/lib"
"--with-mpc=${libmpc}"
]
++ lib.optionals (!withoutTargetLibc) [
(
if libcCross == null then
(
# GCC will search for the headers relative to SDKROOT on Darwin, so it will find them in the store.
if targetPlatform.isDarwin then
"--with-native-system-header-dir=/usr/include"
else
"--with-native-system-header-dir=${lib.getDev stdenv.cc.libc}/include"
)
else
"--with-native-system-header-dir=${lib.getDev libcCross}${libcCross.incdir or "/include"}"
)
# gcc builds for cross-compilers (build != host) or cross-built
# gcc (host != target) always apply the offset prefix to disentangle
# target headers from build or host headers:
# ${with_build_sysroot}${native_system_header_dir}
# or ${test_exec_prefix}/${target_noncanonical}/sys-include
# or ${with_sysroot}${native_system_header_dir}
# While native build (build == host == target) uses passed headers
# path as is:
# ${with_build_sysroot}${native_system_header_dir}
#
# Nixpkgs uses flat directory structure for both native and cross
# cases. As a result libc headers don't get found for cross case
# and many modern features get disabled (libssp is used instead of
# target-specific implementations and similar). More details at:
# https://github.com/NixOS/nixpkgs/pull/181802#issuecomment-1186822355
#
# We pick "/" path to effectively avoid sysroot offset and make it work
# as a native case.
# Darwin requires using the SDK as the sysroot for `SDKROOT` to work correctly.
"--with-build-sysroot=${if targetPlatform.isDarwin then apple-sdk.sdkroot else "/"}"
# Same with the stdlibc++ headers embedded in the gcc output
"--with-gxx-include-dir=${placeholder "out"}/include/c++/${version}/"
]
# Basic configuration
++ [
# Force target prefix. The behavior if `--target` and `--host`
# are specified is inconsistent: Sometimes specifying `--target`
# always causes a prefix to be generated, sometimes it's only
# added if the `--host` and `--target` differ. This means that
# sometimes there may be a prefix even though nixpkgs doesn't
# expect one and sometimes there may be none even though nixpkgs
# expects one (since not all information is serialized into the
# config attribute). The easiest way out of these problems is to
# always set the program prefix, so gcc will conform to our
# expectations.
"--program-prefix=${targetPrefix}"
(lib.enableFeature enableLTO "lto")
"--disable-libstdcxx-pch"
"--without-included-gettext"
"--with-system-zlib"
"--enable-static"
"--enable-languages=${
lib.concatStringsSep "," (
lib.optional langC "c"
++ lib.optional langCC "c++"
++ lib.optional langFortran "fortran"
++ lib.optional langAda "ada"
++ lib.optional langGo "go"
++ lib.optional langObjC "objc"
++ lib.optional langObjCpp "obj-c++"
++ lib.optionals crossDarwin [
"objc"
"obj-c++"
]
++ lib.optional langJit "jit"
++ lib.optional langRust "rust"
)
}"
]
++ (
if (enableMultilib || targetPlatform.isAvr) then
[
"--enable-multilib"
"--disable-libquadmath"
]
else
[ "--disable-multilib" ]
)
++ lib.optional (!enableShared) "--disable-shared"
++ lib.singleton (lib.enableFeature enablePlugin "plugin")
# Libcc1 is the GCC cc1 plugin for the GDB debugger which is only used by gdb
++ lib.optional disableGdbPlugin "--disable-libcc1"
# Support -m32 on powerpc64le/be
++ lib.optional (targetPlatform.system == "powerpc64le-linux") "--enable-targets=powerpcle-linux"
++ lib.optional (targetPlatform.system == "powerpc64-linux") "--enable-targets=powerpc-linux"
# Fix "unknown long double size, cannot define BFP_FMT"
++ lib.optional (targetPlatform.isPower && targetPlatform.isMusl) "--disable-decimal-float"
# Optional features
++ lib.optional (isl != null) "--with-isl=${isl}"
# Ada options, gcc can't build the runtime library for a cross compiler
++ lib.optional langAda (
if lib.systems.equals hostPlatform targetPlatform then "--enable-libada" else "--disable-libada"
)
++ import ../common/platform-flags.nix {
inherit (stdenv) targetPlatform;
inherit lib;
}
++ lib.optionals (!lib.systems.equals targetPlatform hostPlatform) crossConfigureFlags
++ lib.optional disableBootstrap' "--disable-bootstrap"
# Platform-specific flags
++ lib.optional (
lib.systems.equals targetPlatform hostPlatform && targetPlatform.isx86_32
) "--with-arch=${stdenv.hostPlatform.parsed.cpu.name}"
++ lib.optional (targetPlatform.isNetBSD || targetPlatform.isCygwin) "--disable-libssp" # Provided by libc.
++ lib.optionals hostPlatform.isSunOS [
"--enable-long-long"
"--enable-libssp"
"--enable-threads=posix"
"--disable-nls"
"--enable-__cxa_atexit"
# On Illumos/Solaris GNU as is preferred
"--with-gnu-as"
"--without-gnu-ld"
]
++
lib.optional (targetPlatform.libc == "musl")
# musl at least, disable: https://git.buildroot.net/buildroot/commit/?id=873d4019f7fb00f6a80592224236b3ba7d657865
"--disable-libmpx"
++ lib.optionals (lib.systems.equals targetPlatform hostPlatform && targetPlatform.libc == "musl") [
"--disable-libsanitizer"
"--disable-symvers"
"libat_cv_have_ifunc=no"
"--disable-gnu-indirect-function"
]
++ lib.optionals enableDefaultPie [
"--enable-default-pie"
]
++ lib.optionals langJit [
"--enable-host-shared"
]
++ lib.optionals targetPlatform.isAlpha [
# Workaround build failures like:
# cc1: error: fp software completion requires '-mtrap-precision=i' [-Werror]
"--disable-werror"
];
in
configureFlags

View File

@@ -0,0 +1,86 @@
{
lib,
stdenv,
version,
buildPackages,
targetPackages,
texinfo,
which,
gettext,
gnused,
patchelf,
gmp,
mpfr,
libmpc,
libucontext ? null,
libxcrypt ? null,
isSnapshot ? false,
isl ? null,
zlib ? null,
gnat-bootstrap ? null,
flex ? null,
perl ? null,
langAda ? false,
langGo ? false,
langRust ? false,
cargo,
withoutTargetLibc ? null,
threadsCross ? null,
}:
let
inherit (lib) optionals;
inherit (stdenv) buildPlatform hostPlatform targetPlatform;
in
{
# same for all gcc's
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
texinfo
which
gettext
]
++ optionals (perl != null) [ perl ]
++ optionals (with stdenv.targetPlatform; isVc4 || isRedox || isSnapshot && flex != null) [ flex ]
++ optionals langAda [ gnat-bootstrap ]
++ optionals langRust [ cargo ]
# The builder relies on GNU sed (for instance, Darwin's `sed' fails with
# "-i may not be used with stdin"), and `stdenvNative' doesn't provide it.
++ optionals buildPlatform.isDarwin [ gnused ];
# For building runtime libs
# same for all gcc's
depsBuildTarget =
(
if lib.systems.equals hostPlatform buildPlatform then
[
targetPackages.stdenv.cc.bintools # newly-built gcc will be used
]
else
assert lib.systems.equals targetPlatform hostPlatform;
[
# build != host == target
stdenv.cc
]
)
++ optionals targetPlatform.isLinux [ patchelf ];
buildInputs = [
gmp
mpfr
libmpc
libxcrypt
]
++ [
targetPackages.stdenv.cc.bintools # For linking code at run-time
]
++ optionals (isl != null) [ isl ]
++ optionals (zlib != null) [ zlib ]
++ optionals (langGo && stdenv.hostPlatform.isMusl) [ libucontext ];
depsTargetTarget = optionals (
!withoutTargetLibc && threadsCross != { } && threadsCross.package != null
) [ threadsCross.package ];
}

View File

@@ -0,0 +1,58 @@
{
lib,
stdenv,
withoutTargetLibc,
libcCross,
threadsCross,
}:
let
inherit (stdenv) hostPlatform targetPlatform;
in
{
# For non-cross builds these flags are currently assigned in builder.sh.
# It would be good to consolidate the generation of makeFlags
# ({C,CXX,LD}FLAGS_FOR_{BUILD,TARGET}, etc...) at some point.
EXTRA_FLAGS_FOR_TARGET =
let
mkFlags =
dep:
lib.optionals ((!lib.systems.equals targetPlatform hostPlatform) && dep != null) (
[
"-O2 -idirafter ${lib.getDev dep}${dep.incdir or "/include"}"
]
++ lib.optionals (!withoutTargetLibc) [
"-B${lib.getLib dep}${dep.libdir or "/lib"}"
]
);
in
mkFlags libcCross
++ lib.optionals (!withoutTargetLibc) (mkFlags (threadsCross.package or null))
++ mkFlags (libcCross.w32api or null);
EXTRA_LDFLAGS_FOR_TARGET =
let
mkFlags =
dep:
lib.optionals ((!lib.systems.equals targetPlatform hostPlatform) && dep != null) (
[
"-Wl,-L${lib.getLib dep}${dep.libdir or "/lib"}"
]
++ (
if withoutTargetLibc then
[
"-B${lib.getLib dep}${dep.libdir or "/lib"}"
]
else
[
"-Wl,-rpath,${lib.getLib dep}${dep.libdir or "/lib"}"
"-Wl,-rpath-link,${lib.getLib dep}${dep.libdir or "/lib"}"
]
)
);
in
mkFlags libcCross
++ lib.optionals (!withoutTargetLibc) (mkFlags (threadsCross.package or null))
++ mkFlags (libcCross.w32api or null);
}

View File

@@ -0,0 +1,60 @@
{
lib,
stdenv,
}:
# Trick to build a gcc that is capable of emitting shared libraries *without* having the
# targetPlatform libc available beforehand. Taken from:
# https://web.archive.org/web/20170222224855/http://frank.harvard.edu/~coldwell/toolchain/
# https://web.archive.org/web/20170224235700/http://frank.harvard.edu/~coldwell/toolchain/t-linux.diff
let
# crt{i,n}.o are the first and last (respectively) object file
# linked when producing an executable. Traditionally these
# files are delivered as part of the C library, but on GNU
# systems they are in fact built by GCC. Since libgcc needs to
# build before glibc, we can't wait for them to be copied by
# glibc. At this early pre-glibc stage these files sometimes
# have different names.
crtstuff-ofiles =
if stdenv.targetPlatform.isPower64 then "ecrti.o ecrtn.o ncrti.o ncrtn.o" else "crti.o crtn.o";
# Normally, `SHLIB_LC` is set to `-lc`, which means that
# `libgcc_s.so` cannot be built until `libc.so` is available.
# The assignment below clobbers this variable, removing the
# `-lc`.
#
# On PowerPC we add `-mnewlib`, which means "libc has not been
# built yet". This causes libgcc's Makefile to use the
# gcc-built `{e,n}crt{n,i}.o` instead of failing to find the
# versions which have been repackaged in libc as `crt{n,i}.o`
#
SHLIB_LC = lib.optionalString stdenv.targetPlatform.isPower64 "-mnewlib";
in
''
echo 'libgcc.a: ${crtstuff-ofiles}' >> libgcc/Makefile.in
echo 'SHLIB_LC=${SHLIB_LC}' >> libgcc/Makefile.in
''
# Meanwhile, crt{i,n}.S are not present on certain platforms
# (e.g. LoongArch64), resulting in the following error:
#
# No rule to make target '../../../gcc-xx.x.x/libgcc/config/loongarch/crti.S', needed by 'crti.o'. Stop.
#
# For LoongArch64 and S390, a hacky workaround is to simply touch them,
# as the platform forces .init_array support.
#
# https://www.openwall.com/lists/musl/2022/11/09/3
#
# 'parsed.cpu.family' won't be correct for every platform.
+ (lib.optionalString
(
stdenv.targetPlatform.isLoongArch64 || stdenv.targetPlatform.isS390 || stdenv.targetPlatform.isAlpha
)
''
touch libgcc/config/${stdenv.targetPlatform.parsed.cpu.family}/crt{i,n}.S
''
)
+ lib.optionalString (stdenv.targetPlatform.isPower && !stdenv.targetPlatform.isPower64) ''
touch libgcc/config/rs6000/crt{i,n}.S
''

View File

@@ -0,0 +1,181 @@
{
lib,
stdenv,
version,
langC,
langCC,
langJit,
enableShared,
targetPlatform,
hostPlatform,
withoutTargetLibc,
libcCross,
}:
assert !stdenv.targetPlatform.hasSharedLibraries -> !enableShared;
drv:
lib.pipe drv
(
[
(
pkg:
pkg.overrideAttrs (
previousAttrs:
lib.optionalAttrs
(
(!lib.systems.equals targetPlatform hostPlatform)
&& (enableShared || targetPlatform.isMinGW)
&& withoutTargetLibc
)
{
makeFlags = [
"all-gcc"
"all-target-libgcc"
];
installTargets = "install-gcc install-target-libgcc";
}
)
)
]
++ (
let
targetPlatformSlash =
if lib.systems.equals hostPlatform targetPlatform then "" else "${targetPlatform.config}/";
# If we are building a cross-compiler and the target libc provided
# to us at build time has a libgcc, use that instead of building a
# new one. This avoids having two separate (but identical) libgcc
# outpaths in the closure of most packages, which can be confusing.
useLibgccFromTargetLibc = libcCross != null && libcCross ? passthru.libgcc;
enableLibGccOutput =
(
!(stdenv.targetPlatform.isWindows || stdenv.targetPlatform.isCygwin)
|| (lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform)
)
&& !langJit
&& !stdenv.hostPlatform.isDarwin
&& enableShared
&& !useLibgccFromTargetLibc;
# For some reason libgcc_s.so has major-version "2" on m68k but
# "1" everywhere else. Might be worth changing this to "*".
libgcc_s-version-major = if targetPlatform.isM68k then "2" else "1";
in
[
(
pkg:
pkg.overrideAttrs (
previousAttrs:
lib.optionalAttrs useLibgccFromTargetLibc {
passthru = (previousAttrs.passthru or { }) // {
inherit (libcCross) libgcc;
};
}
)
)
(
pkg:
pkg.overrideAttrs (
previousAttrs:
lib.optionalAttrs ((!langC) || langJit || enableLibGccOutput) {
outputs = previousAttrs.outputs ++ lib.optionals enableLibGccOutput [ "libgcc" ];
# This is a separate phase because gcc assembles its phase scripts
# in bash instead of nix (we should fix that).
preFixupPhases =
(previousAttrs.preFixupPhases or [ ])
++ lib.optionals ((!langC) || enableLibGccOutput) [ "preFixupLibGccPhase" ];
preFixupLibGccPhase =
# delete extra/unused builds of libgcc_s in non-langC builds
# (i.e. libgccjit, gnat, etc) to avoid potential confusion
lib.optionalString (!langC) ''
rm -f $out/lib/libgcc_s.so*
''
# move `libgcc_s.so` into its own output, `$libgcc`
# We maintain $libgcc/lib/$target/ structure to make sure target
# strip runs over libgcc_s.so and remove debug references to headers:
# https://github.com/NixOS/nixpkgs/issues/316114
+ lib.optionalString enableLibGccOutput (
''
# move libgcc from lib to its own output (libgcc)
mkdir -p $libgcc/${targetPlatformSlash}lib
mv $lib/${targetPlatformSlash}lib/libgcc_s.so $libgcc/${targetPlatformSlash}lib/
mv $lib/${targetPlatformSlash}lib/libgcc_s.so.${libgcc_s-version-major} $libgcc/${targetPlatformSlash}lib/
ln -s $libgcc/${targetPlatformSlash}lib/libgcc_s.so $lib/${targetPlatformSlash}lib/
ln -s $libgcc/${targetPlatformSlash}lib/libgcc_s.so.${libgcc_s-version-major} $lib/${targetPlatformSlash}lib/
''
+ lib.optionalString (targetPlatformSlash != "") ''
ln -s ${targetPlatformSlash}lib $libgcc/lib
''
#
# Nixpkgs ordinarily turns dynamic linking into pseudo-static linking:
# libraries are still loaded dynamically, exactly which copy of each
# library is loaded is permanently fixed at compile time (via RUNPATH).
# For libgcc_s we must revert to the "impure dynamic linking" style found
# in imperative software distributions. We must do this because
# `libgcc_s` calls `malloc()` and therefore has a `DT_NEEDED` for `libc`,
# which creates two problems:
#
# 1. A circular package dependency `glibc`<-`libgcc`<-`glibc`
#
# 2. According to the `-Wl,-rpath` flags added by Nixpkgs' `ld-wrapper`,
# the two versions of `glibc` in the cycle above are actually
# different packages. The later one is compiled by this `gcc`, but
# the earlier one was compiled by the compiler *that compiled* this
# `gcc` (usually the bootstrapFiles). In any event, the `glibc`
# dynamic loader won't honor that specificity without namespaced
# manual loads (`dlmopen()`). Once a `libc` is present in the address
# space of a process, that `libc` will be used to satisfy all
# `DT_NEEDED`s for `libc`, regardless of `RUNPATH`s.
#
# So we wipe the RUNPATH using `patchelf --set-rpath ""`. We can't use
# `patchelf --remove-rpath`, because at least as of patchelf 0.15.0 it
# will leave the old RUNPATH string in the file where the reference
# scanner can still find it:
#
# https://github.com/NixOS/patchelf/issues/453
#
# Note: we might be using the bootstrapFiles' copy of patchelf, so we have
# to keep doing it this way until both the issue is fixed *and* all the
# bootstrapFiles are regenerated, on every platform.
#
# This patchelfing is *not* effectively equivalent to copying
# `libgcc_s` into `glibc`'s outpath. There is one minor and one
# major difference:
#
# 1. (Minor): multiple builds of `glibc` (say, with different
# overrides or parameters) will all reference a single store
# path:
#
# /nix/store/xxx...xxx-gcc-libgcc/lib/libgcc_s.so.1
#
# This many-to-one referrer relationship will be visible in the store's
# dependency graph, and will be available to `nix-store -q` queries.
# Copying `libgcc_s` into each of its referrers would lose that
# information.
#
# 2. (Major): by referencing `libgcc_s.so.1`, rather than copying it, we
# are still able to run `nix-store -qd` on it to find out how it got
# built! Most importantly, we can see from that deriver which compiler
# was used to build it (or if it is part of the unpacked
# bootstrap-files). Copying `libgcc_s.so.1` from one outpath to
# another eliminates the ability to make these queries.
#
+ ''
patchelf --set-rpath "" $libgcc/lib/libgcc_s.so.${libgcc_s-version-major}
''
);
}
)
)
]
)
)

View File

@@ -0,0 +1,34 @@
{
lib,
version,
targetPrefix,
}:
let
inherit (lib)
licenses
maintainers
platforms
teams
versionOlder
;
in
{
homepage = "https://gcc.gnu.org/";
license = licenses.gpl3Plus; # runtime support libraries are typically LGPLv3+
description = "GNU Compiler Collection, version ${version}";
longDescription = ''
The GNU Compiler Collection includes compiler front ends for C, C++,
Objective-C, Fortran, OpenMP for C/C++/Fortran, and Ada, as well as
libraries for these languages (libstdc++, libgomp,...).
GCC development is a part of the GNU Project, aiming to improve the
compiler used in the GNU system including the GNU/Linux variant.
'';
platforms = platforms.unix;
teams = [ teams.gcc ];
mainProgram = "${targetPrefix}gcc";
identifiers.cpeParts.vendor = "gnu";
}

View File

@@ -0,0 +1,47 @@
{ lib, targetPlatform }:
let
isAarch64Darwin = targetPlatform.isDarwin && targetPlatform.isAarch64;
gcc = targetPlatform.gcc or { };
p = gcc // targetPlatform.parsed.abi;
in
lib.concatLists [
# --with-arch= is unknown flag on x86_64 and aarch64-darwin.
(lib.optional (!targetPlatform.isx86_64 && !isAarch64Darwin && p ? arch) "--with-arch=${p.arch}")
# See supported_defaults in gcc/config.gcc for architecture support.
# --with-cpu on aarch64-darwin fails with "Unknown cpu used in --with-cpu=apple-a13".
(lib.optional (
with targetPlatform; !isLoongArch64 && !isMips && !isRiscV && !isS390 && !isAarch64Darwin && p ? cpu
) "--with-cpu=${p.cpu}")
(lib.optional (p ? abi) "--with-abi=${p.abi}")
(lib.optional (p ? fpu) "--with-fpu=${p.fpu}")
(lib.optional (p ? float) "--with-float=${p.float}")
(lib.optional (p ? mode) "--with-mode=${p.mode}")
(lib.optionals targetPlatform.isPower64
# musl explicitly rejects 128-bit long double on
# powerpc64; see musl/arch/powerpc64/bits/float.h
(
lib.optionals
(
!targetPlatform.isMusl
&& (
targetPlatform.isLittleEndian
||
# "... --with-long-double-format is only supported if the default cpu is power7 or newer"
# https://github.com/NixOS/nixpkgs/pull/170215#issuecomment-1202164709
(lib.lists.elem (lib.strings.substring 0 6 (p.cpu or "")) [
"power7"
"power8"
"power9"
"power1" # 0, 11, etc
])
)
)
[
"--with-long-double-128"
"--with-long-double-format=${gcc.long-double-format or "ieee"}"
]
)
)
(lib.optional targetPlatform.isMips64n32 "--disable-libsanitizer") # libsanitizer does not compile on mips64n32
]

View File

@@ -0,0 +1,85 @@
{
lib,
stdenv,
version,
buildPlatform,
hostPlatform,
targetPlatform,
gnat-bootstrap ? null,
langAda ? false,
langFortran,
langJit ? false,
langGo,
withoutTargetLibc,
enableShared,
enableMultilib,
pkgsBuildTarget,
}:
assert langAda -> gnat-bootstrap != null;
lib.optionalString (hostPlatform.isSunOS && hostPlatform.is64bit) ''
export NIX_LDFLAGS=`echo $NIX_LDFLAGS | sed -e s~$prefix/lib~$prefix/lib/amd64~g`
export LDFLAGS_FOR_TARGET="-Wl,-rpath,$prefix/lib/amd64 $LDFLAGS_FOR_TARGET"
export CXXFLAGS_FOR_TARGET="-Wl,-rpath,$prefix/lib/amd64 $CXXFLAGS_FOR_TARGET"
export CFLAGS_FOR_TARGET="-Wl,-rpath,$prefix/lib/amd64 $CFLAGS_FOR_TARGET"
''
+ lib.optionalString langAda ''
export PATH=${gnat-bootstrap}/bin:$PATH
''
# For a cross-built native compiler, i.e. build!=(host==target), the
# bundled libgfortran needs a gfortran which can run on the
# buildPlatform and emit code for the targetPlatform. The compiler
# which is built alongside gfortran in this configuration doesn't
# meet that need: it runs on the hostPlatform.
+
lib.optionalString
(
langFortran
&& (
(!lib.systems.equals buildPlatform hostPlatform) && (lib.systems.equals hostPlatform targetPlatform)
)
)
''
export GFORTRAN_FOR_TARGET=${pkgsBuildTarget.gfortran}/bin/${stdenv.targetPlatform.config}-gfortran
''
# In order to properly install libgccjit on macOS Catalina, strip(1)
# upon installation must not remove external symbols, otherwise the
# install step errors with "symbols referenced by indirect symbol
# table entries that can't be stripped".
+ lib.optionalString (hostPlatform.isDarwin && langJit) ''
export STRIP='strip -x'
''
# HACK: if host and target config are the same, but the platforms are
# actually different we need to convince the configure script that it
# is in fact building a cross compiler although it doesn't believe it.
+
lib.optionalString
(targetPlatform.config == hostPlatform.config && (!lib.systems.equals targetPlatform hostPlatform))
''
substituteInPlace configure --replace is_cross_compiler=no is_cross_compiler=yes
''
# Normally (for host != target case) --without-headers automatically
# enables 'inhibit_libc=true' in gcc's gcc/configure.ac. But case of
# gcc->clang or dynamic->static "cross"-compilation manages to evade it: there
# ! lib.systems.equals hostPlatform targetPlatform, hostPlatform.config == targetPlatform.config.
# We explicitly inhibit libc headers use in this case as well.
+
lib.optionalString
(
(!lib.systems.equals targetPlatform hostPlatform)
&& withoutTargetLibc
&& targetPlatform.config == hostPlatform.config
)
''
export inhibit_libc=true
''
+ lib.optionalString (
(!lib.systems.equals targetPlatform hostPlatform) && withoutTargetLibc && enableShared
) (import ./libgcc-buildstuff.nix { inherit lib stdenv; })

View File

@@ -0,0 +1,82 @@
{
lib,
stdenv,
langJit,
}:
{
# Note [Cross-compiler stripping]
# gcc requires delicate stripping as it installs ELF files for both
# HOST and TARGET platforms. It requires according strip tool otherwise
# strip could remove sections it's not aware of.
# Example ARM breakage by x86_64 strip: https://bugs.gentoo.org/697428
#
# Let's recap the file layout for directories with object files for a
# cross-compiler:
#
# $out (host != target)
# `- bin: HOST
# lib/*.{a,o}: HOST
# `- gcc/<TARGET>/<VERSION>/*.{a,o}: TARGET
# `- plugin/: HOST
# `- lib{,32,64,x32}: symlink to lib or identical layout
# `- libexec/: HOST
# `- <TARGET>/: TARGET
#
# $out (host == target) has identical directory layout.
#
# $lib (host != target):
# `- <TARGET>/lib/*.{la,so}: TARGET
#
# $lib (host == target):
# `- lib/*.{la,so}: HOST
# The rest of stripDebugList{Host,Target} will be populated in
# postInstall to disambiguate lib/ object files.
stripDebugList = [
"bin"
"libexec"
];
stripDebugListTarget = [ stdenv.targetPlatform.config ];
preFixup = ''
# Populate most delicated lib/ part of stripDebugList{,Target}
updateDebugListPaths() {
local oldOpts
oldOpts="$(shopt -p nullglob)" || true
shopt -s nullglob
pushd $out
local -ar outHostFiles=(
lib{,32,64}/*.{a,o,so*}
lib{,32,64}/gcc/${stdenv.targetPlatform.config}/*/plugin
)
local -ar outTargetFiles=(
lib{,32,64}/gcc/${stdenv.targetPlatform.config}/*/*.{a,o,so*}
)
popd
''
+ lib.optionalString (!langJit) ''
${
# keep indentation
""
}
pushd $lib
local -ar libHostFiles=(
lib{,32,64}/*.{a,o,so*}
)
local -ar libTargetFiles=(
lib{,32,64}/${stdenv.targetPlatform.config}/*.{a,o,so*}
)
popd
''
+ ''
eval "$oldOpts"
stripDebugList="$stripDebugList ''${outHostFiles[*]} ''${libHostFiles[*]}"
stripDebugListTarget="$stripDebugListTarget ''${outTargetFiles[*]} ''${libTargetFiles[*]}"
}
updateDebugListPaths
'';
}