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,74 @@
{
lib,
stdenv,
pkgs,
targetPackages,
callPackage,
isl_0_20,
noSysDirs,
lowPrio,
wrapCC,
}@args:
let
versions = import ./versions.nix;
gccForMajorMinorVersion =
majorMinorVersion:
let
majorVersion = lib.versions.major majorMinorVersion;
atLeast = lib.versionAtLeast majorMinorVersion;
attrName = "gcc${lib.replaceStrings [ "." ] [ "" ] majorMinorVersion}";
pkg = lowPrio (
wrapCC (
callPackage ./default.nix {
inherit noSysDirs;
inherit majorMinorVersion;
reproducibleBuild = true;
profiledCompiler = false;
libcCross =
if !lib.systems.equals stdenv.targetPlatform stdenv.buildPlatform then
targetPackages.libc or pkgs.libc
else
null;
threadsCross =
if !lib.systems.equals stdenv.targetPlatform stdenv.buildPlatform then
targetPackages.threads or pkgs.threads
else
{ };
isl = if stdenv.hostPlatform.isDarwin then null else isl_0_20;
# do not allow version skew when cross-building gcc
#
# When `gcc` is cross-built (`build` != `target` && `host` == `target`)
# `gcc` assumes that it has a compatible cross-compiler in the environment
# that can build target libraries. Version of a cross-compiler has to
# match the compiler being cross-built as libraries frequently use fresh
# compiler features, like `-std=c++26` or target-specific types like
# `_Bfloat16`.
# Version mismatch causes build failures like:
# https://github.com/NixOS/nixpkgs/issues/351905
#
# Similar problems (but on a smaller scale) happen when a `gcc`
# cross-compiler is built (`build` == `host` && `host` != `target`) built
# by a mismatching version of a native compiler (`build` == `host` &&
# `host` == `target`).
#
# Let's fix both problems by requiring the same compiler version for
# cross-case.
stdenv =
if
(
(!lib.systems.equals stdenv.targetPlatform stdenv.buildPlatform)
|| (!lib.systems.equals stdenv.hostPlatform stdenv.targetPlatform)
)
&& stdenv.cc.isGNU
then
pkgs."gcc${majorVersion}Stdenv"
else
stdenv;
}
)
);
in
lib.nameValuePair attrName pkg;
in
lib.listToAttrs (map gccForMajorMinorVersion versions.allMajorVersions)

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
'';
}

View File

@@ -0,0 +1,447 @@
{
lib,
stdenv,
targetPackages,
fetchurl,
fetchpatch,
noSysDirs,
langC ? true,
langCC ? true,
langFortran ? false,
langAda ? false,
langObjC ? stdenv.targetPlatform.isDarwin,
langObjCpp ? stdenv.targetPlatform.isDarwin,
langGo ? false,
reproducibleBuild ? true,
profiledCompiler ? false,
langJit ? false,
langRust ? false,
cargo,
staticCompiler ? false,
enableShared ? stdenv.targetPlatform.hasSharedLibraries,
enableDefaultPie ? true,
enableLTO ? stdenv.hostPlatform.hasSharedLibraries,
texinfo ? null,
perl ? null, # optional, for texi2pod (then pod2man)
gmp,
mpfr,
libmpc,
gettext,
which,
patchelf,
binutils,
isl ? null, # optional, for the Graphite optimization framework.
zlib ? null,
libucontext ? null,
gnat-bootstrap ? null,
enableMultilib ? false,
enablePlugin ? (lib.systems.equals stdenv.hostPlatform stdenv.buildPlatform), # Whether to support user-supplied plug-ins
name ? "gcc",
libcCross ? null,
threadsCross ? { }, # for MinGW
withoutTargetLibc ? stdenv.targetPlatform.libc == null,
flex,
gnused ? null,
buildPackages,
pkgsBuildTarget,
libxcrypt,
disableGdbPlugin ?
!enablePlugin
|| (stdenv.targetPlatform.isAvr && stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64),
nukeReferences,
callPackage,
majorMinorVersion,
apple-sdk,
darwin,
}:
let
inherit (lib)
callPackageWith
filter
getBin
maintainers
makeLibraryPath
makeSearchPathOutput
mapAttrs
optional
optionalAttrs
optionals
optionalString
pipe
platforms
versionAtLeast
versions
;
gccVersions = import ./versions.nix;
version = gccVersions.fromMajorMinor majorMinorVersion;
majorVersion = versions.major version;
atLeast14 = versionAtLeast version "14";
is14 = majorVersion == "14";
is13 = majorVersion == "13";
# releases have a form: MAJOR.MINOR.MICRO, like 14.2.1
# snapshots have a form like MAJOR.MINOR.MICRO.DATE, like 14.2.1.20250322
isSnapshot = lib.length (lib.splitVersion version) == 4;
# return snapshot date of gcc's given version:
# "14.2.1.20250322" -> "20250322"
# "14.2.0" -> ""
snapDate = lib.concatStrings (lib.drop 3 (lib.splitVersion version));
# return base version without a snapshot:
# "14.2.1.20250322" -> "14.2.1"
# "14.2.0" -> "14.2.0"
baseVersion = lib.concatStringsSep "." (lib.take 3 (lib.splitVersion version));
disableBootstrap = !stdenv.hostPlatform.isDarwin && !profiledCompiler;
inherit (stdenv) buildPlatform hostPlatform targetPlatform;
targetConfig =
if (!lib.systems.equals targetPlatform hostPlatform) then targetPlatform.config else null;
patches = callFile ./patches { };
# Cross-gcc settings (build == host != target)
crossMingw = (!lib.systems.equals targetPlatform hostPlatform) && targetPlatform.isMinGW;
stageNameAddon = optionalString withoutTargetLibc "-nolibc";
crossNameAddon = optionalString (
!lib.systems.equals targetPlatform hostPlatform
) "${targetPlatform.config}${stageNameAddon}-";
targetPrefix = lib.optionalString (
!lib.systems.equals stdenv.targetPlatform stdenv.hostPlatform
) "${stdenv.targetPlatform.config}-";
callFile = callPackageWith {
# lets
inherit
majorVersion
isSnapshot
version
buildPlatform
hostPlatform
targetPlatform
targetConfig
patches
crossMingw
stageNameAddon
crossNameAddon
;
# inherit generated with 'nix eval --json --impure --expr "with import ./. {}; lib.attrNames (lib.functionArgs gcc${majorVersion}.cc.override)" | jq '.[]' --raw-output'
inherit
apple-sdk
binutils
buildPackages
cargo
withoutTargetLibc
darwin
disableBootstrap
disableGdbPlugin
enableDefaultPie
enableLTO
enableMultilib
enablePlugin
enableShared
fetchpatch
fetchurl
flex
gettext
gmp
gnat-bootstrap
gnused
isl
langAda
langC
langCC
langFortran
langGo
langJit
langObjC
langObjCpp
langRust
lib
libcCross
libmpc
libucontext
libxcrypt
mpfr
name
noSysDirs
nukeReferences
patchelf
perl
pkgsBuildTarget
profiledCompiler
reproducibleBuild
staticCompiler
stdenv
targetPackages
texinfo
threadsCross
which
zlib
;
};
in
# Make sure we get GNU sed.
assert stdenv.buildPlatform.isDarwin -> gnused != null;
# The go frontend is written in c++
assert langGo -> langCC;
assert langAda -> gnat-bootstrap != null;
# threadsCross is just for MinGW
assert threadsCross != { } -> stdenv.targetPlatform.isWindows;
# profiledCompiler builds inject non-determinism in one of the compilation stages.
# If turned on, we can't provide reproducible builds anymore
assert reproducibleBuild -> profiledCompiler == false;
pipe
((callFile ./common/builder.nix { }) (
{
pname = "${crossNameAddon}${name}";
# retain snapshot date in package version, but not in final version
# as the version is frequently used to construct pathnames (at least
# in cc-wrapper).
name = "${crossNameAddon}${name}-${version}";
version = baseVersion;
src = fetchurl {
url =
if isSnapshot then
"mirror://gcc/snapshots/${majorVersion}-${snapDate}/gcc-${majorVersion}-${snapDate}.tar.xz"
else
"mirror://gcc/releases/gcc-${version}/gcc-${version}.tar.xz";
${if is13 then "hash" else "sha256"} = gccVersions.srcHashForVersion version;
};
inherit patches;
outputs = [
"out"
"man"
"info"
]
++ optional (!langJit) "lib";
setOutputFlags = false;
libc_dev = stdenv.cc.libc_dev;
hardeningDisable = [
"format"
"pie"
"stackclashprotection"
];
postPatch = ''
configureScripts=$(find . -name configure)
for configureScript in $configureScripts; do
patchShebangs $configureScript
done
# Make sure nixpkgs versioning match upstream one
# to ease version-based comparisons.
gcc_base_version=$(< gcc/BASE-VER)
if [[ ${baseVersion} != $gcc_base_version ]]; then
echo "Please update 'version' variable:"
echo " Expected: '$gcc_base_version'"
echo " Actual: '${version}'"
exit 1
fi
''
# This should kill all the stdinc frameworks that gcc and friends like to
# insert into default search paths.
+ optionalString hostPlatform.isDarwin ''
substituteInPlace gcc/config/darwin-c.cc \
--replace 'if (stdinc)' 'if (0)'
substituteInPlace libgcc/config/t-slibgcc-darwin \
--replace "-install_name @shlib_slibdir@/\$(SHLIB_INSTALL_NAME)" "-install_name ''${!outputLib}/lib/\$(SHLIB_INSTALL_NAME)"
substituteInPlace libgfortran/configure \
--replace "-install_name \\\$rpath/\\\$soname" "-install_name ''${!outputLib}/lib/\\\$soname"
''
+ (optionalString ((!lib.systems.equals targetPlatform hostPlatform) || stdenv.cc.libc != null)
# On NixOS, use the right path to the dynamic linker instead of
# `/lib/ld*.so'.
(
let
libc = if libcCross != null then libcCross else stdenv.cc.libc;
in
(
''
echo "fixing the {GLIBC,UCLIBC,MUSL}_DYNAMIC_LINKER macros..."
for header in "gcc/config/"*-gnu.h "gcc/config/"*"/"*.h
do
grep -q _DYNAMIC_LINKER "$header" || continue
echo " fixing $header..."
sed -i "$header" \
-e 's|define[[:blank:]]*\([UCG]\+\)LIBC_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define \1LIBC_DYNAMIC_LINKER\2 "${libc.out}\3"|g' \
-e 's|define[[:blank:]]*MUSL_DYNAMIC_LINKER\([0-9]*\)[[:blank:]]"\([^\"]\+\)"$|define MUSL_DYNAMIC_LINKER\1 "${libc.out}\2"|g'
done
''
+ optionalString (targetPlatform.libc == "musl") ''
sed -i gcc/config/linux.h -e '1i#undef LOCAL_INCLUDE_DIR'
''
)
)
)
+ optionalString targetPlatform.isAvr ''
makeFlagsArray+=(
'-s' # workaround for hitting hydra log limit
'LIMITS_H_TEST=false'
)
'';
inherit
noSysDirs
staticCompiler
withoutTargetLibc
libcCross
crossMingw
;
inherit (callFile ./common/dependencies.nix { })
depsBuildBuild
nativeBuildInputs
depsBuildTarget
buildInputs
depsTargetTarget
;
preConfigure = (callFile ./common/pre-configure.nix { }) + ''
ln -sf ${libxcrypt}/include/crypt.h libsanitizer/sanitizer_common/crypt.h
'';
dontDisableStatic = true;
configurePlatforms = [
"build"
"host"
"target"
];
configureFlags = callFile ./common/configure-flags.nix { inherit targetPrefix; };
inherit targetConfig;
buildFlags =
# we do not yet have Nix-driven profiling
assert profiledCompiler -> !disableBootstrap;
let
target =
optionalString profiledCompiler "profiled"
+ optionalString (
(lib.systems.equals targetPlatform hostPlatform)
&& (lib.systems.equals hostPlatform buildPlatform)
&& !disableBootstrap
) "bootstrap";
in
optional (target != "") target;
inherit (callFile ./common/strip-attributes.nix { })
stripDebugList
stripDebugListTarget
preFixup
;
# https://gcc.gnu.org/PR109898
enableParallelInstalling = false;
env = mapAttrs (_: v: toString v) {
NIX_NO_SELF_RPATH = true;
# https://gcc.gnu.org/install/specific.html#x86-64-x-solaris210
${if hostPlatform.system == "x86_64-solaris" then "CC" else null} = "gcc -m64";
# Setting $CPATH and $LIBRARY_PATH to make sure both `gcc' and `xgcc' find the
# library headers and binaries, regardless of the language being compiled.
#
# The LTO code doesn't find zlib, so we just add it to $CPATH and
# $LIBRARY_PATH in this case.
#
# Cross-compiling, we need gcc not to read ./specs in order to build the g++
# compiler (after the specs for the cross-gcc are created). Having
# LIBRARY_PATH= makes gcc read the specs from ., and the build breaks.
CPATH = optionals (lib.systems.equals targetPlatform hostPlatform) (
makeSearchPathOutput "dev" "include" ([ ] ++ optional (zlib != null) zlib)
);
LIBRARY_PATH = optionals (lib.systems.equals targetPlatform hostPlatform) (
makeLibraryPath (optional (zlib != null) zlib)
);
NIX_LDFLAGS = optionalString hostPlatform.isSunOS "-lm";
inherit (callFile ./common/extra-target-flags.nix { })
EXTRA_FLAGS_FOR_TARGET
EXTRA_LDFLAGS_FOR_TARGET
;
};
passthru = {
inherit
langC
langCC
langObjC
langObjCpp
langAda
langFortran
langGo
version
;
isGNU = true;
hardeningUnsupportedFlags =
optional (
!(targetPlatform.isLinux && targetPlatform.isx86_64 && targetPlatform.libc == "glibc")
) "shadowstack"
++ optional (!(targetPlatform.isLinux && targetPlatform.isAarch64)) "pacret"
++ optionals langFortran [
"fortify"
"format"
];
};
enableParallelBuilding = true;
inherit enableShared enableMultilib;
meta = {
inherit (callFile ./common/meta.nix { inherit targetPrefix; })
homepage
license
description
longDescription
platforms
teams
mainProgram
identifiers
;
};
}
// optionalAttrs enableMultilib {
dontMoveLib64 = true;
}
))
[
(callPackage ./common/libgcc.nix {
inherit
version
langC
langCC
langJit
targetPlatform
hostPlatform
withoutTargetLibc
enableShared
libcCross
;
})
(callPackage ./common/checksum.nix { inherit langC langCC; })
]

