mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-02 13:00:23 +00:00
Gccng misc fixes (#551313)
This commit is contained in:
@@ -153,6 +153,16 @@ let
|
||||
# Derived meta-data
|
||||
useLLVM = final.isFreeBSD || final.isOpenBSD;
|
||||
|
||||
# Use the split GCC package set (`gccNGPackages`) instead of the
|
||||
# monolithic `gcc`. No platform selects it yet; it is opt-in, set
|
||||
# explicitly on a platform spec, so that the split set can be exercised
|
||||
# before anything depends on it.
|
||||
#
|
||||
# I (@Ericson2314) plan on making obscure low-tier platforms (e.g.
|
||||
# NetBSD) use it soon, so we can dogfood GCC NG and thereby iron out its
|
||||
# bugs.
|
||||
useGccNG = false;
|
||||
|
||||
libc =
|
||||
if final.isDarwin then
|
||||
"libSystem"
|
||||
|
||||
@@ -804,9 +804,15 @@ stdenvNoCC.mkDerivation {
|
||||
include -cxx-isystem "${getDev libcxx}/include/c++/v1" >> $out/nix-support/libcxx-cxxflags
|
||||
echo "-stdlib=libc++" >> $out/nix-support/libcxx-ldflags
|
||||
''
|
||||
# GCC NG friendly libc++
|
||||
# This is the GCC NG case, libstdc++ is being built as a separate package.
|
||||
#
|
||||
# Point at `include-cxx`, not `include`. `libcxx` is also a propagated
|
||||
# target-target dep, so the generic setup hook puts its `include` on the *C*
|
||||
# include path -- and libstdc++ ships headers named after C headers
|
||||
# (`math.h`, `stdlib.h`, `stdckdint.h`, ...) that are only meant to shadow
|
||||
# the C ones in C++. A sibling directory the setup hook ignores is enough.
|
||||
+ optionalString (libcxx != null && libcxx.isGNU or false) ''
|
||||
include -isystem "${getDev libcxx}/include" >> $out/nix-support/libcxx-cxxflags
|
||||
include -isystem "${getDev libcxx}/include-cxx" >> $out/nix-support/libcxx-cxxflags
|
||||
''
|
||||
|
||||
##
|
||||
|
||||
@@ -174,7 +174,14 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
install -D ${tree_h} $dev/include/sys/tree.h
|
||||
'';
|
||||
|
||||
passthru.linuxHeaders = linuxHeaders;
|
||||
passthru = {
|
||||
linuxHeaders = linuxHeaders;
|
||||
|
||||
# musl's threads are POSIX threads. `libgcc` and `libstdc++` have to be
|
||||
# configured for the same threading model as each other, so rather than
|
||||
# have each guess, they take it from the libc they are built against.
|
||||
threadModel = "posix";
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Efficient, small, quality libc implementation";
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
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
|
||||
Subject: [PATCH] libstdc++: Force regular lib dir, headers in include-cxx
|
||||
|
||||
Delete a bunch of unneeded logic to do this.
|
||||
|
||||
The library goes straight in $(libdir), with no version-specific or
|
||||
target-specific subdirectory.
|
||||
|
||||
The headers go in $(includedir)-cxx rather than $(includedir). libstdc++
|
||||
intentionally ships headers named after C headers -- `math.h`, `stdlib.h`,
|
||||
`complex.h`, `stdckdint.h` and friends -- whose whole purpose is to shadow
|
||||
the C ones when compiling C++. Installed into the ordinary include dir they
|
||||
shadow them when compiling *C* too, because the generic setup hook puts that
|
||||
directory on the C include path. A sibling directory keeps them out of C's
|
||||
way while staying findable for C++; no version or target subdirectory is
|
||||
needed, since the store path already separates one libstdc++ from another.
|
||||
---
|
||||
libstdc++-v3/acinclude.m4 | 80 ++------------------------------
|
||||
libstdc++-v3/include/Makefile.am | 2 +-
|
||||
@@ -21,7 +33,7 @@ index a0094c2dd95..a0718dff394 100644
|
||||
- glibcxx_toolexeclibdir=no
|
||||
+ glibcxx_toolexecdir='$(libdir)'
|
||||
+ glibcxx_toolexeclibdir='$(libdir)'
|
||||
+ gxx_include_dir='$(includedir)'
|
||||
+ gxx_include_dir='$(includedir)-cxx'
|
||||
glibcxx_prefixdir=$prefix
|
||||
|
||||
- AC_MSG_CHECKING([for gxx-include-dir])
|
||||
|
||||
@@ -1,3 +1,58 @@
|
||||
# GCC Next-Generation
|
||||
|
||||
Experimental split GCC package set based on the LLVM package set design.
|
||||
Experimental split GCC package set, based on the LLVM package set design.
|
||||
|
||||
The monolithic `gcc` derivation builds the compiler and every runtime library in one go, so a change to the target libc rebuilds the compiler too.
|
||||
This set separates them — `gcc`, `libgcc`, `libstdcxx` and the rest are individual packages — so the compiler stops depending on the libc, and each piece can be rebuilt on its own.
|
||||
Because GCC is not a multi-target compiler — a single target is baked into the binary with CPP — we still need to rebuild it more than we do LLVM, but someday that should change.
|
||||
|
||||
A platform opts in with `useGccNG`, in the same way it would opt into `useLLVM`.
|
||||
|
||||
## The bootstrap chain
|
||||
|
||||
The libc and libgcc depend on each other: a libc's own sources call into libgcc for integer and floating-point helpers and for stack unwinding, and a libgcc that can use the libc's threads needs the libc.
|
||||
|
||||
The way out we currently use is the same one the LLVM set takes with `compiler-rt-no-libc` and `compiler-rt-libc` — build the runtime twice, either side of the libc.
|
||||
It is unclear whether this works in general to resolve the circularity, but we shall see.
|
||||
|
||||
That gives four compilers, each one step further along:
|
||||
|
||||
| compiler | libc | libgcc | used to build |
|
||||
|---|---|---|---|
|
||||
| `gccNoLibgcc` | headers, or nothing | — | `libgcc-no-libc` |
|
||||
| `gccWithLibgcc` | headers, or nothing | `libgcc-no-libc` | the libc |
|
||||
| `gccWithLibcAndBasicLibgcc` | real | `libgcc-no-libc` | `libgcc-libc` |
|
||||
| `gccWithLibc` / `gcc` | real | `libgcc-libc` | everything else |
|
||||
|
||||
`libgcc` resolves to `libgcc-libc` wherever a libc exists; only those first three stages ever see `libgcc-no-libc`.
|
||||
The bootstrap one is single-threaded and compiled against the libc's headers at best, so it is not intended for use beyond building the libc.
|
||||
|
||||
Nothing is passed down to say which stage is which.
|
||||
It follows from the compiler: each package reads `stdenv.cc.libc` and needs no flag of its own.
|
||||
That is also how the two `libgcc`s differ — same expression, different `stdenv`.
|
||||
|
||||
## Where the pre-libc stage is written down
|
||||
|
||||
`binutilsNoLibc` carries `preLibcHeaders` as its `libc`: the header-only stand-in for platforms that have one, and nothing at all for platforms that do not.
|
||||
`wrapCCWith` defaults `libc` to `bintools.libc`, so the bootstrap compilers inherit it, and everything built with them reads `stdenv.cc.libc`.
|
||||
|
||||
Setting a sysroot as well is unusual for nixpkgs, since headers normally reach a compiler through the wrapper, as they do here.
|
||||
It is needed because `gcc/configure` takes `target_header_dir` from `--with-sysroot`, and `target_header_dir` is what decides `inhibit_libc`.
|
||||
A libgcc built with `inhibit_libc` still compiles, links and installs, just with pieces silently missing.
|
||||
|
||||
Given that, the sysroot is derived from `stdenv.cc.libc` too, so it cannot disagree with the headers.
|
||||
|
||||
## Threading
|
||||
|
||||
Which threading model is available is a property of the libc, so the libc declares it as `passthru.threadModel`; `libgcc` reads it from there, and `libstdcxx` takes both the model and the generated `gthr-default.h` from `libgcc`.
|
||||
|
||||
Reading it from the compiler instead, with `$CC -v | sed -n 's/^Thread model: //p'`, reports the wrong component: in this set the compiler is configured separately from libgcc, so the two can disagree.
|
||||
A platform whose libc declares nothing gets `single`.
|
||||
|
||||
## Relationship to the monolithic set
|
||||
|
||||
Both are packaged from the same sources and, for now, the same version: `gccNGPackages` tracks `default-gcc-version` with no fallback, so bumping the monolithic default past what is packaged here is an evaluation error rather than a silent version skew.
|
||||
|
||||
Nothing selects GGN NG yet by default.
|
||||
The plan is for very exotic package sets to switch to this first.
|
||||
The main tier-1 native Linux package sets cached on `cache.nixos.org` will come later.
|
||||
|
||||
@@ -131,6 +131,7 @@ makeScopeWithSplicing' {
|
||||
"-B${targetGccPackages.libssp}/lib"
|
||||
"-B${targetGccPackages.libatomic}/lib"
|
||||
"-B${targetGccPackages.libgomp}/lib"
|
||||
"-B${targetGccPackages.libstdcxx}/lib"
|
||||
"-B${targetGccPackages.libgfortran}/lib/"
|
||||
];
|
||||
};
|
||||
@@ -163,10 +164,20 @@ makeScopeWithSplicing' {
|
||||
"-B${targetGccPackages.libssp}/lib"
|
||||
"-B${targetGccPackages.libatomic}/lib"
|
||||
"-B${targetGccPackages.libgomp}/lib"
|
||||
# `libcxx` above tells cc-wrapper where the C++ *headers* are; it does
|
||||
# not put the library itself on the link path for a GNU compiler. So
|
||||
# every C++ link failed with `cannot find -lstdc++` until this was
|
||||
# added, in the same style as the other runtime libraries.
|
||||
"-B${targetGccPackages.libstdcxx}/lib"
|
||||
"-I${targetGccPackages.libgomp}/lib/gcc/${metadata.release_version}/include"
|
||||
];
|
||||
};
|
||||
|
||||
# Stage 1 of the bootstrap chain; see ../README.md.
|
||||
#
|
||||
# No `libc` is passed: `wrapCCWith` defaults it to `bintools.libc`, and
|
||||
# `binutilsNoLibc` carries `preLibcHeaders`. That is the only place the
|
||||
# pre-libc stage is written down.
|
||||
gccNoLibgcc = wrapCCWith {
|
||||
cc = gccPackages.gcc-unwrapped;
|
||||
libcxx = null;
|
||||
@@ -177,10 +188,51 @@ makeScopeWithSplicing' {
|
||||
];
|
||||
};
|
||||
|
||||
libgcc = callPackage ./libgcc {
|
||||
# Built before there is a libc, and not intended for use beyond getting
|
||||
# one built. Note the two differ only by `stdenv`: which stage this is
|
||||
# follows from the compiler, never from an argument.
|
||||
libgcc-no-libc = callPackage ./libgcc {
|
||||
stdenv = overrideCC stdenv buildGccPackages.gccNoLibgcc;
|
||||
};
|
||||
|
||||
# The real one, built against the finished libc, so it can use that
|
||||
# libc's threads. This is what everything above the libc gets.
|
||||
libgcc-libc = callPackage ./libgcc {
|
||||
stdenv = overrideCC stdenv buildGccPackages.gccWithLibcAndBasicLibgcc;
|
||||
};
|
||||
|
||||
libgcc =
|
||||
if stdenv.hostPlatform.libc == null then gccPackages.libgcc-no-libc else gccPackages.libgcc-libc;
|
||||
|
||||
# Stage 2: libgcc available, libc not yet — what compiling a libc needs.
|
||||
# `binutilsNoLibc` is what keeps the libc out, so nothing here refers to
|
||||
# a libc derivation and the cycle stays broken.
|
||||
gccWithLibgcc = wrapCCWith {
|
||||
cc = gccPackages.gcc-unwrapped;
|
||||
libcxx = null;
|
||||
bintools = binutilsNoLibc;
|
||||
extraPackages = [
|
||||
targetGccPackages.libgcc-no-libc
|
||||
];
|
||||
nixSupport.cc-cflags = [
|
||||
"-B${targetGccPackages.libgcc-no-libc}/lib"
|
||||
];
|
||||
};
|
||||
|
||||
# Stage 3: real libc, bootstrap libgcc still. The finished libgcc is what
|
||||
# this is about to build.
|
||||
gccWithLibcAndBasicLibgcc = wrapCCWith {
|
||||
cc = gccPackages.gcc-unwrapped;
|
||||
libcxx = null;
|
||||
bintools = binutils;
|
||||
extraPackages = [
|
||||
targetGccPackages.libgcc-no-libc
|
||||
];
|
||||
nixSupport.cc-cflags = [
|
||||
"-B${targetGccPackages.libgcc-no-libc}/lib"
|
||||
];
|
||||
};
|
||||
|
||||
gccWithLibc = wrapCCWith {
|
||||
cc = gccPackages.gcc-unwrapped;
|
||||
libcxx = null;
|
||||
|
||||
@@ -27,11 +27,18 @@
|
||||
texinfo,
|
||||
which,
|
||||
gettext,
|
||||
flex,
|
||||
bison,
|
||||
# Whether `monorepoSrc` is a VCS checkout rather than a release tarball. A
|
||||
# checkout lacks the generated sources (gengtype-lex.cc and friends) that a
|
||||
# tarball ships pre-built, so they have to be regenerated with flex and bison.
|
||||
fromVCS ? false,
|
||||
getVersionFile,
|
||||
buildGccPackages,
|
||||
targetPackages,
|
||||
libc,
|
||||
bintools,
|
||||
# Build the shared runtime libraries, and so have the driver's specs emit
|
||||
# `-lgcc_s`. Derived the way the monolithic build derives it.
|
||||
enableTargetShared ? stdenv.targetPlatform.hasSharedLibraries,
|
||||
}:
|
||||
let
|
||||
inherit (stdenv) targetPlatform hostPlatform;
|
||||
@@ -81,6 +88,36 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
hash = "sha256-54/HzM+aeWq8CTkQu8Pualqc/LgRLS0+8EY8uPUsD+s=";
|
||||
})
|
||||
|
||||
# Not upstream yet; a follow-up to the series above (drop the `/raw` to
|
||||
# read them). They extend that series' `<target>-as` preference to `PATH`,
|
||||
# where we put the cross toolchain, so a cross compiler finds its tools
|
||||
# the way a native one does. See below for the problems `--with-as` and
|
||||
# `--with-ld` cause, and thus why we want to avoid them.
|
||||
(fetchpatch {
|
||||
name = "driver-factor-out-env-path-parsing.patch";
|
||||
url = "https://inbox.sourceware.org/gcc-patches/20260810065714.2215299-1-git@JohnEricson.me/raw";
|
||||
hash = "sha256-2qUUMWuyxX4mVaBPeNnHIiMl/aN7ejWM5stTSFWxD7g=";
|
||||
})
|
||||
(fetchpatch {
|
||||
name = "driver-search-PATH-ourselves.patch";
|
||||
url = "https://inbox.sourceware.org/gcc-patches/20260810065714.2215299-2-git@JohnEricson.me/raw";
|
||||
# The posted patch is against trunk, which spells this cast with the C++
|
||||
# operator. GCC 15 still uses the CONST_CAST macro, and the line is
|
||||
# context rather than a change, so it cannot fuzz-match. Rewrite it
|
||||
# here rather than keeping a forked copy of the whole patch.
|
||||
postFetch = ''
|
||||
substituteInPlace "$out" \
|
||||
--replace-fail 'string, const_cast<char **> (commands[i].argv),' \
|
||||
'string, CONST_CAST (char **, commands[i].argv),'
|
||||
'';
|
||||
hash = "sha256-uD8xJxQus2qyNgNDN/63WnURNuUJFDkhaXPph7g/DIk=";
|
||||
})
|
||||
(fetchpatch {
|
||||
name = "driver-search-PATH-machine-prefix.patch";
|
||||
url = "https://inbox.sourceware.org/gcc-patches/20260810065714.2215299-3-git@JohnEricson.me/raw";
|
||||
hash = "sha256-Q5CJpJKD11kadIKselQdHgNe26GqojpyAAmlAyHnsB0=";
|
||||
})
|
||||
|
||||
(getVersionFile "gcc/fix-collect2-paths.diff")
|
||||
];
|
||||
|
||||
@@ -93,12 +130,39 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
strictDeps = true;
|
||||
|
||||
depsBuildBuild = [ buildPackages.stdenv.cc ];
|
||||
|
||||
# The target assembler and linker have to be *runnable here*, during
|
||||
# configure. GCC probes them for capabilities, and a probe it cannot run is
|
||||
# not an error -- it silently records "no". Without the target `ld` on
|
||||
# `PATH`, every `gcc_cv_ld_*` probe fails that way, and the two that matter
|
||||
# most are `HAVE_GAS_HIDDEN` (which needs `gcc_cv_as_hidden` *and*
|
||||
# `gcc_cv_ld_hidden`) and `HAVE_LD_EH_FRAME_HDR`.
|
||||
#
|
||||
# Losing `HAVE_GAS_HIDDEN` is the nasty one: `-fvisibility=hidden` degrades
|
||||
# into a no-op that merely warns, so every symbol stays preemptible and GCC's
|
||||
# own same-translation-unit `R_X86_64_PC32` references become invalid when
|
||||
# linking a shared library.
|
||||
#
|
||||
# The *unwrapped* bintools: `as` and `ld` proper carry no target-libc
|
||||
# reference, so the decoupling this package set exists for still holds.
|
||||
#
|
||||
# Note this is `PATH` rather than `--with-as`/`--with-ld` on purpose. We want
|
||||
# configure to *ask* the real tools what they support, and we want it to bake
|
||||
# nothing else: those flags record `DEFAULT_ASSEMBLER`/`DEFAULT_LINKER` as
|
||||
# absolute store paths, and the driver then runs exactly those binaries
|
||||
# instead of the wrapped ones it is meant to defer to.
|
||||
depsBuildTarget = [ (bintools.bintools or bintools) ];
|
||||
|
||||
nativeBuildInputs = [
|
||||
texinfo
|
||||
which
|
||||
gettext
|
||||
]
|
||||
++ lib.optional (perl != null) perl;
|
||||
++ lib.optional (perl != null) perl
|
||||
++ lib.optionals fromVCS [
|
||||
flex
|
||||
bison
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
gmp
|
||||
@@ -197,7 +261,11 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
"--disable-install-libiberty"
|
||||
"--disable-multilib"
|
||||
"--disable-nls"
|
||||
"--disable-shared"
|
||||
# Derived rather than forced off: the driver's specs only emit `-lgcc_s`
|
||||
# for a target that has shared libraries, so hardcoding this leaves every
|
||||
# throwing C++ program unlinkable even though `libgcc_s.so` is built and
|
||||
# findable. Same predicate the monolithic build uses.
|
||||
(lib.enableFeature enableTargetShared "shared")
|
||||
"--enable-default-pie"
|
||||
"--enable-languages=${
|
||||
lib.concatStrings (
|
||||
@@ -218,12 +286,26 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
"--without-headers"
|
||||
"--with-gnu-as"
|
||||
"--with-gnu-ld"
|
||||
"--with-as=${lib.getExe' bintools "${bintools.targetPrefix}as"}"
|
||||
# Deliberately no `--with-as` / `--with-ld`. Those bake
|
||||
# `DEFAULT_ASSEMBLER` and `DEFAULT_LINKER` -- absolute store paths -- into
|
||||
# the compiler, so the driver runs exactly those binaries and stops
|
||||
# deferring to the wrapped tools it is meant to use.
|
||||
#
|
||||
# Nothing has to be baked. At configure time the tools are on `PATH` via
|
||||
# `depsBuildTarget`, which is what the capability probes need; at use time
|
||||
# the driver finds them on `PATH` under their target-prefixed names, via
|
||||
# the `find_a_program` patches above.
|
||||
"--with-system-zlib"
|
||||
"--without-included-gettext"
|
||||
"--enable-linker-build-id"
|
||||
"--with-sysroot=${lib.getDev (targetPackages.libc or libc)}"
|
||||
"--with-native-system-header-dir=/include"
|
||||
# Deliberately *no* `--with-sysroot` / `--with-native-system-header-dir`
|
||||
# pointing at the target libc. Baking a libc store path into the compiler
|
||||
# makes every libc change rebuild the compiler, which is precisely the
|
||||
# coupling this split package set exists to remove. cc-wrapper already
|
||||
# supplies the target libc (`-idirafter <libc.dev>/include` and the
|
||||
# corresponding `-B`/`-L` flags), so the compiler proper does not need to
|
||||
# know about it -- exactly as in the LLVM package set, where `clang`
|
||||
# likewise carries no libc reference (`--without-headers` above).
|
||||
]
|
||||
++ lib.optionals enablePlugin [
|
||||
"--enable-plugin"
|
||||
@@ -236,6 +318,20 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
"--with-multilib-list="
|
||||
];
|
||||
|
||||
# `LIMITS_H_TEST` decides whether gcc's generated `syslimits.h` chains to the
|
||||
# target libc's `limits.h` (`#include_next`) or is emitted self-contained. It
|
||||
# defaults to a `[ -f $(BUILD_SYSTEM_HEADER_DIR)/limits.h ]` probe, which
|
||||
# necessarily fails here: we deliberately do not point the compiler at a
|
||||
# sysroot (see `configureFlags`), so there is no libc for it to find at build
|
||||
# time.
|
||||
#
|
||||
# Self-contained is the wrong answer regardless. Every target in this package
|
||||
# set is hosted, and cc-wrapper always supplies a libc, so the chained header
|
||||
# is what resolves correctly at *use* time. Without it, anything the libc's
|
||||
# `limits.h` defines and gcc's does not -- `PATH_MAX` being the common one --
|
||||
# goes missing from every libgcc source that needs it.
|
||||
makeFlags = [ "LIMITS_H_TEST=true" ];
|
||||
|
||||
doCheck = false;
|
||||
|
||||
postInstall = ''
|
||||
|
||||
@@ -14,29 +14,34 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libatomic";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libatomic-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libatomic-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r libatomic "$out"
|
||||
cp -r libatomic "$out"
|
||||
|
||||
cp -r config "$out"
|
||||
cp -r multilib.am "$out"
|
||||
cp -r libtool.m4 "$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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
patches = [
|
||||
(fetchpatch {
|
||||
|
||||
@@ -11,28 +11,33 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libbacktrace";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libbacktrace-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libbacktrace-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r include "$out"
|
||||
cp -r libbacktrace "$out"
|
||||
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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
|
||||
@@ -12,9 +12,37 @@
|
||||
buildPackages,
|
||||
which,
|
||||
python3,
|
||||
# Build `libgcc_s` as well as `libgcc.a`, deriving it the way the monolithic
|
||||
# build does rather than forcing it off.
|
||||
enableShared ? stdenv.hostPlatform.hasSharedLibraries,
|
||||
}:
|
||||
let
|
||||
# A libc needs libgcc to build, and a libgcc that can use the libc's threads
|
||||
# needs the libc, so this package is instantiated twice — see
|
||||
# `libgcc-no-libc` and `libgcc-libc` in the package set, the same split the
|
||||
# LLVM package set makes with `compiler-rt-no-libc` and `compiler-rt-libc`.
|
||||
#
|
||||
# Nothing here says which of the two it is. The difference is entirely in the
|
||||
# compiler it is handed: the bootstrap wrapper's `libc` is `preLibcHeaders`
|
||||
# (or nothing at all, on platforms without one), the later wrapper's is the
|
||||
# finished libc. Everything below reads that one value.
|
||||
libc = stdenv.cc.libc or null;
|
||||
|
||||
# Which threading model may be used is decided by the libc, so take it from
|
||||
# there rather than guess — and pass it on in `passthru` so that `libstdcxx`,
|
||||
# which has to agree, reads the same answer instead of probing for its own.
|
||||
#
|
||||
# This is what makes the bootstrap build single-threaded without being told
|
||||
# to be: a headers-only package declares no `threadModel`, and a real libc
|
||||
# does. That build exists only to get the libc built and is thrown away
|
||||
# afterwards, so there is nothing to be gained from threading it, and plenty
|
||||
# to go wrong: `gthr-posix.h` includes `<pthread.h>` unconditionally, which
|
||||
# at that point is either absent or a stand-in for a libc that does not exist
|
||||
# yet.
|
||||
threadModel = if libc == null then "single" else libc.threadModel or "single";
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libgcc";
|
||||
pname = "libgcc" + lib.optionalString (libc == null) "-no-libc";
|
||||
inherit version;
|
||||
|
||||
src = monorepoSrc;
|
||||
@@ -83,9 +111,37 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
buildRoot=$(readlink -e "./build")
|
||||
'';
|
||||
|
||||
postPatch = ''
|
||||
sourceRoot=$(readlink -e "./libgcc")
|
||||
'';
|
||||
postPatch =
|
||||
# `SHLIB_LC` defaults to `-lc`, so the `libgcc_s.so` rule cannot link
|
||||
# before libc exists. The monolithic build clobbers it for exactly this
|
||||
# reason; do the same rather than giving up on shared libgcc. Runs while
|
||||
# the working directory is still the monorepo root, before `sourceRoot`
|
||||
# is repointed below.
|
||||
lib.optionalString enableShared (
|
||||
import ../../../common/libgcc-buildstuff.nix { inherit lib stdenv; }
|
||||
)
|
||||
# gcc's installed `limits.h` chains to the target libc's with
|
||||
# `#include_next`. Where the compiler has a libc — headers-only or real —
|
||||
# that resolves, and it has to: some targets build libgcc sources that need
|
||||
# what only the libc header defines. Where it does not, the chain has
|
||||
# nowhere to land, and
|
||||
# even configure's `AC_PROG_CPP` probe fails -- it includes `<limits.h>`
|
||||
# precisely because that "exists even on freestanding compilers" -- after
|
||||
# which configure falls back to `/lib/cpp` and reports that as the error.
|
||||
#
|
||||
# Only in that case, put gcc's own `glimits.h` earlier on the include path
|
||||
# for this build. That is the self-contained variant, the same file gcc
|
||||
# installs when configured against no libc, so nothing is invented here.
|
||||
# The compiler keeps shipping the chained header either way, which is what
|
||||
# has to stay correct for everything compiled against a real libc later.
|
||||
+ lib.optionalString (libc == null) ''
|
||||
mkdir -p "$NIX_BUILD_TOP/freestanding-include"
|
||||
cp gcc/glimits.h "$NIX_BUILD_TOP/freestanding-include/limits.h"
|
||||
export NIX_CFLAGS_COMPILE="-isystem $NIX_BUILD_TOP/freestanding-include ''${NIX_CFLAGS_COMPILE-}"
|
||||
''
|
||||
+ ''
|
||||
sourceRoot=$(readlink -e "./libgcc")
|
||||
'';
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
@@ -100,6 +156,35 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
cd "$buildRoot/gcc"
|
||||
|
||||
(
|
||||
''
|
||||
# `AS`, `CC`, `CPP` and `LD` still name the *target* tools at this point,
|
||||
# under their machine-prefixed names. Snapshot them before the
|
||||
# `*_FOR_BUILD` assignments below overwrite them.
|
||||
#
|
||||
# Deriving `AS_FOR_TARGET` from `$AS` *after* `AS=$AS_FOR_BUILD` asked for
|
||||
# the basename of the build assembler -- plain `as` -- inside the target
|
||||
# compiler's `bin`, and a cross wrapper installs only prefixed names, so
|
||||
# the path did not exist. Likewise `ld`.
|
||||
#
|
||||
# That is not an error `gcc/configure` reports. It probes the target
|
||||
# assembler and linker for capabilities, and a probe it cannot run simply
|
||||
# records "no"; with neither tool found, *every* `gcc_cv_as_*`/`gcc_cv_ld_*`
|
||||
# answer came back "no". The one that matters here is
|
||||
# `HAVE_LD_EH_FRAME_HDR`: `unwind-dw2-fde-dip.c` gates `USE_PT_GNU_EH_FRAME`
|
||||
# on it, so without it the unwinder is compiled with no `dl_iterate_phdr`
|
||||
# lookup at all -- only the `__register_frame` registry, which nothing
|
||||
# populates for normally linked objects. libgcc and libstdc++ then build,
|
||||
# link and install perfectly cleanly, and every C++ `throw` finds no FDE
|
||||
# and calls `std::terminate`.
|
||||
#
|
||||
# `CPP` in particular is not always exported, so fall back to the
|
||||
# machine-prefixed name the wrappers install.
|
||||
+ ''
|
||||
targetAs=$(basename "''${AS:-${stdenv.hostPlatform.config}-as}")
|
||||
targetCc=$(basename "''${CC:-${stdenv.hostPlatform.config}-cc}")
|
||||
targetCpp=$(basename "''${CPP:-${stdenv.hostPlatform.config}-cpp}")
|
||||
targetLd=$(basename "''${LD:-${stdenv.hostPlatform.config}-ld}")
|
||||
|
||||
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)"}
|
||||
@@ -112,10 +197,10 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
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 AS_FOR_TARGET=${lib.getExe' stdenv.cc "$targetAs"}
|
||||
export CC_FOR_TARGET=${lib.getExe' stdenv.cc "$targetCc"}
|
||||
export CPP_FOR_TARGET=${lib.getExe' stdenv.cc "$targetCpp"}
|
||||
export LD_FOR_TARGET=${lib.getExe' stdenv.cc.bintools "$targetLd"}
|
||||
|
||||
export NIX_CFLAGS_COMPILE_FOR_BUILD+=' -DGENERATOR_FILE=1'
|
||||
|
||||
@@ -184,6 +269,21 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
"--with-system-zlib"
|
||||
]
|
||||
# `gcc/configure` sets `inhibit_libc=true` when host != target and
|
||||
# `$target_header_dir/stdio.h` does not exist. `inhibit_libc` makes
|
||||
# `tsystem.h` skip <unistd.h> and friends, which is fine for the generic
|
||||
# sources but breaks the target-specific ones that genuinely need libc
|
||||
# declarations -- the profiling support files are the usual casualty.
|
||||
#
|
||||
# `target_header_dir` is derived from `--with-sysroot`, *not* from
|
||||
# `--with-headers`, so the sysroot pair is what has to be set. Point it at
|
||||
# whichever libc the compiler carries, which in the bootstrap build is the
|
||||
# headers-only one. This affects only the `gcc/configure` run that generates
|
||||
# libgcc's makefile fragments, not the compiler that gets shipped.
|
||||
++ lib.optionals (libc != null) [
|
||||
"--with-sysroot=${lib.getDev libc}"
|
||||
"--with-native-system-header-dir=/include"
|
||||
]
|
||||
++
|
||||
lib.optional (!stdenv.hostPlatform.isRiscV)
|
||||
# RISC-V does not like it being empty
|
||||
@@ -202,13 +302,14 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
configureFlags = [
|
||||
"--disable-dependency-tracking"
|
||||
"gcc_cv_target_thread_file=single"
|
||||
"gcc_cv_target_thread_file=${threadModel}"
|
||||
# $CC cannot link binaries, let alone run then
|
||||
"cross_compiling=true"
|
||||
# Do not have dynamic linker without libc
|
||||
"--enable-static"
|
||||
"--disable-shared"
|
||||
];
|
||||
]
|
||||
# `libgcc_s` needs no libc: it comes out with an empty `DT_NEEDED`, which is
|
||||
# why the monolithic build ships one even from its nolibc stage.
|
||||
++ lib.optional (!enableShared) "--disable-shared";
|
||||
|
||||
# Set the variable back the way it was, see corresponding code in
|
||||
# `preConfigure`.
|
||||
@@ -226,6 +327,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
passthru = {
|
||||
isGNU = true;
|
||||
inherit threadModel;
|
||||
};
|
||||
|
||||
meta = gcc_meta // {
|
||||
|
||||
@@ -13,30 +13,35 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libgomp";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libgomp-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libgomp-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r libgomp "$out"
|
||||
cp -r include "$out"
|
||||
cp -r libgomp "$out"
|
||||
cp -r include "$out"
|
||||
|
||||
cp -r config "$out"
|
||||
cp -r multilib.am "$out"
|
||||
cp -r libtool.m4 "$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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
|
||||
@@ -11,26 +11,31 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libiberty";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libiberty-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libiberty-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r include "$out"
|
||||
cp -r libiberty "$out"
|
||||
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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
|
||||
@@ -11,25 +11,30 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libquadmath";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libquadmath-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libquadmath-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r libquadmath "$out"
|
||||
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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
sourceRoot = "${finalAttrs.src.name}/libquadmath";
|
||||
|
||||
|
||||
@@ -12,25 +12,30 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libsanitizer";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libsanitizer-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libsanitizer-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r libsanitizer "$out"
|
||||
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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
sourceRoot = "${finalAttrs.src.name}/libsanitizer";
|
||||
|
||||
|
||||
@@ -14,28 +14,33 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libssp";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libssp-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
src = runCommand "libssp-src-${version}" { src = monorepoSrc; } (
|
||||
''
|
||||
runPhase unpackPhase
|
||||
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
mkdir -p "$out/gcc"
|
||||
cp gcc/BASE-VER "$out/gcc"
|
||||
cp gcc/DATESTAMP "$out/gcc"
|
||||
|
||||
cp -r libssp "$out"
|
||||
cp -r libssp "$out"
|
||||
|
||||
cp -r config "$out"
|
||||
cp -r multilib.am "$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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
|
||||
@@ -10,41 +10,55 @@
|
||||
autoreconfHook269,
|
||||
runCommand,
|
||||
gettext,
|
||||
libgcc,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "libstdcxx";
|
||||
inherit version;
|
||||
|
||||
src = runCommand "libstdcxx-src-${version}" { src = monorepoSrc; } ''
|
||||
runPhase unpackPhase
|
||||
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/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"
|
||||
mkdir -p "$out/libgcc"
|
||||
cp libgcc/gthr*.h "$out/libgcc"
|
||||
cp libgcc/unwind-pe.h "$out/libgcc"
|
||||
|
||||
cp -r libstdc++-v3 "$out"
|
||||
cp -r libstdc++-v3 "$out"
|
||||
|
||||
cp -r libiberty "$out"
|
||||
cp -r include "$out"
|
||||
cp -r contrib "$out"
|
||||
cp -r libiberty "$out"
|
||||
cp -r include "$out"
|
||||
cp -r contrib "$out"
|
||||
|
||||
cp -r config "$out"
|
||||
cp -r multilib.am "$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"
|
||||
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"
|
||||
'';
|
||||
''
|
||||
# `src/Makefile` runs this to compute `LTLDFLAGS`, reaching out of the
|
||||
# subdirectory for it as `$(top_srcdir)/../libtool-ldflags`. Missing, the
|
||||
# shell says "No such file or directory" and `LTLDFLAGS` silently comes out
|
||||
# empty, dropping our `LDFLAGS` from every library link.
|
||||
+ ''
|
||||
cp libtool-ldflags "$out"
|
||||
|
||||
''
|
||||
# `MD5SUMS` exists only in release tarballs, not in a VCS checkout.
|
||||
+ ''
|
||||
if [[ -f MD5SUMS ]]; then cp MD5SUMS "$out"; fi
|
||||
''
|
||||
);
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
@@ -85,6 +99,59 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
cd "$buildRoot"
|
||||
configureScript=$sourceRoot/configure
|
||||
chmod +x "$configureScript"
|
||||
|
||||
''
|
||||
# Build libstdc++ with the *C* driver, not `g++`. `g++` implies `-lstdc++`,
|
||||
# which cannot be satisfied while building the very library that provides
|
||||
# it, and the link fails with `cannot find -lstdc++`.
|
||||
#
|
||||
# This is not our invention; it is what a monolithic build does, and
|
||||
# `libstdc++-v3/src/Makefile.am` says so where it defines `CXXLINK`:
|
||||
#
|
||||
# We cannot allow g++ to be used since this would add -lstdc++ to the
|
||||
# link line which of course is problematic at this point. So, we get
|
||||
# the top-level directory to configure libstdc++-v3 to use gcc as the
|
||||
# C++ compilation driver.
|
||||
#
|
||||
# The top level does that through `RAW_CXX_FOR_TARGET`, which is `xgcc`
|
||||
# -- not `xg++` -- plus `-shared-libgcc` and `-nostdinc++`. Building
|
||||
# standalone there is no top level to arrange it, so arrange it here. The
|
||||
# C driver still compiles `.cc` as C++ by extension; what it drops is the
|
||||
# implicit `-lstdc++`. `-shared-libgcc` puts back the linkage `g++` would
|
||||
# have chosen, which the C driver does not default to, and `-nostdinc++`
|
||||
# keeps any already-installed C++ headers out of a build whose whole
|
||||
# purpose is to produce them.
|
||||
+ ''
|
||||
cxxForLibstdcxx="$CC -shared-libgcc -nostdinc++"
|
||||
|
||||
''
|
||||
# Put libgcc's `gthr-default.h` where libstdc++ expects to find it.
|
||||
#
|
||||
# It is not a source file. In a monolithic build libgcc's Makefile creates
|
||||
# it by copying whichever `gthr-<model>.h` matches the target's thread
|
||||
# model, and libstdc++ -- configured inside that same build tree -- picks
|
||||
# it up. Standalone there is no such tree, so take the one `libgcc`
|
||||
# installed. The two implement a single threading model between them, and
|
||||
# copying libgcc's own answer is what makes them agree by construction
|
||||
# rather than by two independent guesses that can drift apart. `libgcc`
|
||||
# decided it from the libc; `gcc_cv_target_thread_file` below repeats the
|
||||
# same value.
|
||||
#
|
||||
# The consequence of getting this wrong is worth spelling out, because the
|
||||
# installed headers do not show it. `GLIBCXX_CHECK_GTHREADS` compiles
|
||||
# `#include "gthr.h"` and requires `__GTHREADS_CXX0X`, which
|
||||
# `gthr-posix.h` defines unconditionally. With no posix `gthr-default.h`
|
||||
# on the include path that test fails, configure concludes there are no
|
||||
# gthreads, and `_GLIBCXX_HAS_GTHREADS` is left undefined in
|
||||
# `c++config.h` -- so `<mutex>` compiles away and `std::mutex` does not
|
||||
# exist. Stating the intent with `--enable-threads=posix` does not help:
|
||||
# the probe overrides intent with an empirical answer, so the header has
|
||||
# to actually be there.
|
||||
+ ''
|
||||
cp ${lib.getDev libgcc}/include/gthr-default.h "$sourceRoot/../libgcc/gthr-default.h"
|
||||
|
||||
export CXX="$cxxForLibstdcxx"
|
||||
echo "libstdcxx: building with CXX=$CXX"
|
||||
'';
|
||||
|
||||
configurePlatforms = [
|
||||
@@ -94,11 +161,19 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
configureFlags = [
|
||||
"--disable-dependency-tracking"
|
||||
"gcc_cv_target_thread_file=posix"
|
||||
# The same answer `libgcc` used, and the model of the `gthr-default.h`
|
||||
# copied in above. A mismatch here is silent: the unwinder's locks vanish
|
||||
# while `libstdc++` still hands out `std::thread`.
|
||||
"gcc_cv_target_thread_file=${libgcc.threadModel}"
|
||||
"cross_compiling=true"
|
||||
"--disable-multilib"
|
||||
|
||||
"--enable-clocale=gnu"
|
||||
# `gnu` is the glibc locale model: `config/locale/gnu/ctype_members.cc`
|
||||
# reads `__ctype_b`, which only glibc has. Forcing it everywhere breaks any
|
||||
# other libc -- on musl the build fails converting `const unsigned short *`
|
||||
# to `const ctype_base::mask *`. Configure picks the right model from the
|
||||
# host triple on its own, as it does for the monolithic build, which passes
|
||||
# no `--enable-clocale` at all.
|
||||
"--disable-libstdcxx-pch"
|
||||
"--disable-vtable-verify"
|
||||
"--enable-libstdcxx-visibility"
|
||||
|
||||
@@ -278,6 +278,11 @@ stdenv.mkDerivation (
|
||||
passthru = {
|
||||
inherit version;
|
||||
minorRelease = version;
|
||||
|
||||
# glibc's threads are POSIX threads. `libgcc` and `libstdc++` have to be
|
||||
# configured for the same threading model as each other, so rather than
|
||||
# have each guess, they take it from the libc they are built against.
|
||||
threadModel = "posix";
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,11 @@ symlinkJoin {
|
||||
fixupPhase
|
||||
'';
|
||||
|
||||
# NetBSD's threads are POSIX threads — `libpthread` is joined in above.
|
||||
# `libgcc` and `libstdc++` have to be configured for the same threading model
|
||||
# as each other, so rather than have each guess, they take it from the libc
|
||||
# they are built against.
|
||||
passthru.threadModel = "posix";
|
||||
|
||||
meta.platforms = lib.platforms.netbsd;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,8 @@ lib.init bootStages
|
||||
buildPackages.zig.cc
|
||||
else if crossSystem.useArocc or false then
|
||||
buildPackages.arocc
|
||||
else if crossSystem.useGccNG or false then
|
||||
buildPackages.gccNGPackages.gcc
|
||||
else
|
||||
buildPackages.gcc;
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ with pkgs;
|
||||
(
|
||||
if stdenvNoCC.hostPlatform.isDarwin || stdenvNoCC.hostPlatform.useLLVM or false then
|
||||
overrideCC stdenvNoCC buildPackages.llvmPackages.clangNoCompilerRt
|
||||
else if stdenvNoCC.hostPlatform.useGccNG or false then
|
||||
overrideCC stdenvNoCC buildPackages.gccNGPackages.gccNoLibgcc
|
||||
else
|
||||
gccCrossLibcStdenv
|
||||
)
|
||||
@@ -99,6 +101,11 @@ with pkgs;
|
||||
(
|
||||
if stdenvNoCC.hostPlatform.isDarwin || stdenvNoCC.hostPlatform.useLLVM or false then
|
||||
overrideCC stdenvNoCC buildPackages.llvmPackages.clangNoLibc
|
||||
else if stdenvNoCC.hostPlatform.useGccNG or false then
|
||||
# The split package set can express the two rungs separately, the way
|
||||
# the LLVM set does: no libgcc above, libgcc but no libc here. The
|
||||
# monolithic `gccCrossLibcStdenv` has to serve both.
|
||||
overrideCC stdenvNoCC buildPackages.gccNGPackages.gccWithLibgcc
|
||||
else
|
||||
gccCrossLibcStdenv
|
||||
)
|
||||
@@ -3244,9 +3251,11 @@ with pkgs;
|
||||
# NOTE: keep this with the "NG" label until we're ready to drop the monolithic GCC
|
||||
gccNGPackagesSet = recurseIntoAttrs (callPackages ../development/compilers/gcc/ng { });
|
||||
gccNGPackages_15 = gccNGPackagesSet."15";
|
||||
gccNGPackages = gccNGPackagesSet.${toString default-gcc-version};
|
||||
mkGCCNGPackages = gccNGPackagesSet.mkPackage;
|
||||
})
|
||||
gccNGPackages_15
|
||||
gccNGPackages
|
||||
mkGCCNGPackages
|
||||
;
|
||||
|
||||
@@ -5622,11 +5631,22 @@ with pkgs;
|
||||
if stdenv.hostPlatform != stdenv.buildPlatform then
|
||||
{
|
||||
stdenv = gccCrossLibcStdenv; # doesn't compile without gcc
|
||||
libgcc = callPackage ../development/libraries/gcc/libgcc {
|
||||
gcc = gccCrossLibcStdenv.cc;
|
||||
glibc = glibc.override { libgcc = null; };
|
||||
stdenvNoLibs = gccCrossLibcStdenv;
|
||||
};
|
||||
# glibc `dlopen`s `libgcc_s.so` without consulting the usual search
|
||||
# path, so it has to name one that already exists. The monolithic
|
||||
# build gets there by building glibc twice: the inner `libgcc = null`
|
||||
# one names no libgcc at all, and is used for nothing but building the
|
||||
# libgcc the real one names. The split package set already has that
|
||||
# rung as a package of its own — `libgcc-no-libc` is what exists
|
||||
# before any libc does — so there is nothing left to open-code here.
|
||||
libgcc =
|
||||
if stdenv.hostPlatform.useGccNG or false then
|
||||
gccNGPackages.libgcc-no-libc
|
||||
else
|
||||
callPackage ../development/libraries/gcc/libgcc {
|
||||
gcc = gccCrossLibcStdenv.cc;
|
||||
glibc = glibc.override { libgcc = null; };
|
||||
stdenvNoLibs = gccCrossLibcStdenv;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user