View File

@@ -0,0 +1,315 @@
diff --git a/gcc/collect2.cc b/gcc/collect2.cc
index 268ac378b9c..8a5c606075a 100644
--- a/gcc/collect2.cc
+++ b/gcc/collect2.cc
@@ -327,7 +327,7 @@ static void write_aix_file (FILE *, struct id *);
static char *resolve_lib_name (const char *);
#endif
static char *extract_string (const char **);
-static void post_ld_pass (bool);
+static void post_ld_pass (bool, bool);
static void process_args (int *argcp, char **argv);
/* Enumerations describing which pass this is for scanning the
@@ -513,12 +513,10 @@ is_ctor_dtor (const char *s)
static struct path_prefix cpath, path;
-#ifdef CROSS_DIRECTORY_STRUCTURE
/* This is the name of the target machine. We use it to form the name
of the files to execute. */
static const char *const target_machine = TARGET_MACHINE;
-#endif
/* Search for NAME using prefix list PPREFIX. We only look for executable
files.
@@ -577,7 +575,7 @@ add_lto_object (struct lto_object_list *list, const char *name)
static void
maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
- const char **object, bool force)
+ const char **object, bool force, bool is_cross_compiler)
{
const char **object_file = CONST_CAST2 (const char **, char **, object_lst);
@@ -722,7 +720,7 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
"ld_args");
/* We assume that temp files were created, and therefore we need to take
that into account (maybe run dsymutil). */
- post_ld_pass (/*temp_file*/true);
+ post_ld_pass (/*temp_file*/true, is_cross_compiler);
free (lto_ld_argv);
maybe_unlink_list (lto_o_files);
@@ -734,10 +732,10 @@ maybe_run_lto_and_relink (char **lto_ld_argv, char **object_lst,
fork_execute ("ld", lto_ld_argv, HAVE_GNU_LD && at_file_supplied,
"ld_args");
/* No LTO objects were found, so no new temp file. */
- post_ld_pass (/*temp_file*/false);
+ post_ld_pass (/*temp_file*/false, is_cross_compiler);
}
else
- post_ld_pass (false); /* No LTO objects were found, no temp file. */
+ post_ld_pass (false, is_cross_compiler); /* No LTO objects were found, no temp file. */
}
/* Entry point for linker invoation. Called from main in collect2.cc.
LD_ARGV is an array of arguments for the linker. */
@@ -799,33 +797,14 @@ main (int argc, char **argv)
static const char *const gstrip_suffix = "gstrip";
const char *full_ld_suffixes[USE_LD_MAX];
-#ifdef CROSS_DIRECTORY_STRUCTURE
- /* If we look for a program in the compiler directories, we just use
- the short name, since these directories are already system-specific.
- But it we look for a program in the system directories, we need to
- qualify the program name with the target machine. */
-
- const char *const full_nm_suffix =
- concat (target_machine, "-", nm_suffix, NULL);
- const char *const full_gnm_suffix =
- concat (target_machine, "-", gnm_suffix, NULL);
-#ifdef LDD_SUFFIX
- const char *const full_ldd_suffix =
- concat (target_machine, "-", ldd_suffix, NULL);
-#endif
- const char *const full_strip_suffix =
- concat (target_machine, "-", strip_suffix, NULL);
- const char *const full_gstrip_suffix =
- concat (target_machine, "-", gstrip_suffix, NULL);
-#else
+ const char *full_nm_suffix;
+ const char *full_gnm_suffix;
+ const char *full_strip_suffix;
+ const char *full_gstrip_suffix;
+
#ifdef LDD_SUFFIX
- const char *const full_ldd_suffix = ldd_suffix;
+ const char *full_ldd_suffix;
#endif
- const char *const full_nm_suffix = nm_suffix;
- const char *const full_gnm_suffix = gnm_suffix;
- const char *const full_strip_suffix = strip_suffix;
- const char *const full_gstrip_suffix = gstrip_suffix;
-#endif /* CROSS_DIRECTORY_STRUCTURE */
const char *arg;
FILE *outf;
@@ -840,6 +819,7 @@ main (int argc, char **argv)
const char **ld1;
bool use_plugin = false;
bool use_collect_ld = false;
+ bool is_cross_compiler = false;
/* The kinds of symbols we will have to consider when scanning the
outcome of a first pass link. This is ALL to start with, then might
@@ -864,17 +844,6 @@ main (int argc, char **argv)
#endif
int i;
- for (i = 0; i < USE_LD_MAX; i++)
-#ifdef CROSS_DIRECTORY_STRUCTURE
- /* lld and mold are platform-agnostic and not prefixed with target
- triple. */
- if (!(i == USE_LLD_LD || i == USE_MOLD_LD))
- full_ld_suffixes[i] = concat (target_machine, "-", ld_suffixes[i],
- NULL);
- else
-#endif
- full_ld_suffixes[i] = ld_suffixes[i];
-
p = argv[0] + strlen (argv[0]);
while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
--p;
@@ -1050,6 +1019,65 @@ main (int argc, char **argv)
prefix_from_env ("COMPILER_PATH", &cpath);
prefix_from_env ("PATH", &path);
+ /* Determine the full path name of the C compiler to use. */
+ c_file_name = getenv ("COLLECT_GCC");
+ if (c_file_name == 0)
+ {
+ c_file_name = concat (target_machine, "-gcc", NULL);
+ p = find_a_file (&cpath, c_file_name, X_OK);
+ if (p == 0)
+ p = find_a_file (&path, c_file_name, X_OK);
+
+ if (p == 0) {
+ c_file_name = "gcc";
+ p = find_a_file (&cpath, c_file_name, X_OK);
+ if (p == 0)
+ p = find_a_file (&path, c_file_name, X_OK);
+ }
+ }
+ else
+ {
+ p = find_a_file (&cpath, c_file_name, X_OK);
+
+ /* Here it should be safe to use the system search path since we should have
+ already qualified the name of the compiler when it is needed. */
+ if (p == 0)
+ p = find_a_file (&path, c_file_name, X_OK);
+ }
+
+ if (p)
+ c_file_name = p;
+
+ if (c_file_name) {
+ is_cross_compiler = strncmp(basename(c_file_name), target_machine, strlen(target_machine)) == 0;
+ }
+
+ for (i = 0; i < USE_LD_MAX; i++)
+ /* lld and mold are platform-agnostic and not prefixed with target
+ triple. */
+ if (!(i == USE_LLD_LD || i == USE_MOLD_LD) && is_cross_compiler)
+ full_ld_suffixes[i] = concat (target_machine, "-", ld_suffixes[i],
+ NULL);
+ else
+ full_ld_suffixes[i] = ld_suffixes[i];
+
+ full_nm_suffix =
+ is_cross_compiler ? concat (target_machine, "-", nm_suffix, NULL) : nm_suffix;
+
+ full_gnm_suffix =
+ is_cross_compiler ? concat (target_machine, "-", gnm_suffix, NULL) : gnm_suffix;
+
+ full_strip_suffix =
+ is_cross_compiler ? concat (target_machine, "-", strip_suffix, NULL) : strip_suffix;
+
+ full_gstrip_suffix =
+ is_cross_compiler ? concat (target_machine, "-", gstrip_suffix, NULL) : gstrip_suffix;
+
+#ifdef LDD_SUFFIX
+ full_ldd_suffix =
+ is_cross_compiler ? concat (target_machine, "-", ldd_suffix, NULL) : ldd_suffix;
+#endif
+
/* Try to discover a valid linker/nm/strip to use. */
/* Maybe we know the right file to use (if not cross). */
@@ -1139,27 +1167,6 @@ main (int argc, char **argv)
if (strip_file_name == 0)
strip_file_name = find_a_file (&path, full_strip_suffix, X_OK);
- /* Determine the full path name of the C compiler to use. */
- c_file_name = getenv ("COLLECT_GCC");
- if (c_file_name == 0)
- {
-#ifdef CROSS_DIRECTORY_STRUCTURE
- c_file_name = concat (target_machine, "-gcc", NULL);
-#else
- c_file_name = "gcc";
-#endif
- }
-
- p = find_a_file (&cpath, c_file_name, X_OK);
-
- /* Here it should be safe to use the system search path since we should have
- already qualified the name of the compiler when it is needed. */
- if (p == 0)
- p = find_a_file (&path, c_file_name, X_OK);
-
- if (p)
- c_file_name = p;
-
*ld1++ = *ld2++ = ld_file_name;
/* Make temp file names. */
@@ -1595,6 +1602,8 @@ main (int argc, char **argv)
(c_file ? c_file : "not found"));
fprintf (stderr, "o_file = %s\n",
(o_file ? o_file : "not found"));
+ fprintf (stderr, "is_cross_compiler = %s\n",
+ (is_cross_compiler ? "yes" : "no"));
ptr = getenv ("COLLECT_GCC_OPTIONS");
if (ptr)
@@ -1644,9 +1653,9 @@ main (int argc, char **argv)
maybe_unlink (export_file);
#endif
if (lto_mode != LTO_MODE_NONE)
- maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
+ maybe_run_lto_and_relink (ld1_argv, object_lst, object, false, is_cross_compiler);
else
- post_ld_pass (/*temp_file*/false);
+ post_ld_pass (/*temp_file*/false, is_cross_compiler);
return 0;
}
@@ -1698,7 +1707,7 @@ main (int argc, char **argv)
do_link (ld1_argv, "ld1_args");
if (lto_mode)
- maybe_run_lto_and_relink (ld1_argv, object_lst, object, false);
+ maybe_run_lto_and_relink (ld1_argv, object_lst, object, false, is_cross_compiler);
/* Strip now if it was requested on the command line. */
if (strip_flag)
@@ -1716,7 +1725,7 @@ main (int argc, char **argv)
#ifdef COLLECT_EXPORT_LIST
maybe_unlink (export_file);
#endif
- post_ld_pass (/*temp_file*/false);
+ post_ld_pass (/*temp_file*/false, is_cross_compiler);
return 0;
}
@@ -1799,15 +1808,15 @@ main (int argc, char **argv)
do_link (ld2_argv, "ld2_args");
if (lto_mode)
- maybe_run_lto_and_relink (ld2_argv, object_lst, object, false);
+ maybe_run_lto_and_relink (ld2_argv, object_lst, object, false, is_cross_compiler);
#else
/* Otherwise, simply call ld because link is already done. */
if (lto_mode)
- maybe_run_lto_and_relink (ld2_argv, object_lst, object, true);
+ maybe_run_lto_and_relink (ld2_argv, object_lst, object, true, is_cross_compiler);
else
{
fork_execute ("ld", ld2_argv, HAVE_GNU_LD && at_file_supplied, "ld_args");
- post_ld_pass (/*temp_file*/false);
+ post_ld_pass (/*temp_file*/false, is_cross_compiler);
}
/* Let scan_prog_file do any final mods (OSF/rose needs this for
@@ -3020,7 +3029,7 @@ process_args (int *argcp, char **argv) {
}
static void
-do_dsymutil (const char *output_file) {
+do_dsymutil (const char *output_file, bool is_cross_compiler) {
const char *dsymutil = 0;
struct pex_obj *pex;
char **real_argv = XCNEWVEC (char *, verbose ? 4 : 3);
@@ -3032,11 +3041,7 @@ do_dsymutil (const char *output_file) {
here is consistent with the way other installations work (and one can
always symlink a multitarget dsymutil with a target-specific name). */
const char *dsname = "dsymutil";
-#ifdef CROSS_DIRECTORY_STRUCTURE
- const char *qname = concat (target_machine, "-", dsname, NULL);
-#else
- const char *qname = dsname;
-#endif
+ const char *qname = is_cross_compiler ? concat (target_machine, "-", dsname, NULL) : dsname;
#ifdef DEFAULT_DSYMUTIL
/* Configured default takes priority. */
if (dsymutil == 0 && access (DEFAULT_DSYMUTIL, X_OK) == 0)
@@ -3071,14 +3076,14 @@ do_dsymutil (const char *output_file) {
}
static void
-post_ld_pass (bool temp_file) {
+post_ld_pass (bool temp_file, bool is_cross_compiler) {
if (!(temp_file && flag_idsym) && !flag_dsym)
return;
- do_dsymutil (output_file);
+ do_dsymutil (output_file, is_cross_compiler);
}
#else
static void
process_args (int *argcp ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) { }
-static void post_ld_pass (bool temp_file ATTRIBUTE_UNUSED) { }
+static void post_ld_pass (bool temp_file ATTRIBUTE_UNUSED, bool is_cross_compiler ATTRIBUTE_UNUSED) { }
#endif

View File

@@ -0,0 +1,49 @@
From bb3277895d3bd77bcacb7c489ebb1390478bbc12 Mon Sep 17 00:00:00 2001
From: John Ericson <John.Ericson@Obsidian.Systems>
Date: Thu, 17 Jul 2025 11:00:07 -0400
Subject: [PATCH 2/2] Force regular dirs
Override directories in libgcc so they are normal $out/lib and
$dev/include. This is not suitable for upstreaming, but is done on top
of a different patch which is, and which makes this smaller.
---
libgcc/Makefile.in | 6 +++---
libgcc/configure.ac | 3 ---
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index 4661c36703d..986cd035148 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -202,10 +202,10 @@ STRIP = @STRIP@
STRIP_FOR_TARGET = $(STRIP)
# Used to install the shared libgcc.
-slibdir = @slibdir@
+slibdir = $(libdir)
# Maybe used for DLLs on Windows targets.
-toolexecdir = @toolexecdir@
-toolexeclibdir = @toolexeclibdir@
+toolexecdir = $(bindir)
+toolexeclibdir = $(libdir)
export AR_FOR_TARGET
export AR_CREATE_FOR_TARGET
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 5fdac5d95f2..89044cb65c9 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -479,9 +479,6 @@ if test x"$enable_as_accelerator_for" != x; then
accel_dir_suffix=/accel/${target_noncanonical}
real_host_noncanonical=${enable_as_accelerator_for}
fi
-# Directory in which the compiler finds libraries etc.
-libdir=${orig_libdir}/gcc/${real_host_noncanonical}/'$(version)'${accel_dir_suffix}
-includedir=${libdir}/include
if test x"$enable_offload_targets" != x; then
extra_parts="${extra_parts} crtoffloadbegin.o crtoffloadend.o"
--
2.47.2

View File

@@ -0,0 +1,53 @@
From 7a0c8ca8872a73c6886940448ba9b3203b13268d Mon Sep 17 00:00:00 2001
From: John Ericson <git@JohnEricson.me>
Date: Mon, 21 Jul 2025 11:42:13 -0400
Subject: [PATCH] libgfortran: Force regular include/lib dir
---
libgfortran/Makefile.am | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/libgfortran/Makefile.am b/libgfortran/Makefile.am
index 21b35c76a06..3d38cde5b42 100644
--- a/libgfortran/Makefile.am
+++ b/libgfortran/Makefile.am
@@ -42,14 +42,13 @@ extra_darwin_ldflags_libgfortran += -Wc,-nodefaultrpaths
extra_darwin_ldflags_libgfortran += -Wl,-rpath,@loader_path
endif
-gfor_c_HEADERS = ISO_Fortran_binding.h
-gfor_cdir = $(libdir)/gcc/$(target_alias)/$(gcc_version)/include
+include_HEADERS = ISO_Fortran_binding.h
LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/../libtool-ldflags $(LDFLAGS)) \
$(lt_host_flags)
-toolexeclib_LTLIBRARIES = libgfortran.la
-toolexeclib_DATA = libgfortran.spec
+lib_LTLIBRARIES = libgfortran.la
+toolexeclib_DATA = libgfortran.spec # needs "exec" in name
libgfortran_la_LINK = $(LINK) $(libgfortran_la_LDFLAGS)
libgfortran_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` \
$(LTLDFLAGS) $(LIBQUADLIB) ../libbacktrace/libbacktrace.la \
@@ -58,16 +57,14 @@ libgfortran_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version`
$(version_arg) -Wc,-shared-libgcc
libgfortran_la_DEPENDENCIES = $(version_dep) libgfortran.spec $(LIBQUADLIB_DEP)
-cafexeclib_LTLIBRARIES = libcaf_single.la
-cafexeclibdir = $(libdir)/gcc/$(target_alias)/$(gcc_version)$(MULTISUBDIR)
+lib_LTLIBRARIES += libcaf_single.la
libcaf_single_la_SOURCES = caf/single.c
libcaf_single_la_LDFLAGS = -static
libcaf_single_la_DEPENDENCIES = caf/libcaf.h
libcaf_single_la_LINK = $(LINK) $(libcaf_single_la_LDFLAGS)
if IEEE_SUPPORT
-fincludedir = $(libdir)/gcc/$(target_alias)/$(gcc_version)$(MULTISUBDIR)/finclude
-nodist_finclude_HEADERS = ieee_arithmetic.mod ieee_exceptions.mod ieee_features.mod
+nodist_include_HEADERS = ieee_arithmetic.mod ieee_exceptions.mod ieee_features.mod
endif
## io.h conflicts with a system header on some platforms, so
--
2.47.2

View File

@@ -0,0 +1,30 @@
From e7dac0e90f3e4363d858a6f147d7cc4f62815dd6 Mon Sep 17 00:00:00 2001
From: John Ericson <John.Ericson@Obsidian.Systems>
Date: Fri, 18 Jul 2025 16:54:17 -0400
Subject: [PATCH 3/3] Force regular dirs
Override directories in libssp so they are normal $out/lib and
$dev/include. This is not suitable for upstreaming, but is done on top
of a different patch which is, and which makes this smaller.
---
libssp/configure.ac | 4 ----
1 file changed, 4 deletions(-)
diff --git a/libssp/configure.ac b/libssp/configure.ac
index 5b9fa4fbecc..f1723dc33ce 100644
--- a/libssp/configure.ac
+++ b/libssp/configure.ac
@@ -207,10 +207,6 @@ esac
AC_SUBST(toolexecdir)
AC_SUBST(toolexeclibdir)
-# Directory in which the compiler finds libraries etc.
-libdir='$(toolexeclibdir)'
-includedir=${orig_libdir}/gcc/${host_noncanonical}/'$(version)/include'
-
if test ${multilib} = yes; then
multilib_arg="--enable-multilib"
else
--
2.47.2

View File

@@ -0,0 +1,120 @@
From db427c55334dd2edc11397d3a92d55dc9c06d1c3 Mon Sep 17 00:00:00 2001
From: John Ericson <git@JohnEricson.me>
Date: Sun, 20 Jul 2025 14:20:00 -0400
Subject: [PATCH] libstdc++: Force regular include/lib dir
Delete a bunch of unneeded logic to do this.
---
libstdc++-v3/acinclude.m4 | 80 ++------------------------------
libstdc++-v3/include/Makefile.am | 2 +-
2 files changed, 4 insertions(+), 78 deletions(-)
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index a0094c2dd95..a0718dff394 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -727,85 +727,11 @@ dnl
dnl This logic must match gcc/configure.ac's setting of gcc_gxx_include_dir.
dnl config/gxx-include-dir.m4 must be kept consistant with this as well.
AC_DEFUN([GLIBCXX_EXPORT_INSTALL_INFO], [
- glibcxx_toolexecdir=no
- glibcxx_toolexeclibdir=no
+ glibcxx_toolexecdir='$(libdir)'
+ glibcxx_toolexeclibdir='$(libdir)'
+ gxx_include_dir='$(includedir)'
glibcxx_prefixdir=$prefix
- AC_MSG_CHECKING([for gxx-include-dir])
- AC_ARG_WITH([gxx-include-dir],
- AC_HELP_STRING([--with-gxx-include-dir=DIR],
- [installation directory for include files]),
- [case "$withval" in
- yes) AC_MSG_ERROR([Missing directory for --with-gxx-include-dir]) ;;
- no) gxx_include_dir=no ;;
- *) gxx_include_dir=$withval ;;
- esac],
- [gxx_include_dir=no])
- AC_MSG_RESULT($gxx_include_dir)
-
- AC_MSG_CHECKING([for --enable-version-specific-runtime-libs])
- AC_ARG_ENABLE([version-specific-runtime-libs],
- AC_HELP_STRING([--enable-version-specific-runtime-libs],
- [Specify that runtime libraries should be installed in a compiler-specific directory]),
- [case "$enableval" in
- yes) version_specific_libs=yes ;;
- no) version_specific_libs=no ;;
- *) AC_MSG_ERROR([Unknown argument to enable/disable version-specific libs]);;
- esac],
- [version_specific_libs=no])
- AC_MSG_RESULT($version_specific_libs)
-
- GCC_WITH_TOOLEXECLIBDIR
-
- # Default case for install directory for include files.
- if test $version_specific_libs = no && test $gxx_include_dir = no; then
- gxx_include_dir='include/c++/${gcc_version}'
- if test -n "$with_cross_host" &&
- test x"$with_cross_host" != x"no"; then
- gxx_include_dir='${prefix}/${target_alias}/'"$gxx_include_dir"
- else
- gxx_include_dir='${prefix}/'"$gxx_include_dir"
- fi
- fi
-
- # Version-specific runtime libs processing.
- if test $version_specific_libs = yes; then
- # Need the gcc compiler version to know where to install libraries
- # and header files if --enable-version-specific-runtime-libs option
- # is selected. FIXME: these variables are misnamed, there are
- # no executables installed in _toolexecdir or _toolexeclibdir.
- if test x"$gxx_include_dir" = x"no"; then
- gxx_include_dir='${libdir}/gcc/${host_alias}/${gcc_version}/include/c++'
- fi
- glibcxx_toolexecdir='${libdir}/gcc/${host_alias}'
- glibcxx_toolexeclibdir='${toolexecdir}/${gcc_version}$(MULTISUBDIR)'
- fi
-
- # Calculate glibcxx_toolexecdir, glibcxx_toolexeclibdir
- # Install a library built with a cross compiler in tooldir, not libdir.
- if test x"$glibcxx_toolexecdir" = x"no"; then
- if test -n "$with_cross_host" &&
- test x"$with_cross_host" != x"no"; then
- glibcxx_toolexecdir='${exec_prefix}/${host_alias}'
- case ${with_toolexeclibdir} in
- no)
- glibcxx_toolexeclibdir='${toolexecdir}/lib'
- ;;
- *)
- glibcxx_toolexeclibdir=${with_toolexeclibdir}
- ;;
- esac
- else
- glibcxx_toolexecdir='${libdir}/gcc/${host_alias}'
- glibcxx_toolexeclibdir='${libdir}'
- fi
- multi_os_directory=`$CXX -print-multi-os-directory`
- case $multi_os_directory in
- .) ;; # Avoid trailing /.
- *) glibcxx_toolexeclibdir=$glibcxx_toolexeclibdir/$multi_os_directory ;;
- esac
- fi
-
AC_MSG_CHECKING([for install location])
AC_MSG_RESULT($gxx_include_dir)
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 537774c2668..c0bfeb43b44 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -1048,7 +1048,7 @@ endif
host_srcdir = ${glibcxx_srcdir}/$(OS_INC_SRCDIR)
host_builddir = ./${host_alias}/bits
-host_installdir = ${gxx_include_dir}/${host_alias}$(MULTISUBDIR)/bits
+host_installdir = ${gxx_include_dir}/bits
host_headers = \
${host_srcdir}/ctype_base.h \
${host_srcdir}/ctype_inline.h \
--
2.47.2

View File

@@ -0,0 +1,3 @@
# GCC Next-Generation
Experimental split GCC package set based on the LLVM package set design.

View File

@@ -0,0 +1,47 @@
{
lib,
fetchurl ? null,
fetchgit ? null,
release_version ? null,
gitRelease ? null,
officialRelease ? null,
monorepoSrc' ? null,
version ? null,
}@args:
rec {
gcc_meta = {
license = with lib.licenses; [ gpl3Plus ];
teams = [ lib.teams.gcc ];
};
releaseInfo =
if gitRelease != null then
rec {
original = gitRelease;
release_version = args.version or original.version;
version = gitRelease.rev-version;
}
else
rec {
original = officialRelease;
release_version = args.version or original.version;
version =
if original ? candidate then "${release_version}-${original.candidate}" else release_version;
};
monorepoSrc =
if monorepoSrc' != null then
monorepoSrc'
else if gitRelease != null then
fetchgit {
url = "https://gcc.gnu.org/git/gcc.git";
inherit (gitRelease) rev;
hash = releaseInfo.original.sha256;
}
else
fetchurl {
url = "mirror://gcc/releases/gcc-${releaseInfo.version}/gcc-${releaseInfo.version}.tar.xz";
hash = releaseInfo.original.sha256;
};
}

View File

@@ -0,0 +1,235 @@
{
lib,
newScope,
stdenv,
overrideCC,
fetchgit,
fetchurl,
gitRelease ? null,
officialRelease ? null,
monorepoSrc ? null,
version ? null,
patchesFn ? lib.id,
wrapCCWith,
binutilsNoLibc,
binutils,
buildGccPackages,
targetGccPackages,
makeScopeWithSplicing',
otherSplices,
...
}@args:
assert lib.assertMsg (lib.xor (gitRelease != null) (officialRelease != null)) (
"must specify `gitRelease` or `officialRelease`"
+ (lib.optionalString (gitRelease != null) " not both")
);
let
monorepoSrc' = monorepoSrc;
metadata = rec {
inherit
(import ./common-let.nix {
inherit (args)
lib
gitRelease
officialRelease
version
;
})
releaseInfo
;
inherit (releaseInfo) release_version version;
inherit
(import ./common-let.nix {
inherit
lib
fetchgit
fetchurl
release_version
gitRelease
officialRelease
monorepoSrc'
version
;
})
gcc_meta
monorepoSrc
;
src = monorepoSrc;
versionDir =
(toString ../.) + "/${if (gitRelease != null) then "git" else lib.versions.major release_version}";
getVersionFile =
p:
builtins.path {
name = baseNameOf p;
path =
let
patches = args.patchesFn (import ./patches.nix);
constraints = patches."${p}" or null;
matchConstraint =
{
before ? null,
after ? null,
path,
}:
let
check = fn: value: if value == null then true else fn release_version value;
matchBefore = check lib.versionOlder before;
matchAfter = check lib.versionAtLeast after;
in
matchBefore && matchAfter;
patchDir =
toString
(
if constraints == null then
{ path = metadata.versionDir; }
else
(lib.findFirst matchConstraint { path = metadata.versionDir; } constraints)
).path;
in
"${patchDir}/${p}";
};
};
in
makeScopeWithSplicing' {
inherit otherSplices;
f =
gccPackages:
let
callPackage = gccPackages.newScope (args // metadata);
in
{
stdenv = overrideCC stdenv gccPackages.gcc;
gcc-unwrapped = callPackage ./gcc {
bintools = binutils;
};
libbacktrace = callPackage ./libbacktrace { };
libiberty = callPackage ./libiberty { };
libsanitizer = callPackage ./libsanitizer { };
libquadmath = callPackage ./libquadmath { };
gfortran-unwrapped = gccPackages.gcc-unwrapped.override {
stdenv = overrideCC stdenv buildGccPackages.gcc;
langFortran = true;
};
gfortran = wrapCCWith {
cc = gccPackages.gfortran-unwrapped;
libcxx = targetGccPackages.libstdcxx;
bintools = binutils;
extraPackages = [
targetGccPackages.libgcc
];
nixSupport.cc-cflags = [
"-B${targetGccPackages.libgcc}/lib"
"-B${targetGccPackages.libssp}/lib"
"-B${targetGccPackages.libatomic}/lib"
"-B${targetGccPackages.libgfortran}/lib/"
];
};
gfortranNoLibgfortran = wrapCCWith {
cc = gccPackages.gfortran-unwrapped;
libcxx = targetGccPackages.libstdcxx;
bintools = binutils;
extraPackages = [
targetGccPackages.libgcc
];
nixSupport.cc-cflags = [
"-B${targetGccPackages.libgcc}/lib"
"-B${targetGccPackages.libssp}/lib"
"-B${targetGccPackages.libatomic}/lib"
];
};
gcc = wrapCCWith {
cc = gccPackages.gcc-unwrapped;
libcxx = targetGccPackages.libstdcxx;
bintools = binutils;
extraPackages = [
targetGccPackages.libgcc
];
nixSupport.cc-cflags = [
"-B${targetGccPackages.libgcc}/lib"
"-B${targetGccPackages.libssp}/lib"
"-B${targetGccPackages.libatomic}/lib"
];
};
gccNoLibgcc = wrapCCWith {
cc = gccPackages.gcc-unwrapped;
libcxx = null;
bintools = binutilsNoLibc;
extraPackages = [ ];
nixSupport.cc-cflags = [
"-nostartfiles"
];
};
libgcc = callPackage ./libgcc {
stdenv = overrideCC stdenv buildGccPackages.gccNoLibgcc;
};
gccWithLibc = wrapCCWith {
cc = gccPackages.gcc-unwrapped;
libcxx = null;
bintools = binutils;
extraPackages = [
targetGccPackages.libgcc
];
nixSupport.cc-cflags = [
"-B${targetGccPackages.libgcc}/lib"
];
};
libssp = callPackage ./libssp {
stdenv = overrideCC stdenv buildGccPackages.gccWithLibc;
};
gccWithLibssp = wrapCCWith {
cc = gccPackages.gcc-unwrapped;
libcxx = null;
bintools = binutils;
extraPackages = [
targetGccPackages.libgcc
];
nixSupport.cc-cflags = [
"-B${targetGccPackages.libgcc}/lib"
"-B${targetGccPackages.libssp}/lib"
];
};
libatomic = callPackage ./libatomic {
stdenv = overrideCC stdenv buildGccPackages.gccWithLibssp;
};
gccWithLibatomic = wrapCCWith {
cc = gccPackages.gcc-unwrapped;
libcxx = null;
bintools = binutils;
extraPackages = [
targetGccPackages.libgcc
];
nixSupport.cc-cflags = [
"-B${targetGccPackages.libgcc}/lib"
"-B${targetGccPackages.libssp}/lib"
"-B${targetGccPackages.libatomic}/lib"
];
};
libgfortran = callPackage ./libgfortran {
stdenv = overrideCC stdenv buildGccPackages.gcc;
gfortran = buildGccPackages.gfortranNoLibgfortran;
};
libstdcxx = callPackage ./libstdcxx {
stdenv = overrideCC stdenv buildGccPackages.gccWithLibatomic;
};
};
}

View File

@@ -0,0 +1,256 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
fetchpatch,
langAda ? false,
langC ? true,
langCC ? true,
langFortran ? false,
langGo ? false,
langJava ? false,
langObjC ? stdenv.targetPlatform.isDarwin,
langObjCpp ? stdenv.targetPlatform.isDarwin,
langJit ? false,
enablePlugin ? lib.systems.equals stdenv.hostPlatform stdenv.buildPlatform,
runCommand,
buildPackages,
isl,
zlib,
gmp,
libmpc,
mpfr,
perl,
texinfo,
which,
gettext,
getVersionFile,
buildGccPackages,
targetPackages,
libc,
bintools,
}:
let
inherit (stdenv) targetPlatform hostPlatform;
targetPrefix = lib.optionalString (targetPlatform != hostPlatform) "${targetPlatform.config}-";
in
stdenv.mkDerivation (finalAttrs: {
pname = "${targetPrefix}${if langFortran then "gfortran" else "gcc"}";
inherit version;
src = monorepoSrc;
outputs = [
"out"
"man"
"info"
];
patches = [
(fetchpatch {
name = "for_each_path-functional-programming.patch";
url = "https://github.com/gcc-mirror/gcc/commit/f23bac62f46fc296a4d0526ef54824d406c3756c.diff";
hash = "sha256-J7SrypmVSbvYUzxWWvK2EwEbRsfGGLg4vNZuLEe6Xe0=";
})
(fetchpatch {
name = "find_a_program-separate-from-find_a_file.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250822234120.1988059-1-git@JohnEricson.me/raw";
hash = "sha256-0gaWaeFZq+a8q7Bcr3eILNjHh1LfzL/Lz4F+W+H6XIU=";
})
(fetchpatch {
name = "simplify-find_a_program-and-find_a_file.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250822234120.1988059-2-git@JohnEricson.me/raw";
hash = "sha256-ojdyszxLGL+njHK4eAaeBkxAhFTDI57j6lGuAf0A+N0=";
})
(fetchpatch {
name = "for_each_path-pass-machine-specific.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250822234120.1988059-3-git@JohnEricson.me/raw";
hash = "sha256-C5jUSyNchmZcE8RTXc2dHfCqNKuBHeiouLruK9UooSM=";
})
(fetchpatch {
name = "find_a_program-search-with-machine-prefix.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250822234120.1988059-4-git@JohnEricson.me/raw";
hash = "sha256-MwcO4OXPlcdaSYivsh5ru+Cfq6qybeAtgCgTEPGYg40=";
})
(getVersionFile "gcc/fix-collect2-paths.diff")
];
enableParallelBuilding = true;
hardeningDisable = [
"format" # Some macro-indirect formatting in e.g. libcpp
];
strictDeps = true;
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
texinfo
which
gettext
]
++ lib.optional (perl != null) perl;
buildInputs = [
gmp
libmpc
mpfr
]
++ lib.optional (isl != null) isl
++ lib.optional (zlib != null) zlib;
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
postPatch = ''
configureScripts=$(find . -name configure)
for configureScript in $configureScripts; do
patchShebangs $configureScript
done
patchShebangs libbacktrace/install-debuginfo-for-buildid.sh
patchShebangs runtest
''
# This should kill all the stdinc frameworks that gcc and friends like to
# insert into default search paths.
+ lib.optionalString hostPlatform.isDarwin ''
substituteInPlace gcc/config/darwin-c.c \
--replace 'if (stdinc)' 'if (0)'
'';
preConfigure =
# Don't built target libraries, because we want to build separately
''
substituteInPlace configure \
--replace 'noconfigdirs=""' 'noconfigdirs="$noconfigdirs $target_libraries"'
''
# 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 && targetPlatform != hostPlatform)
''
substituteInPlace configure --replace is_cross_compiler=no is_cross_compiler=yes
''
# Cannot configure from src dir
+ ''
cd "$buildRoot"
mkdir -p "$buildRoot/libbacktrace/.libs"
cp ${buildGccPackages.libbacktrace}/lib/libbacktrace.a "$buildRoot/libbacktrace/.libs/libbacktrace.a"
cp -r ${buildGccPackages.libbacktrace}/lib/*.la "$buildRoot/libbacktrace"
cp -r ${buildGccPackages.libbacktrace.dev}/include/*.h "$buildRoot/libbacktrace"
mkdir -p "$buildRoot/libiberty/pic"
cp ${buildGccPackages.libiberty}/lib/libiberty.a "$buildRoot/libiberty"
cp ${buildGccPackages.libiberty}/lib/libiberty_pic.a "$buildRoot/libiberty/pic/libiberty.a"
touch "$buildRoot/libiberty/stamp-noasandir"
touch "$buildRoot/libiberty/stamp-h"
touch "$buildRoot/libiberty/stamp-picdir"
mkdir -p "$buildRoot/build-${stdenv.hostPlatform.config}"
cp -r "$buildRoot/libiberty" "$buildRoot/build-${stdenv.hostPlatform.config}/libiberty"
configureScript=../$sourceRoot/configure
'';
# Don't store the configure flags in the resulting executables.
postConfigure = ''
sed -e '/TOPLEVEL_CONFIGURE_ARGUMENTS=/d' -i Makefile
'';
dontDisableStatic = true;
configurePlatforms = [
"build"
"host"
"target"
];
configureFlags = [
# 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}"
"--disable-dependency-tracking"
"--enable-fast-install"
"--disable-serial-configure"
"--disable-bootstrap"
"--disable-decimal-float"
"--disable-install-libiberty"
"--disable-multilib"
"--disable-nls"
"--disable-shared"
"--enable-default-pie"
"--enable-languages=${
lib.concatStrings (
lib.intersperse "," (
lib.optional langC "c"
++ lib.optional langCC "c++"
++ lib.optional langFortran "fortran"
++ lib.optional langJava "java"
++ lib.optional langAda "ada"
++ lib.optional langGo "go"
++ lib.optional langObjC "objc"
++ lib.optional langObjCpp "obj-c++"
++ lib.optional langJit "jit"
)
)
}"
(lib.withFeature (isl != null) "isl")
"--without-headers"
"--with-gnu-as"
"--with-gnu-ld"
"--with-as=${lib.getExe' bintools "${bintools.targetPrefix}as"}"
"--with-system-zlib"
"--without-included-gettext"
"--enable-linker-build-id"
"--with-sysroot=${lib.getDev (targetPackages.libc or libc)}"
"--with-native-system-header-dir=/include"
]
++ lib.optionals enablePlugin [
"--enable-plugin"
"--enable-plugins"
]
++
# Only pass when the arch supports it.
# Exclude RISC-V because GCC likes to fail when the string is empty on RISC-V.
lib.optionals (targetPlatform.isAarch || targetPlatform.isAvr || targetPlatform.isx86_64) [
"--with-multilib-list="
];
doCheck = false;
postInstall = ''
moveToOutput "lib/gcc/${targetPlatform.config}/${version}/plugin/include" "''${!outputDev}"
'';
passthru = {
inherit
langC
langCC
langObjC
langObjCpp
langAda
langFortran
langGo
;
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,94 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
fetchpatch,
autoreconfHook269,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libatomic";
inherit version;
src = runCommand "libatomic-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
cp -r libatomic "$out"
cp -r config "$out"
cp -r multilib.am "$out"
cp -r libtool.m4 "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp mkinstalldirs "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
patches = [
(fetchpatch {
name = "custom-threading-model.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250716204545.1063669-1-git@JohnEricson.me/raw";
hash = "sha256-kxNntY2r4i/+XHQSpf9bYV2Jg+FD/pD5TiMn5hd4ckk=";
includes = [
"config/*"
"libatomic/*"
];
})
];
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
preAutoreconf = ''
sourceRoot=$(readlink -e "./libatomic")
cd $sourceRoot
'';
enableParallelBuilding = true;
nativeBuildInputs = [
autoreconfHook269
];
configurePlatforms = [
"build"
"host"
];
configureFlags = [
"--disable-dependency-tracking"
"cross_compiling=true"
"--disable-multilib"
];
preConfigure = ''
cd "$buildRoot"
configureScript=$sourceRoot/configure
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,74 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libbacktrace";
inherit version;
src = runCommand "libbacktrace-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
cp -r include "$out"
cp -r libbacktrace "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp move-if-change "$out"
cp mkinstalldirs "$out"
cp test-driver "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
outputs = [
"out"
"dev"
];
enableParallelBuilding = true;
sourceRoot = "${finalAttrs.src.name}/libbacktrace";
preConfigure = ''
mkdir ../../build
cd ../../build
configureScript=../$sourceRoot/configure
'';
installPhase = ''
runHook preInstall
mkdir -p "$out/lib"
cp .libs/*.a "$out/lib"
cp libbacktrace*.la "$out/lib"
mkdir -p "$dev/include"
cp backtrace-supported.h "$dev/include"
runHook postInstall
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,224 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
fetchpatch,
autoreconfHook269,
buildGccPackages,
buildPackages,
which,
python3,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libgcc";
inherit version;
src = monorepoSrc;
outputs = [
"out"
"dev"
];
strictDeps = true;
depsBuildBuild = [
buildPackages.stdenv.cc
buildGccPackages.libiberty
];
nativeBuildInputs = [
autoreconfHook269
which
python3
];
patches = [
(fetchpatch {
name = "delete-MACHMODE_H.patch";
url = "https://github.com/gcc-mirror/gcc/commit/493aae4b034d62054d5e7e54dc06cd9a8be54e29.diff";
hash = "sha256-oEk0lnI96RlpALWpb7J+GnrtgQsFVqDO57I/zjiqqTk=";
})
(fetchpatch {
name = "custom-threading-model.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250716204545.1063669-1-git@JohnEricson.me/raw";
hash = "sha256-NgiC4cFeFInXXg27me1XpSeImPaL0WHs50Tf1YHz4ps=";
})
(fetchpatch {
name = "libgcc.mvars-less-0.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250716234028.1153560-1-John.Ericson@Obsidian.Systems/raw";
hash = "sha256-NEcieDCsy+7IRU3qQKVD3i57OuwGZKB/rmNF8X2I1n0=";
})
(fetchpatch {
name = "libgcc.mvars-less-1.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250716234028.1153560-2-John.Ericson@Obsidian.Systems/raw";
hash = "sha256-nfRC4f6m3kHDro4+6E4y1ZPs+prxBQmn0H2rzIjaMWM=";
})
(fetchpatch {
name = "regular-libdir-includedir.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250717174911.1536129-1-git@JohnEricson.me/raw";
hash = "sha256-Cn7rvg1FI7H/26GzSe4pv5VW/gvwbwGqivAqEeawkwk=";
})
(getVersionFile "libgcc/force-regular-dirs.patch")
];
autoreconfFlags = "--install --force --verbose . libgcc";
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
postPatch = ''
sourceRoot=$(readlink -e "./libgcc")
'';
enableParallelBuilding = true;
preConfigure = ''
cd "$buildRoot"
mkdir -p build-${stdenv.buildPlatform.config}/libiberty/
cd build-${stdenv.buildPlatform.config}/libiberty/
ln -s ${buildGccPackages.libiberty}/lib/libiberty.a ./
mkdir -p "$buildRoot/gcc"
cd "$buildRoot/gcc"
(
export AS_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $AS_FOR_BUILD)"}
export CC_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $CC_FOR_BUILD)"}
export CPP_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $CPP_FOR_BUILD)"}
export CXX_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $CXX_FOR_BUILD)"}
export LD_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc.bintools "$(basename $LD_FOR_BUILD)"}
export AS=$AS_FOR_BUILD
export CC=$CC_FOR_BUILD
export CPP=$CPP_FOR_BUILD
export CXX=$CXX_FOR_BUILD
export LD=$LD_FOR_BUILD
export AS_FOR_TARGET=${lib.getExe' stdenv.cc "$(basename $AS)"}
export CC_FOR_TARGET=${lib.getExe' stdenv.cc "$(basename $CC)"}
export CPP_FOR_TARGET=${lib.getExe' stdenv.cc "$(basename $CPP)"}
export LD_FOR_TARGET=${lib.getExe' stdenv.cc.bintools "$(basename $LD)"}
export NIX_CFLAGS_COMPILE_FOR_BUILD+=' -DGENERATOR_FILE=1'
"$sourceRoot/../gcc/configure" $topLevelConfigureFlags
sed -e 's,libgcc.mvars:.*$,libgcc.mvars:,' -i Makefile
make \
config.h \
libgcc.mvars \
tconfig.h \
tm.h \
options.h \
insn-constants.h \
version.h
)
mkdir -p "$buildRoot/gcc/include"
mkdir -p "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgcc"
cd "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgcc"
configureScript=$sourceRoot/configure
chmod +x "$configureScript"
export AS_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $AS_FOR_BUILD)"}
export CC_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $CC_FOR_BUILD)"}
export CPP_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $CPP_FOR_BUILD)"}
export CXX_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$(basename $CXX_FOR_BUILD)"}
export LD_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc.bintools "$(basename $LD_FOR_BUILD)"}
export AS=${lib.getExe' stdenv.cc "$(basename $AS)"}
export CC=${lib.getExe' stdenv.cc "$(basename $CC)"}
export CPP=${lib.getExe' stdenv.cc "$(basename $CPP)"}
export CXX=${lib.getExe' stdenv.cc "$(basename $CXX)"}
export LD=${lib.getExe' stdenv.cc.bintools "$(basename $LD)"}
export AS_FOR_TARGET=${lib.getExe' stdenv.cc "$(basename $AS_FOR_TARGET)"}
export CC_FOR_TARGET=${lib.getExe' stdenv.cc "$(basename $CC_FOR_TARGET)"}
export CPP_FOR_TARGET=${lib.getExe' stdenv.cc "$(basename $CPP_FOR_TARGET)"}
export LD_FOR_TARGET=${lib.getExe' stdenv.cc.bintools "$(basename $LD_FOR_TARGET)"}
''
+ lib.optionalString stdenv.hostPlatform.isMusl ''
NIX_CFLAGS_COMPILE_OLD=$NIX_CFLAGS_COMPILE
NIX_CFLAGS_COMPILE+=' -isystem ${stdenv.cc.cc}/lib/gcc/${stdenv.hostPlatform.config}/${version}/include-fixed'
'';
topLevelConfigureFlags = [
"--build=${stdenv.buildPlatform.config}"
"--host=${stdenv.buildPlatform.config}"
"--target=${stdenv.hostPlatform.config}"
"--disable-bootstrap"
"--disable-multilib"
"--enable-languages=c"
"--disable-fixincludes"
"--disable-intl"
"--disable-lto"
"--disable-libatomic"
"--disable-libbacktrace"
"--disable-libcpp"
"--disable-libssp"
"--disable-libquadmath"
"--disable-libgomp"
"--disable-libvtv"
"--disable-vtable-verify"
"--with-system-zlib"
]
++
lib.optional (!stdenv.hostPlatform.isRiscV)
# RISC-V does not like it being empty
"--with-multilib-list="
++
lib.optional (stdenv.hostPlatform.libc == "glibc")
# Cheat and use previous stage's glibc to avoid infinite recursion. As
# of GCC 11, libgcc only cares if the version is greater than 2.19,
# which is quite ancient, so this little lie should be fine.
"--with-glibc-version=${buildPackages.glibc.version}";
configurePlatforms = [
"build"
"host"
];
configureFlags = [
"--disable-dependency-tracking"
"gcc_cv_target_thread_file=single"
# $CC cannot link binaries, let alone run then
"cross_compiling=true"
# Do not have dynamic linker without libc
"--enable-static"
"--disable-shared"
];
# Set the variable back the way it was, see corresponding code in
# `preConfigure`.
postConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
NIX_CFLAGS_COMPILE=$NIX_CFLAGS_COMPILE_OLD
'';
makeFlags = [ "MULTIBUILDTOP:=../" ];
postInstall = ''
install -c -m 644 gthr-default.h "$dev/include"
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,188 @@
{
lib,
stdenv,
gfortran,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
autoreconfHook269,
libiberty,
buildPackages,
libgcc,
libbacktrace,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libgfortran";
inherit version;
src = monorepoSrc;
outputs = [
"out"
"dev"
];
strictDeps = true;
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
autoreconfHook269
libiberty
gfortran
];
patches = [
(getVersionFile "libgfortran/force-regular-dirs.patch")
];
autoreconfFlags = "--install --force --verbose . libgfortran";
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
postPatch = ''
sourceRoot=$(readlink -e "./libgfortran")
'';
enableParallelBuilding = true;
preConfigure = ''
cd "$buildRoot"
mkdir -p build-${stdenv.buildPlatform.config}/libiberty/
cd build-${stdenv.buildPlatform.config}/libiberty/
ln -s ${libiberty}/lib/libiberty.a ./
mkdir -p "$buildRoot/gcc"
cd "$buildRoot/gcc"
(
export AS_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$AS_FOR_BUILD"}
export CC_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$CC_FOR_BUILD"}
export CPP_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$CPP_FOR_BUILD"}
export CXX_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$CXX_FOR_BUILD"}
export LD_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc.bintools "$LD_FOR_BUILD"}
export AS=$AS_FOR_BUILD
export CC=$CC_FOR_BUILD
export CPP=$CPP_FOR_BUILD
export CXX=$CXX_FOR_BUILD
export LD=$LD_FOR_BUILD
export AS_FOR_TARGET=${lib.getExe' stdenv.cc "$AS"}
export CC_FOR_TARGET=${lib.getExe' stdenv.cc "$CC"}
export CPP_FOR_TARGET=${lib.getExe' stdenv.cc "$CPP"}
export LD_FOR_TARGET=${lib.getExe' stdenv.cc.bintools "$LD"}
export NIX_CFLAGS_COMPILE_FOR_BUILD+=' -DGENERATOR_FILE=1'
"$sourceRoot/../gcc/configure" $topLevelConfigureFlags
make \
config.h
)
mkdir -p "$buildRoot/gcc/include"
mkdir -p "$buildRoot/gcc/libbacktrace/.libs"
cp ${libbacktrace}/lib/libbacktrace.a "$buildRoot/gcc/libbacktrace/.libs/libbacktrace.a"
cp -r ${libbacktrace}/lib/*.la "$buildRoot/gcc/libbacktrace"
cp -r ${libbacktrace.dev}/include/*.h "$buildRoot/gcc/libbacktrace"
mkdir -p "$buildRoot/gcc/libgcc"
ln -s "${libgcc.dev}/include/gthr-default.h" "$buildRoot/gcc/libgcc"
mkdir -p "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgfortran"
ln -s "$buildRoot/gcc/libbacktrace" "$buildRoot/gcc/${stdenv.buildPlatform.config}/libbacktrace"
ln -s "$buildRoot/gcc/libgcc" "$buildRoot/gcc/${stdenv.buildPlatform.config}/libgcc"
cd "$buildRoot/gcc/${stdenv.hostPlatform.config}/libgfortran"
configureScript=$sourceRoot/configure
chmod +x "$configureScript"
export AS_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$AS_FOR_BUILD"}
export CC_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$CC_FOR_BUILD"}
export CPP_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$CPP_FOR_BUILD"}
export CXX_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc "$CXX_FOR_BUILD"}
export LD_FOR_BUILD=${lib.getExe' buildPackages.stdenv.cc.bintools "$LD_FOR_BUILD"}
export AS=${lib.getExe' stdenv.cc "$AS"}
export CC=${lib.getExe' stdenv.cc "$CC"}
export CPP=${lib.getExe' stdenv.cc "$CPP"}
export CXX=${lib.getExe' stdenv.cc "$CXX"}
export LD=${lib.getExe' stdenv.cc.bintools "$LD"}
export AS_FOR_TARGET=${lib.getExe' stdenv.cc "$AS_FOR_TARGET"}
export CC_FOR_TARGET=${lib.getExe' stdenv.cc "$CC_FOR_TARGET"}
export CPP_FOR_TARGET=${lib.getExe' stdenv.cc "$CPP_FOR_TARGET"}
export LD_FOR_TARGET=${lib.getExe' stdenv.cc.bintools "$LD_FOR_TARGET"}
''
+ lib.optionalString stdenv.hostPlatform.isMusl ''
NIX_CFLAGS_COMPILE_OLD=$NIX_CFLAGS_COMPILE
NIX_CFLAGS_COMPILE+=' -isystem ${stdenv.cc.cc}/lib/gcc/${stdenv.hostPlatform.config}/${version}/include-fixed'
'';
topLevelConfigureFlags = [
"--build=${stdenv.buildPlatform.config}"
"--host=${stdenv.buildPlatform.config}"
"--target=${stdenv.hostPlatform.config}"
"--disable-bootstrap"
"--disable-multilib"
"--with-multilib-list="
"--enable-languages=fortran"
"--disable-fixincludes"
"--disable-intl"
"--disable-lto"
"--disable-libatomic"
"--disable-libbacktrace"
"--disable-libcpp"
"--disable-libssp"
"--disable-libquadmath"
"--disable-libgomp"
"--disable-libvtv"
"--disable-vtable-verify"
"--with-system-zlib"
]
++
lib.optional (stdenv.hostPlatform.libc == "glibc")
# Cheat and use previous stage's glibc to avoid infinite recursion. As
# of GCC 11, libgcc only cares if the version is greater than 2.19,
# which is quite ancient, so this little lie should be fine.
"--with-glibc-version=${buildPackages.glibc.version}";
configurePlatforms = [
"build"
"host"
];
configureFlags = [
"--disable-dependency-tracking"
"gcc_cv_target_thread_file=single"
# $CC cannot link binaries, let alone run then
"cross_compiling=true"
"--with-toolexeclibdir=${placeholder "dev"}/lib"
];
# Set the variable back the way it was, see corresponding code in
# `preConfigure`.
postConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
NIX_CFLAGS_COMPILE=$NIX_CFLAGS_COMPILE_OLD
'';
makeFlags = [ "MULTIBUILDTOP:=../" ];
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,68 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libiberty";
inherit version;
src = runCommand "libiberty-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
cp -r include "$out"
cp -r libiberty "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp mkinstalldirs "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
outputs = [
"out"
"dev"
];
enableParallelBuilding = true;
sourceRoot = "${finalAttrs.src.name}/libiberty";
preConfigure = ''
mkdir ../../build
cd ../../build
configureScript=../$sourceRoot/configure
'';
configureFlags = [
"--enable-install-libiberty"
]
++ lib.optional (!stdenv.hostPlatform.isStatic) "--enable-shared";
postInstall = ''
cp pic/libiberty.a $out/lib/libiberty_pic.a
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,51 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libquadmath";
inherit version;
src = runCommand "libquadmath-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
cp -r libquadmath "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp mkinstalldirs "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
sourceRoot = "${finalAttrs.src.name}/libquadmath";
preConfigure = ''
mkdir ../../build
cd ../../build
configureScript=../$sourceRoot/configure
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,57 @@
{
lib,
stdenv,
libstdcxx,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libsanitizer";
inherit version;
src = runCommand "libsanitizer-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
cp -r libsanitizer "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp mkinstalldirs "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
sourceRoot = "${finalAttrs.src.name}/libsanitizer";
postUnpack = ''
mkdir -p libstdc++-v3/src/
ln -s ${libstdcxx}/lib/libstdc++.la libstdc++-v3/src/libstdc++.la
'';
preConfigure = ''
mkdir ../../build
cd ../../build
configureScript=../$sourceRoot/configure
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,101 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
fetchpatch,
autoreconfHook269,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libssp";
inherit version;
src = runCommand "libssp-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
cp -r libssp "$out"
cp -r config "$out"
cp -r multilib.am "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp mkinstalldirs "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
outputs = [
"out"
"dev"
];
patches = [
(fetchpatch {
name = "regular-libdir-includedir.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250720172933.2404828-1-git@JohnEricson.me/raw";
hash = "sha256-W7dcy1Tm3O2reK7kx83DRv8W97qUfaqDbKLiLXIegRw=";
})
(getVersionFile "libssp/force-regular-dirs.patch")
];
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
preAutoreconf = ''
sourceRoot=$(readlink -e "./libssp")
cd $sourceRoot
'';
enableParallelBuilding = true;
nativeBuildInputs = [
autoreconfHook269
];
configurePlatforms = [
"build"
"host"
];
configureFlags = [
"--disable-dependency-tracking"
"cross_compiling=true"
"--disable-multilib"
];
preConfigure = ''
cd "$buildRoot"
configureScript=$sourceRoot/configure
'';
hardeningDisable = [
"fortify"
# Because we are building it!
"stackprotector"
];
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@@ -0,0 +1,127 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
fetchpatch,
autoreconfHook269,
runCommand,
gettext,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libstdcxx";
inherit version;
src = runCommand "libstdcxx-src-${version}" { src = monorepoSrc; } ''
runPhase unpackPhase
mkdir -p "$out/gcc"
cp gcc/BASE-VER "$out/gcc"
cp gcc/DATESTAMP "$out/gcc"
mkdir -p "$out/libgcc"
cp libgcc/gthr*.h "$out/libgcc"
cp libgcc/unwind-pe.h "$out/libgcc"
cp -r libstdc++-v3 "$out"
cp -r libiberty "$out"
cp -r include "$out"
cp -r contrib "$out"
cp -r config "$out"
cp -r multilib.am "$out"
cp config.guess "$out"
cp config.rpath "$out"
cp config.sub "$out"
cp config-ml.in "$out"
cp ltmain.sh "$out"
cp install-sh "$out"
cp mkinstalldirs "$out"
[[ -f MD5SUMS ]]; cp MD5SUMS "$out"
'';
outputs = [
"out"
"dev"
];
patches = [
(fetchpatch {
name = "custom-threading-model.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250716204545.1063669-1-git@JohnEricson.me/raw";
hash = "sha256-jPP0+MoPLtCwWcW6doO6KHCppwAYK40qNVyriLXcGOg=";
includes = [
"config/*"
"libstdc++-v3/*"
];
})
(getVersionFile "libstdcxx/force-regular-dirs.patch")
];
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
preAutoreconf = ''
sourceRoot=$(readlink -e "./libstdc++-v3")
cd $sourceRoot
'';
enableParallelBuilding = true;
nativeBuildInputs = [
autoreconfHook269
gettext
];
preConfigure = ''
cd "$buildRoot"
configureScript=$sourceRoot/configure
chmod +x "$configureScript"
'';
configurePlatforms = [
"build"
"host"
];
configureFlags = [
"--disable-dependency-tracking"
"gcc_cv_target_thread_file=posix"
"cross_compiling=true"
"--disable-multilib"
"--enable-clocale=gnu"
"--disable-libstdcxx-pch"
"--disable-vtable-verify"
"--enable-libstdcxx-visibility"
"--with-default-libstdcxx-abi=new"
];
hardeningDisable = [
# PATH_MAX
"fortify"
];
postInstall = ''
moveToOutput lib/libstdc++.modules.json "$dev"
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/onlinedocs/libstdc++";
description = "GNU C++ Library";
};
})

View File

@@ -0,0 +1,38 @@
{
# TODO: fix up and send to upstream
"gcc/fix-collect2-paths.diff" = [
{
after = "15";
path = ../15;
}
];
# In Git: https://github.com/Ericson2314/gcc/tree/regular-dirs-in-libgcc-15
"libgcc/force-regular-dirs.patch" = [
{
after = "15";
path = ../15;
}
];
# In Git: https://github.com/Ericson2314/gcc/tree/regular-dirs-in-libssp-15
"libssp/force-regular-dirs.patch" = [
{
after = "15";
path = ../15;
}
];
# In Git: https://github.com/Ericson2314/gcc/tree/libstdcxx-force-regular-dirs-15
"libstdcxx/force-regular-dirs.patch" = [
{
after = "15";
path = ../15;
}
];
# In Git: https://github.com/Ericson2314/gcc/tree/libgfortran-force-regular-dirs-15
"libgfortran/force-regular-dirs.patch" = [
{
after = "15";
path = ../15;
}
];
}

View File

@@ -0,0 +1,70 @@
{
lib,
callPackage,
stdenv,
stdenvAdapters,
recurseIntoAttrs,
gccVersions ? { },
patchesFn ? lib.id,
buildPackages,
targetPackages,
binutilsNoLibc,
binutils,
generateSplicesForMkScope,
...
}@packageSetArgs:
let
versions = {
"15.1.0".officialRelease.sha256 = "sha256-4rCewhZg8B/s/7cV4BICZSFpQ/A40OSKmGhxPlTwbOo=";
}
// gccVersions;
mkPackage =
{
name ? null,
officialRelease ? null,
gitRelease ? null,
monorepoSrc ? null,
version ? null,
}@args:
let
inherit
(import ./common/common-let.nix {
inherit
lib
gitRelease
officialRelease
version
;
})
releaseInfo
;
inherit (releaseInfo) release_version;
attrName =
args.name or (if (gitRelease != null) then "git" else lib.versions.major release_version);
in
lib.nameValuePair attrName (
recurseIntoAttrs (
callPackage ./common (
{
inherit (stdenvAdapters) overrideCC;
inherit
officialRelease
gitRelease
monorepoSrc
version
patchesFn
;
buildGccPackages = buildPackages."gccNGPackages_${attrName}";
targetGccPackages = targetPackages."gccNGPackages_${attrName}" or gccPackages."${attrName}";
otherSplices = generateSplicesForMkScope "gccNGPackages_${attrName}";
}
// packageSetArgs # Allow overrides.
)
)
);
gccPackages = lib.mapAttrs' (version: args: mkPackage (args // { inherit version; })) versions;
in
gccPackages // { inherit mkPackage; }

View File

@@ -0,0 +1,97 @@
From e160a8cd4a704f4b7724df02b62394f677cc4198 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <siarheit@google.com>
Date: Fri, 22 Sep 2023 22:41:49 +0100
Subject: [PATCH] gcc/file-prefix-map.cc: always mangle __FILE__ into invalid
store path
Without the change `__FILE__` used in static inline functions in headers
embed paths to header files into executable images. For local headers
it's not a problem, but for headers in `/nix/store` this causes `-dev`
inputs to be retained in runtime closure.
Typical examples are `nix` -> `nlohmann_json` and `pipewire` ->
`lttng-ust.dev`.
For this reason we want to remove the occurrences of hashes in the
expansion of `__FILE__`. `nuke-references` does it by replacing hashes
by `eeeeee...`. It is handy to be able to invert the transformation to
go back to the original store path. The chosen solution is to make the
hash uppercase:
- it does not trigger runtime references (except for all digit hashes,
which are unlikely enough)
- it visually looks like a bogus store path
- it is easy to find the original store path if required
Ideally we would like to use `-fmacro-prefix-map=` feature of `gcc` as:
-fmacro-prefix-map=/nix/store/$hash1-nlohmann-json-ver=/nix/store/$HASH1-nlohmann-json-ver
-fmacro-prefix-map=/nix/...
In practice it quickly exhausts argument length limit due to `gcc`
deficiency: https://gcc.gnu.org/PR111527
Until it's fixed let's hardcode header mangling if $NIX_STORE variable
is present in the environment.
Tested as:
$ printf "# 0 \"/nix/store/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-pppppp-vvvvvvv\" \nconst char * f(void) { return __FILE__; }" | NIX_STORE=/nix/store ./gcc/xgcc -Bgcc -x c - -S -o -
...
.string "/nix/store/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-pppppp-vvvvvvv"
...
Mangled successfully.
To reverse the effect of the mangle use new `NIX_GCC_DONT_MANGLE_PREFIX_MAP`
environment variable. It should not normally be needed.
--- a/gcc/file-prefix-map.cc
+++ b/gcc/file-prefix-map.cc
@@ -74,7 +74,7 @@ add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
remapping was performed. */
static const char *
-remap_filename (file_prefix_map *maps, const char *filename)
+remap_filename (file_prefix_map *maps, const char *filename, bool mangle_nix_store = false)
{
file_prefix_map *map;
char *s;
@@ -102,6 +102,30 @@ remap_filename (file_prefix_map *maps, const char *filename)
break;
if (!map)
{
+ if (mangle_nix_store && getenv("NIX_GCC_DONT_MANGLE_PREFIX_MAP") == NULL)
+ {
+ /* Remap all fo $NIX_STORE/.{32} paths to uppercase
+ *
+ * That way we avoid argument parameters explosion
+ * and still avoid embedding headers into runtime closure:
+ * https://gcc.gnu.org/PR111527
+ */
+ char * nix_store = getenv("NIX_STORE");
+ size_t nix_store_len = nix_store ? strlen(nix_store) : 0;
+ const char * name = realname ? realname : filename;
+ size_t name_len = strlen(name);
+ if (nix_store && name_len >= nix_store_len + 1 + 32 && memcmp(name, nix_store, nix_store_len) == 0)
+ {
+ s = (char *) ggc_alloc_atomic (name_len + 1);
+ memcpy(s, name, name_len + 1);
+ for (size_t i = nix_store_len + 1; i < nix_store_len + 1 + 32; i++) {
+ s[i] = TOUPPER(s[i]);
+ }
+ if (realname != filename)
+ free (const_cast <char *> (realname));
+ return s;
+ }
+ }
if (realname != filename)
free (const_cast <char *> (realname));
return filename;
@@ -163,7 +187,7 @@ add_profile_prefix_map (const char *arg)
const char *
remap_macro_filename (const char *filename)
{
- return remap_filename (macro_prefix_maps, filename);
+ return remap_filename (macro_prefix_maps, filename, true);
}
/* Remap using -fdebug-prefix-map. Return the GC-allocated new name

View File

@@ -0,0 +1,13 @@
--- a/gcc/config/riscv/linux.h
+++ b/gcc/config/riscv/linux.h
@@ -69,9 +69,5 @@
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-#define STARTFILE_PREFIX_SPEC \
- "/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
- "/usr/lib" XLEN_SPEC "/" ABI_SPEC "/ " \
- "/lib/ " \
- "/usr/lib/ "
+#define STARTFILE_PREFIX_SPEC ""

View File

@@ -0,0 +1,39 @@
diff --git a/config/intlmacosx.m4 b/config/intlmacosx.m4
index 3141bf8c5..7a31862b9 100644
--- a/config/intlmacosx.m4
+++ b/config/intlmacosx.m4
@@ -63,7 +63,7 @@ AC_DEFUN([gt_INTL_MACOSX],
dnl and we have to link it in explicitly, otherwise an exception
dnl NSInvalidArgumentException "unrecognized selector sent to instance"
dnl occurs.
- INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation -Wl,-framework -Wl,CoreServices"
+ INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
fi
AC_SUBST([INTL_MACOSX_LIBS])
])
diff --git a/gcc/configure b/gcc/configure
index 23da7d55d..8bd09364d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -13932,7 +13932,7 @@ $as_echo "#define HAVE_CFLOCALECOPYPREFERREDLANGUAGES 1" >>confdefs.h
INTL_MACOSX_LIBS=
if test $gt_cv_func_CFPreferencesCopyAppValue = yes \
|| test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
- INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation -Wl,-framework -Wl,CoreServices"
+ INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
fi
diff --git a/libcpp/configure b/libcpp/configure
index 32d6aaa30..592c33881 100755
--- a/libcpp/configure
+++ b/libcpp/configure
@@ -7570,7 +7570,7 @@ $as_echo "#define HAVE_CFLOCALECOPYPREFERREDLANGUAGES 1" >>confdefs.h
INTL_MACOSX_LIBS=
if test $gt_cv_func_CFPreferencesCopyAppValue = yes \
|| test $gt_cv_func_CFLocaleCopyPreferredLanguages = yes; then
- INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation -Wl,-framework -Wl,CoreServices"
+ INTL_MACOSX_LIBS="-Wl,-framework -Wl,CoreFoundation"
fi

View File

@@ -0,0 +1,21 @@
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 0666fc00b..0e2d53eb8 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -793,14 +793,14 @@ gnatlib-shared-darwin:
-o libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
$(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS) \
$(SO_OPTS) \
- -Wl,-install_name,@rpath/libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
+ -Wl,-install_name,$(ADA_RTL_DSO_DIR)/libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
-nodefaultrpaths -Wl,-rpath,@loader_path/,-rpath,@loader_path/.. \
-Wl,-rpath,@loader_path/../../../../ $(MISCLIB)
cd $(RTSDIR); $(GCC_FOR_ADA_RTS) -dynamiclib $(PICFLAG_FOR_TARGET) \
-o libgnarl$(hyphen)$(LIBRARY_VERSION)$(soext) \
$(GNATRTL_TASKING_OBJS) \
$(SO_OPTS) \
- -Wl,-install_name,@rpath/libgnarl$(hyphen)$(LIBRARY_VERSION)$(soext) \
+ -Wl,-install_name,$(ADA_RTL_DSO_DIR)/libgnarl$(hyphen)$(LIBRARY_VERSION)$(soext) \
-nodefaultrpaths -Wl,-rpath,@loader_path/,-rpath,@loader_path/.. \
-Wl,-rpath,@loader_path/../../../../ \
$(THREADSLIB) -Wl,libgnat$(hyphen)$(LIBRARY_VERSION)$(soext)

View File

@@ -0,0 +1,13 @@
diff --git a/libgcc/config.host b/libgcc/config.host
index 7332903704..27a8b5bedb 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -236,7 +236,7 @@
esac
tmake_file="$tmake_file t-slibgcc-darwin"
case ${host} in
- *-*-darwin2*)
+ *-*-darwin2* | *-*-darwin)
tmake_file="t-darwin-min-11 $tmake_file"
;;
*-*-darwin1[89]*)

View File

@@ -0,0 +1,11 @@
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -239,7 +239,7 @@ case ${host} in
x86_64-*-darwin2[0-2]*)
tmake_file="t-darwin-min-11 t-darwin-libgccs1 $tmake_file"
;;
- *-*-darwin2*)
+ *-*-darwin2* | *-*-darwin)
tmake_file="t-darwin-min-11 $tmake_file"
;;
*-*-darwin1[89]*)

View File

@@ -0,0 +1,33 @@
As originally implemented, the error message check
described in the configure script
breaks detection of Ada compiler support on x86_64-darwin,
because the assembler in the version of cctools currently used
unconditionally emits a deprecation message to stdout,
with no way to disable it.
Furthermore, GCC 3.4 was the minimum version needed to build GNAT
as far back as GCC 4.4 (see the GCC git repo, tags/releases/gcc-4.4.0,
gcc/doc/install.texi, lines 2052-2053 [1]);
GCC 3.4 is newer than any of the broken GCC versions
that the configure script works around
(see the part of the comment in the configure script
before the context in the patch below),
and GCC 4.4 is older than any GCC that Nix currently packages (GCC 4.8).
We therefore choose to not check for error messages,
and just check for an error code.
There's no harm in still checking for an object file being created, though.
[1]: https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/doc/install.texi;h=6bdfbece981f7fb6c26da672d45e5d3ba7879c69;hb=b7fc996728085c0591ea7c5d0e1c84a8f6a29bd8#l2052
--- a/configure 2022-08-19 18:09:52.000000000 +1000
+++ b/configure 2022-12-26 17:30:49.000000000 +1100
@@ -5622,8 +5622,7 @@
# Other compilers, like HP Tru64 UNIX cc, exit successfully when
# given a .adb file, but produce no object file. So we must check
# if an object file was really produced to guard against this.
-errors=`(${CC} -c conftest.adb) 2>&1 || echo failure`
-if test x"$errors" = x && test -f conftest.$ac_objext; then
+if ${CC} -c conftest.adb && test -f conftest.$ac_objext; then
acx_cv_cc_gcc_supports_ada=yes
fi
rm -f conftest.*

View File

@@ -0,0 +1,16 @@
this patch fixes build for clang-18+
diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index d3235bc33..1a56eb61c 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -170,8 +170,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.globl \name
.hidden \name
.type \name, %function
- .cfi_startproc
\name:
+ .cfi_startproc
BTI_C
.endm

View File

@@ -0,0 +1,16 @@
this patch fixes build for clang-18+
diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index ecef47086..b478dd4d9 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -174,8 +174,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.globl \name
HIDDEN(\name)
SYMBOL_TYPE(\name, %function)
- .cfi_startproc
\name:
+ .cfi_startproc
.endm
.macro ENDFN name

View File

@@ -0,0 +1,16 @@
this patch fixes build for clang-18+
diff --git a/libgcc/config/aarch64/lse.S b/libgcc/config/aarch64/lse.S
index d3235bc33..1a56eb61c 100644
--- a/libgcc/config/aarch64/lse.S
+++ b/libgcc/config/aarch64/lse.S
@@ -197,8 +197,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.text
.balign 16
.private_extern _\name
- .cfi_startproc
_\name:
+ .cfi_startproc
BTI_C
.endm

View File

@@ -0,0 +1,240 @@
{
lib,
stdenv,
langC,
langAda,
langObjC,
langObjCpp,
langFortran,
langGo,
reproducibleBuild,
profiledCompiler,
langJit,
staticCompiler,
enableShared,
enableLTO,
version,
fetchpatch,
majorVersion,
targetPlatform,
hostPlatform,
noSysDirs,
buildPlatform,
fetchurl,
withoutTargetLibc,
threadsCross,
}:
let
atLeast15 = lib.versionAtLeast version "15";
atLeast14 = lib.versionAtLeast version "14";
is15 = majorVersion == "15";
is14 = majorVersion == "14";
is13 = majorVersion == "13";
# We only apply these patches when building a native toolchain for
# aarch64-darwin, as it breaks building a foreign one:
# https://github.com/iains/gcc-12-branch/issues/18
canApplyIainsDarwinPatches =
stdenv.hostPlatform.isDarwin
&& stdenv.hostPlatform.isAarch64
&& (lib.systems.equals buildPlatform hostPlatform)
&& (lib.systems.equals hostPlatform targetPlatform);
inherit (lib) optionals optional;
in
#
# Patches below are organized into two general categories:
# 1. Patches relevant on every platform
# 2. Patches relevant on specific platforms
#
## 1. Patches relevant on every platform ####################################
[ ]
# Pass the path to a C++ compiler directly in the Makefile.in
++ optional (!lib.systems.equals targetPlatform hostPlatform) ./libstdc++-target.patch
++ optionals noSysDirs (
[
# Do not try looking for binaries and libraries in /lib and /usr/lib
./gcc-12-no-sys-dirs.patch
]
++ (
{
"15" = [
# Do not try looking for binaries and libraries in /lib and /usr/lib
./13/no-sys-dirs-riscv.patch
# Mangle the nix store hash in __FILE__ to prevent unneeded runtime references
#
# TODO: Remove these and the `useMacroPrefixMap` conditional
# in `cc-wrapper` once <https://gcc.gnu.org/PR111527>
# is fixed.
./13/mangle-NIX_STORE-in-__FILE__.patch
];
"14" = [
./13/no-sys-dirs-riscv.patch
./13/mangle-NIX_STORE-in-__FILE__.patch
];
"13" = [
./13/no-sys-dirs-riscv.patch
./13/mangle-NIX_STORE-in-__FILE__.patch
];
}
."${majorVersion}" or [ ]
)
)
# Pass CFLAGS on to gnat
++ optional langAda ./gnat-cflags-11.patch
++
optional langFortran
# Fix interaction of gfortran and libtool
# Fixes the output of -v
# See also https://github.com/nixOS/nixpkgs/commit/cc6f814a8f0e9b70ede5b24192558664fa1f98a2
./gcc-12-gfortran-driving.patch
# Do not pass a default include dir on PowerPC+Musl
# See https://github.com/NixOS/nixpkgs/pull/45340/commits/d6bb7d45162ac93e017cc9b665ae4836f6410710
++ [ ./ppc-musl.patch ]
# Moves the .cfi_starproc instruction to after the function label
# Needed to build llvm-18 and later
# See https://github.com/NixOS/nixpkgs/pull/354107/commits/2de1b4b14e17f42ba8b4bf43a29347c91511e008
++ optional (!atLeast14) ./cfi_startproc-reorder-label-09-1.diff
++ optional (atLeast14 && !canApplyIainsDarwinPatches) ./cfi_startproc-reorder-label-14-1.diff
## 2. Patches relevant on specific platforms ####################################
### Musl+Go+gcc12
# backport fixes to build gccgo with musl libc
++ optionals (stdenv.hostPlatform.isMusl && langGo) [
# libgo: handle stat st_atim32 field and SYS_SECCOMP
# syscall: gofmt
# Add blank lines after //sys comments where needed, and then run gofmt
# on the syscall package with the new formatter.
# See https://go-review.googlesource.com/c/gofrontend/+/412074
(fetchpatch {
excludes = [ "gcc/go/gofrontend/MERGE" ];
url = "https://github.com/gcc-mirror/gcc/commit/cf79b1117bd177d3d4c6ed24b6fa243c3628ac2d.diff";
hash = "sha256-mS5ZiYi5D8CpGXrWg3tXlbhp4o86ew1imCTwaHLfl+I=";
})
# libgo: permit loff_t and off_t to be macros
# See https://go-review.googlesource.com/c/gofrontend/+/412075
(fetchpatch {
excludes = [ "gcc/go/gofrontend/MERGE" ];
url = "https://github.com/gcc-mirror/gcc/commit/7f195a2270910a6ed08bd76e3a16b0a6503f9faf.diff";
hash = "sha256-Ze/cFM0dQofKH00PWPDoklXUlwWhwA1nyTuiDAZ6FKo=";
})
# libgo: handle stat st_atim32 field and SYS_SECCOMP
# See https://go-review.googlesource.com/c/gofrontend/+/415294
(fetchpatch {
excludes = [ "gcc/go/gofrontend/MERGE" ];
url = "https://github.com/gcc-mirror/gcc/commit/762fd5e5547e464e25b4bee435db6df4eda0de90.diff";
hash = "sha256-o28upwTcHAnHG2Iq0OewzwSBEhHs+XpBGdIfZdT81pk=";
})
# runtime: portable access to sigev_notify_thread_id
# See https://sourceware.org/bugzilla/show_bug.cgi?id=27417
# See https://go-review.googlesource.com/c/gofrontend/+/434755
(fetchpatch {
excludes = [ "gcc/go/gofrontend/MERGE" ];
url = "https://github.com/gcc-mirror/gcc/commit/e73d9fcafbd07bc3714fbaf8a82db71d50015c92.diff";
hash = "sha256-1SjYCVHLEUihdON2TOC3Z2ufM+jf2vH0LvYtZL+c1Fo=";
})
# syscall, runtime: always call XSI strerror_r
# See https://go-review.googlesource.com/c/gofrontend/+/454176
(fetchpatch {
excludes = [ "gcc/go/gofrontend/MERGE" ];
url = "https://github.com/gcc-mirror/gcc/commit/b6c6a3d64f2e4e9347733290aca3c75898c44b2e.diff";
hash = "sha256-RycJ3YCHd3MXtYFjxP0zY2Wuw7/C4bWoBAQtTKJZPOQ=";
})
# libgo: check for makecontext in -lucontext
# See https://go-review.googlesource.com/c/gofrontend/+/458396
(fetchpatch {
excludes = [ "gcc/go/gofrontend/MERGE" ];
url = "https://github.com/gcc-mirror/gcc/commit/2b1a604a9b28fbf4f382060bebd04adb83acc2f9.diff";
hash = "sha256-WiBQG0Xbk75rHk+AMDvsbrm+dc7lDH0EONJXSdEeMGE=";
})
# x86: Fix -fsplit-stack feature detection via TARGET_CAN_SPLIT_STACK
# Fixes compiling for non-glibc target
(fetchpatch {
url = "https://github.com/gcc-mirror/gcc/commit/c86b726c048eddc1be320c0bf64a897658bee13d.diff";
hash = "sha256-QSIlqDB6JRQhbj/c3ejlmbfWz9l9FurdSWxpwDebnlI=";
})
]
## Darwin
# Fixes detection of Darwin on x86_64-darwin. Otherwise, GCC uses a deployment target of 10.5, which crashes ld64.
++ optional (
is14 && stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64
) ../patches/14/libgcc-darwin-detection.patch
++ optional (
atLeast15 && stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64
) ../patches/15/libgcc-darwin-detection.patch
# Fix detection of bootstrap compiler Ada support (cctools as) on Nix Darwin
++ optional (stdenv.hostPlatform.isDarwin && langAda) ./ada-cctools-as-detection-configure.patch
# Remove CoreServices on Darwin, as it is only needed for macOS SDK 14+
++ optional (
atLeast14 && stdenv.hostPlatform.isDarwin && langAda
) ../patches/14/gcc-darwin-remove-coreservices.patch
# Use absolute path in GNAT dylib install names on Darwin
++ optionals (stdenv.hostPlatform.isDarwin && langAda) (
{
"15" = [ ../patches/14/gnat-darwin-dylib-install-name-14.patch ];
"14" = [ ../patches/14/gnat-darwin-dylib-install-name-14.patch ];
"13" = [ ./gnat-darwin-dylib-install-name-13.patch ];
}
.${majorVersion} or [ ]
)
# Here we apply patches by Iains (https://github.com/iains)
# GitHub's "compare" API produces unstable diffs, so we resort to reusing
# diffs from the Homebrew repo.
++ optionals canApplyIainsDarwinPatches (
{
"15" = [
# Patches from https://github.com/iains/gcc-15-branch/compare/releases/gcc-15..gcc-15.1-darwin-rc1
(fetchpatch {
name = "gcc-15-darwin-aarch64-support.patch";
url = "https://raw.githubusercontent.com/Homebrew/formula-patches/a25079204c1cb3d78ba9dd7dd22b8aecce7ce264/gcc/gcc-15.1.0.diff";
sha256 = "sha256-MJxSGv6LEP1sIM8cDqbmfUV7byV0bYgADeIBY/Teyu8=";
})
];
"14" = [
# Patches from https://github.com/iains/gcc-14-branch/compare/04696df09633baf97cdbbdd6e9929b9d472161d3..gcc-14.2-darwin-r2
(fetchpatch {
# There are no upstream release tags nor a static branch for 14.3.0 in https://github.com/iains/gcc-14-branch.
# aa4cd614456de65ee3417acb83c6cff0640144e9 is the merge base of https://github.com/iains/gcc-14-branch/tree/gcc-14-3-darwin-pre-0 and https://github.com/gcc-mirror/gcc/releases/tag/releases%2Fgcc-14.3.0
# 3e1d48d240f4aa5223c701b5c231c66f66ab1126 is the newest commit of https://github.com/iains/gcc-14-branch/tree/gcc-14-3-darwin-pre-0
name = "gcc-14-darwin-aarch64-support.patch";
url = "https://github.com/iains/gcc-14-branch/compare/aa4cd614456de65ee3417acb83c6cff0640144e9..3e1d48d240f4aa5223c701b5c231c66f66ab1126.diff";
hash = "sha256-BSTSYnkBJBEm++mGerVVyaCUC4dUyXq0N1tqbk25bO4=";
})
];
# Patches from https://github.com/iains/gcc-13-branch/compare/b71f1de6e9cf7181a288c0f39f9b1ef6580cf5c8..gcc-13-3-darwin
"13" = [
(fetchpatch {
name = "gcc-13-darwin-aarch64-support.patch";
url = "https://raw.githubusercontent.com/Homebrew/formula-patches/698885df7f624d0ce15bceb79a4d9760a473b502/gcc/gcc-13.4.0.diff";
hash = "sha256-xqkBDFYZ6fdowtqR3kV7bR8a4Cu11RDokSzGn1k3a1w=";
})
];
}
.${majorVersion} or [ ]
)
++ optional targetPlatform.isCygwin (fetchpatch {
name = "libstdc-fix-compilation-in-freestanding-win32.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250922182808.2599390-2-corngood@gmail.com/raw";
hash = "sha256-+EYW9lG8CviVX7RyNHp+iX+8BRHUjt5b07k940khbbY=";
})
++ optionals targetPlatform.isCygwin [
(fetchpatch {
name = "cygwin-fix-compilation-with-inhibit_libc.patch";
url = "https://inbox.sourceware.org/gcc-patches/20250926170154.2222977-1-corngood@gmail.com/raw";
hash = "sha256-mgzMRvgPdhj+Q2VRsFhpE2WQzg0CvWsc5/FRAsSU1Es=";
})
]

View File

@@ -0,0 +1,20 @@
This patch fixes interaction with Libtool.
See <http://thread.gmane.org/gmane.comp.gcc.patches/258777>, for details.
--- a/gcc/fortran/gfortranspec.cc
+++ b/gcc/fortran/gfortranspec.cc
@@ -461,8 +461,15 @@ For more information about these matters, see the file named COPYING\n\n"));
{
fprintf (stderr, _("Driving:"));
for (i = 0; i < g77_newargc; i++)
+ {
+ if (g77_new_decoded_options[i].opt_index == OPT_l)
+ /* Make sure no white space is inserted after `-l'. */
+ fprintf (stderr, " -l%s",
+ g77_new_decoded_options[i].canonical_option[1]);
+ else
fprintf (stderr, " %s",
g77_new_decoded_options[i].orig_option_with_args_text);
+ }
fprintf (stderr, "\n");
}

View File

@@ -0,0 +1,26 @@
--- a/gcc/cppdefault.cc 2013-01-10 21:38:27.000000000 +0100
+++ b/gcc/cppdefault.cc 2014-08-18 16:20:32.893944536 +0200
@@ -35,6 +35,8 @@
# undef CROSS_INCLUDE_DIR
#endif
+#undef LOCAL_INCLUDE_DIR
+
const struct default_include cpp_include_defaults[]
#ifdef INCLUDE_DEFAULTS
= INCLUDE_DEFAULTS;
--- a/gcc/gcc.cc 2014-03-23 12:30:57.000000000 +0100
+++ b/gcc/gcc.cc 2014-08-18 13:19:32.689201690 +0200
@@ -1162,10 +1162,10 @@
/* Default prefixes to attach to command names. */
#ifndef STANDARD_STARTFILE_PREFIX_1
-#define STANDARD_STARTFILE_PREFIX_1 "/lib/"
+#define STANDARD_STARTFILE_PREFIX_1 ""
#endif
#ifndef STANDARD_STARTFILE_PREFIX_2
-#define STANDARD_STARTFILE_PREFIX_2 "/usr/lib/"
+#define STANDARD_STARTFILE_PREFIX_2 ""
#endif
#ifdef CROSS_DIRECTORY_STRUCTURE /* Don't use these prefixes for a cross compiler. */

View File

@@ -0,0 +1,35 @@
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 4e74252bd74..0d848b5b4e3 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -111,7 +111,7 @@ NO_OMIT_ADAFLAGS = -fno-omit-frame-pointer
NO_SIBLING_ADAFLAGS = -fno-optimize-sibling-calls
NO_REORDER_ADAFLAGS = -fno-toplevel-reorder
GNATLIBFLAGS = -W -Wall -gnatg -nostdinc
-GNATLIBCFLAGS = -g -O2
+GNATLIBCFLAGS = -g -O2 $(CFLAGS_FOR_TARGET)
# Pretend that _Unwind_GetIPInfo is available for the target by default. This
# should be autodetected during the configuration of libada and passed down to
# here, but we need something for --disable-libada and hope for the best.
@@ -198,7 +198,7 @@ RTSDIR = rts$(subst /,_,$(MULTISUBDIR))
# Link flags used to build gnat tools. By default we prefer to statically
# link with libgcc to avoid a dependency on shared libgcc (which is tricky
# to deal with as it may conflict with the libgcc provided by the system).
-GCC_LINK_FLAGS=-static-libstdc++ -static-libgcc
+GCC_LINK_FLAGS=-static-libstdc++ -static-libgcc $(CFLAGS_FOR_TARGET)
# End of variables for you to override.
diff --git a/libada/Makefile.in b/libada/Makefile.in
index 522b9207326..ca866c74471 100644
--- a/libada/Makefile.in
+++ b/libada/Makefile.in
@@ -59,7 +59,7 @@ LDFLAGS=
CFLAGS=-g
PICFLAG = @PICFLAG@
GNATLIBFLAGS= -W -Wall -gnatpg -nostdinc
-GNATLIBCFLAGS= -g -O2
+GNATLIBCFLAGS= -g -O2 $(CFLAGS)
GNATLIBCFLAGS_FOR_C = -W -Wall $(GNATLIBCFLAGS) $(CFLAGS_FOR_TARGET) \
-fexceptions -DIN_RTS @have_getipinfo@ @have_capability@

View File

@@ -0,0 +1,18 @@
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -788,13 +788,13 @@ gnatlib-shared-darwin:
-o libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
$(GNATRTL_NONTASKING_OBJS) $(LIBGNAT_OBJS) \
$(SO_OPTS) \
- -Wl,-install_name,@rpath/libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
+ -Wl,-install_name,$(ADA_RTL_DSO_DIR)/libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
$(MISCLIB)
cd $(RTSDIR); $(GCC_FOR_ADA_RTS) -dynamiclib $(PICFLAG_FOR_TARGET) \
-o libgnarl$(hyphen)$(LIBRARY_VERSION)$(soext) \
$(GNATRTL_TASKING_OBJS) \
$(SO_OPTS) \
- -Wl,-install_name,@rpath/libgnarl$(hyphen)$(LIBRARY_VERSION)$(soext) \
+ -Wl,-install_name,$(ADA_RTL_DSO_DIR)/libgnarl$(hyphen)$(LIBRARY_VERSION)$(soext) \
$(THREADSLIB) -Wl,libgnat$(hyphen)$(LIBRARY_VERSION)$(soext)
cd $(RTSDIR); $(LN_S) libgnat$(hyphen)$(LIBRARY_VERSION)$(soext) \
libgnat$(soext)

View File

@@ -0,0 +1,32 @@
Patch to make the target libraries 'configure' scripts find the proper CPP.
I noticed that building the mingw32 cross compiler.
Looking at the build script for mingw in archlinux, I think that only nixos
needs this patch. I don't know why.
diff --git a/Makefile.in b/Makefile.in
index 93f66b6..d691917 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -266,6 +266,7 @@ BASE_TARGET_EXPORTS = \
AR="$(AR_FOR_TARGET)"; export AR; \
AS="$(COMPILER_AS_FOR_TARGET)"; export AS; \
CC="$(CC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CC; \
+ CPP="$(CC_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CC; \
CFLAGS="$(CFLAGS_FOR_TARGET)"; export CFLAGS; \
CONFIG_SHELL="$(SHELL)"; export CONFIG_SHELL; \
CPPFLAGS="$(CPPFLAGS_FOR_TARGET)"; export CPPFLAGS; \
@@ -291,11 +292,13 @@ BASE_TARGET_EXPORTS = \
RAW_CXX_TARGET_EXPORTS = \
$(BASE_TARGET_EXPORTS) \
CXX_FOR_TARGET="$(RAW_CXX_FOR_TARGET)"; export CXX_FOR_TARGET; \
- CXX="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX;
+ CXX="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; \
+ CXXCPP="$(RAW_CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CXX;
NORMAL_TARGET_EXPORTS = \
$(BASE_TARGET_EXPORTS) \
- CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX;
+ CXX="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS"; export CXX; \
+ CXXCPP="$(CXX_FOR_TARGET) $(XGCC_FLAGS_FOR_TARGET) $$TFLAGS -E"; export CXX;
# Where to find GMP
HOST_GMPLIBS = @gmplibs@

View File

@@ -0,0 +1,18 @@
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index cbee89140dd..e1f26b0a096 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -996,13 +996,7 @@ ncrtn.o%s"
{ GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1, \
GPLUSPLUS_INCLUDE_DIR_ADD_SYSROOT, 0 },
-#ifdef LOCAL_INCLUDE_DIR
-#define INCLUDE_DEFAULTS_MUSL_LOCAL \
- { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 2 }, \
- { LOCAL_INCLUDE_DIR, 0, 0, 1, 1, 0 },
-#else
#define INCLUDE_DEFAULTS_MUSL_LOCAL
-#endif
#ifdef PREFIX_INCLUDE_DIR
#define INCLUDE_DEFAULTS_MUSL_PREFIX \

View File

@@ -0,0 +1,27 @@
let
majorMinorToVersionMap = {
"15" = "15.2.0";
"14" = "14.3.0";
"13" = "13.4.0";
};
fromMajorMinor = majorMinorVersion: majorMinorToVersionMap."${majorMinorVersion}";
# TODO(amjoseph): convert older hashes to SRI form
srcHashForVersion =
version:
{
# 3 digits: releases (14.2.0)
# 4 digits: snapshots (14.2.1.20250322)
"15.2.0" = "sha256-Q4/ZloJrDIJIWinaA6ctcdbjVBqD7HAt9Ccfb+Al0k4=";
"14.3.0" = "sha256-4Nx3KXYlYxrI5Q+pL//v6Jmk63AlktpcMu8E4ik6yjo=";
"13.4.0" = "sha256-nEzm27BAVo/cVFWIrAPFy8lajb8MeqSQFwhDr7WcqPU=";
}
."${version}";
in
{
inherit fromMajorMinor;
inherit srcHashForVersion;
allMajorVersions = builtins.attrNames majorMinorToVersionMap;
}