gccNGPackages: init (#414299)

This commit is contained in:
John Ericson 2025-07-11 10:52:32 -04:00 committed by GitHub
commit 2deaafc431
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 2290 additions and 1 deletions

View File

@ -0,0 +1,137 @@
From 3af17de3a5f6acd5a2f9340d84b8667459f43eea Mon Sep 17 00:00:00 2001
From: John Ericson <git@JohnEricson.me>
Date: Wed, 18 Aug 2021 01:55:31 -0400
Subject: [PATCH 1/3] find_a_program: First search with machine prefix
This matches the behavior of Clang, and makes it easier to work with
cross compilers without heeding to hard-code paths at build time.
---
gcc/gcc.cc | 78 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 68 insertions(+), 10 deletions(-)
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 4fd87f2c4a1..55738d258b3 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -1600,6 +1600,11 @@ static const char *machine_suffix = 0;
static const char *just_machine_suffix = 0;
+/* Prefix to attach to *basename* of commands being searched.
+ This is just `MACHINE-'. */
+
+static const char *just_machine_prefix = 0;
+
/* Adjusted value of GCC_EXEC_PREFIX envvar. */
static const char *gcc_exec_prefix;
@@ -3043,15 +3048,6 @@ file_at_path (char *path, void *data)
memcpy (path + len, info->name, info->name_len);
len += info->name_len;
- /* Some systems have a suffix for executable files.
- So try appending that first. */
- if (info->suffix_len)
- {
- memcpy (path + len, info->suffix, info->suffix_len + 1);
- if (access_check (path, info->mode) == 0)
- return path;
- }
-
path[len] = '\0';
if (access_check (path, info->mode) == 0)
return path;
@@ -3091,12 +3087,52 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
file_at_path, &info);
}
+/* Callback for find_a_program. Appends the file name to the directory
+ path. Like file_at_path but tries machine prefix and exe suffix too. */
+
+static void *
+program_at_path (char *path, void *data)
+{
+ /* try first with machine-prefixed name */
+ struct file_at_path_info *info = (struct file_at_path_info *) data;
+ size_t path_len = strlen (path);
+
+ for (auto prefix : { just_machine_prefix, "" })
+ {
+ auto len = path_len;
+
+ auto prefix_len = strlen(prefix);
+ memcpy (path + len, prefix, prefix_len);
+ len += prefix_len;
+
+ memcpy (path + len, info->name, info->name_len);
+ len += info->name_len;
+
+ /* Some systems have a suffix for executable files.
+ So try appending that first. */
+ if (info->suffix_len)
+ {
+ memcpy (path + len, info->suffix, info->suffix_len + 1);
+ if (access_check (path, info->mode) == 0)
+ return path;
+ }
+
+ path[len] = '\0';
+ if (access_check (path, info->mode) == 0)
+ return path;
+ }
+
+ return NULL;
+}
+
/* Specialization of find_a_file for programs that also takes into account
configure-specified default programs. */
static char*
find_a_program (const char *name)
{
+ const int mode = X_OK;
+
/* Do not search if default matches query. */
#ifdef DEFAULT_ASSEMBLER
@@ -3114,7 +3150,28 @@ find_a_program (const char *name)
return xstrdup (DEFAULT_DSYMUTIL);
#endif
- return find_a_file (&exec_prefixes, name, X_OK, false);
+ /* Find the filename in question (special case for absolute paths). */
+
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ if (access (name, mode) == 0)
+ return xstrdup (name);
+
+ return NULL;
+ }
+
+ struct file_at_path_info info;
+
+ info.name = name;
+ info.suffix = HOST_EXECUTABLE_SUFFIX;
+ info.name_len = strlen (info.name);
+ info.suffix_len = strlen (info.suffix);
+ info.mode = mode;
+
+ return (char*) for_each_path (
+ &exec_prefixes, false,
+ info.name_len + info.suffix_len + strlen(just_machine_prefix),
+ program_at_path, &info);
}
/* Ranking of prefixes in the sort list. -B prefixes are put before
@@ -8492,6 +8549,7 @@ driver::set_up_specs () const
machine_suffix = concat (spec_host_machine, dir_separator_str, spec_version,
accel_dir_suffix, dir_separator_str, NULL);
just_machine_suffix = concat (spec_machine, dir_separator_str, NULL);
+ just_machine_prefix = concat (spec_machine, "-", NULL);
specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
/* Read the specs file unless it is a default one. */
--
2.47.2

View File

@ -0,0 +1,103 @@
From 8e1b7a128a69393c6d3f53b8f66bd52c6bbce908 Mon Sep 17 00:00:00 2001
From: John Ericson <git@JohnEricson.me>
Date: Wed, 18 Aug 2021 01:55:45 -0400
Subject: [PATCH 2/3] driver: for_each_pass: Pass to callback whether dir is
machine-disambiguated
We will use this in the subsequent diff to control what basenames we
search for. In machine-specific subdirectories, we should just look for
the original basename, but in machine-agnostic subdirectories, we might
additionally look for prefixed disambiguated names, as an alternate
method of keeping targets apart.
---
gcc/gcc.cc | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 55738d258b3..f9f83d1a804 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2783,7 +2783,7 @@ static void *
for_each_path (const struct path_prefix *paths,
bool do_multi,
size_t extra_space,
- void *(*callback) (char *, void *),
+ void *(*callback) (char *, bool, void *),
void *callback_info)
{
struct prefix_list *pl;
@@ -2844,7 +2844,7 @@ for_each_path (const struct path_prefix *paths,
if (!skip_multi_dir)
{
memcpy (path + len, multi_suffix, suffix_len + 1);
- ret = callback (path, callback_info);
+ ret = callback (path, true, callback_info);
if (ret)
break;
}
@@ -2855,7 +2855,7 @@ for_each_path (const struct path_prefix *paths,
&& pl->require_machine_suffix == 2)
{
memcpy (path + len, just_multi_suffix, just_suffix_len + 1);
- ret = callback (path, callback_info);
+ ret = callback (path, true, callback_info);
if (ret)
break;
}
@@ -2865,7 +2865,7 @@ for_each_path (const struct path_prefix *paths,
&& !pl->require_machine_suffix && multiarch_dir)
{
memcpy (path + len, multiarch_suffix, multiarch_len + 1);
- ret = callback (path, callback_info);
+ ret = callback (path, true, callback_info);
if (ret)
break;
}
@@ -2893,7 +2893,7 @@ for_each_path (const struct path_prefix *paths,
else
path[len] = '\0';
- ret = callback (path, callback_info);
+ ret = callback (path, false, callback_info);
if (ret)
break;
}
@@ -2948,7 +2948,7 @@ struct add_to_obstack_info {
};
static void *
-add_to_obstack (char *path, void *data)
+add_to_obstack (char *path, bool, void *data)
{
struct add_to_obstack_info *info = (struct add_to_obstack_info *) data;
@@ -3040,7 +3040,7 @@ struct file_at_path_info {
};
static void *
-file_at_path (char *path, void *data)
+file_at_path (char *path, bool, void *data)
{
struct file_at_path_info *info = (struct file_at_path_info *) data;
size_t len = strlen (path);
@@ -3091,7 +3091,7 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode,
path. Like file_at_path but tries machine prefix and exe suffix too. */
static void *
-program_at_path (char *path, void *data)
+program_at_path (char *path, bool machine_specific, void *data)
{
/* try first with machine-prefixed name */
struct file_at_path_info *info = (struct file_at_path_info *) data;
@@ -6074,7 +6074,7 @@ struct spec_path_info {
};
static void *
-spec_path (char *path, void *data)
+spec_path (char *path, bool, void *data)
{
struct spec_path_info *info = (struct spec_path_info *) data;
size_t len = 0;
--
2.47.2

View File

@ -0,0 +1,75 @@
From e1ee1a2df1ad32de24e8fdaeac0a533681710578 Mon Sep 17 00:00:00 2001
From: John Ericson <git@JohnEricson.me>
Date: Wed, 18 Aug 2021 01:55:52 -0400
Subject: [PATCH 3/3] find_a_program: Only search for prefixed paths in
undisambiguated dirs
This means, we might search for:
- path/$machine/$version/prog
- path/$machine/prog
- path/$machine-prog
But not
- path/$machine/$version/$machine-prog
because disambiguating $machine twice is unnecessary.
This does mean we less liberal in what we accept than LLVM, but that's
OK. The down side of always Postel's law is everyone converges on
accepting all sorts of garbage, which makes debugging end-to-end hard
when mistakes are not caught early.
---
gcc/gcc.cc | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index f9f83d1a804..d837b6ea779 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -3097,15 +3097,9 @@ program_at_path (char *path, bool machine_specific, void *data)
struct file_at_path_info *info = (struct file_at_path_info *) data;
size_t path_len = strlen (path);
- for (auto prefix : { just_machine_prefix, "" })
+ auto search = [=](size_t len) -> void *
{
- auto len = path_len;
-
- auto prefix_len = strlen(prefix);
- memcpy (path + len, prefix, prefix_len);
- len += prefix_len;
-
- memcpy (path + len, info->name, info->name_len);
+ memcpy (path + len, info->name, info->name_len + 1);
len += info->name_len;
/* Some systems have a suffix for executable files.
@@ -3120,9 +3114,22 @@ program_at_path (char *path, bool machine_specific, void *data)
path[len] = '\0';
if (access_check (path, info->mode) == 0)
return path;
+
+ return NULL;
+ };
+
+ /* Additionally search for $target-prog in machine-agnostic dirs, as an
+ additional way to disambiguate targets. Do not do this in machine-specific
+ dirs because so further disambiguation is needed. */
+ if (!machine_specific)
+ {
+ auto prefix_len = strlen(just_machine_prefix);
+ memcpy (path + path_len, just_machine_prefix, prefix_len);
+ auto res = search(path_len + prefix_len);
+ if (res) return res;
}
- return NULL;
+ return search(path_len);
}
/* Specialization of find_a_file for programs that also takes into account
--
2.47.2

View File

@ -0,0 +1,180 @@
From 1eaf7ce77bb4eb73e5565ede220557c2ef0290b0 Mon Sep 17 00:00:00 2001
From: John Ericson <git@JohnEricson.me>
Date: Sun, 22 Aug 2021 01:14:22 -0400
Subject: [PATCH] Allow explicitly specifying the thread model for runtime libs
Previously, they always scraped the thread mode from `$CC -v', now, that
is the default but one may pass `--with-threads=MODEL` to be explicit
instead.
One use-case is bootstraping with a shorter critical path. The
traditionally route was to build an entire "static stage" GCC, build
libc, and then build GCC again supporting dynamic linking,
multithreading, etc. But this is wasteful in that GCC itself is built
twice.
With this change, rather than having to mess with spec files we can just
configure the runtime libraries the way we want directly. In turn, that
opens to just building libgcc twice rather than all of GCC.
Frankly, specs were always a rather indirect approach to coordinate this
during GCC's bootstrap, since GCC itself really doesn't care what the
threading model is, just that the runtime libraries agree among
themselves. Relying on a hard-coded spec for this also keeps us one step
further from the long-term goal of multi-target GCC, for what it's
worth.
For the record, "single stage" builds of GCC have some precedent in
downstream packaging, for example with [1]. That one, as far as I can
tell, builds libgcc once, but with the headers of the libc
implementation provided and then cyclic linking down later. They are
both fine approaches, but I don't think one should have to be forced
into cyclic dependencies if they don't want to. That opens the door to
non-terminating programs due to, e.g., atomics used in a threads
implementation being lowered to threads absent hardware support.
Finally, I understand that such custom bootstrapping is not officially
supported. I don't mean to imply it should be --- a lot more cleanup
work to the build system would be necessary before supporting it
wouldn't be a huge additional maintainer burden --- I just hope to add a
reasonable knob for those comfortable with doing unsupported things
already.
[1]: https://github.com/richfelker/musl-cross-make
---
config/gthr.m4 | 32 ++++++++++++++++++++++++++++++++
libatomic/configure.ac | 4 +---
libgcc/configure.ac | 4 +---
libphobos/m4/druntime/os.m4 | 2 +-
libstdc++-v3/acinclude.m4 | 8 +++-----
5 files changed, 38 insertions(+), 12 deletions(-)
diff --git a/config/gthr.m4 b/config/gthr.m4
index 11996247f15..7aed5d3df0d 100644
--- a/config/gthr.m4
+++ b/config/gthr.m4
@@ -5,6 +5,35 @@ dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program.
+dnl Define thread model
+
+dnl usage: GCC_AC_THREAD_MODEL
+AC_DEFUN([GCC_AC_THREAD_MODEL],
+[
+# With threads
+# Pass with no value to take from compiler's metadata
+# Pass with a value to specify a thread package
+# 'single' means single threaded -- without threads.
+AC_ARG_WITH(threads,
+[AS_HELP_STRING([[--with-threads=MODEL]],
+ [specify thread model for this GCC
+ runtime library])],,
+[with_threads=''])
+
+if test x"$with_threads" = x'yes'; then
+ AC_MSG_ERROR([Cannot pass bare --with-threads, must pass explicit --with-threads=MODEL])
+elif test x"$with_threads" = x'no'; then
+ target_thread_file=single
+elif test x"$with_threads" = x''; then
+ AC_MSG_CHECKING([for thread model used by GCC])
+ target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
+ AC_MSG_RESULT([$target_thread_file])
+else
+ target_thread_file=$with_threads
+fi
+])
+
+
dnl Define header location by thread model
dnl usage: GCC_AC_THREAD_HEADER([thread_model])
@@ -23,6 +52,9 @@ case $1 in
vxworks) thread_header=config/gthr-vxworks.h ;;
win32) thread_header=config/i386/gthr-win32.h ;;
mcf) thread_header=config/i386/gthr-mcf.h ;;
+ *)
+ AC_MSG_ERROR([No known header for threading model '$1'.])
+ ;;
esac
AC_SUBST(thread_header)
])
diff --git a/libatomic/configure.ac b/libatomic/configure.ac
index 85824fa7614..691f4948f6c 100644
--- a/libatomic/configure.ac
+++ b/libatomic/configure.ac
@@ -162,9 +162,7 @@ libtool_VERSION=3:0:2
AC_SUBST(libtool_VERSION)
# Check for used threading-model
-AC_MSG_CHECKING([for thread model used by GCC])
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-AC_MSG_RESULT([$target_thread_file])
+GCC_AC_THREAD_MODEL
case "$target" in
*aarch64*)
diff --git a/libgcc/configure.ac b/libgcc/configure.ac
index 4e8c036990f..acf54e24c79 100644
--- a/libgcc/configure.ac
+++ b/libgcc/configure.ac
@@ -305,9 +305,7 @@ AC_SUBST([use_tm_clone_registry])
AC_LIB_PROG_LD_GNU
-AC_MSG_CHECKING([for thread model used by GCC])
-target_thread_file=`$CC -v 2>&1 | sed -n 's/^Thread model: //p'`
-AC_MSG_RESULT([$target_thread_file])
+GCC_AC_THREAD_MODEL
# Check for assembler CFI support.
AC_CACHE_CHECK([whether assembler supports CFI directives], [libgcc_cv_cfi],
diff --git a/libphobos/m4/druntime/os.m4 b/libphobos/m4/druntime/os.m4
index 15cde3b04b8..28bd4d3d2bd 100644
--- a/libphobos/m4/druntime/os.m4
+++ b/libphobos/m4/druntime/os.m4
@@ -32,7 +32,7 @@ case $1 in
# TODO: These targets need porting.
dce|mipssde|rtems|tpf|vxworks)
DCFG_THREAD_MODEL="Single" ;;
- *) as_fn_error "Thread implementation '$1' not recognised" "$LINENO" 5 ;;
+ *) AC_MSG_ERROR([Thread implementation '$1' not recognised]) ;;
esac
AC_SUBST(DCFG_THREAD_MODEL)
])
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 51a08bcc8b1..71697f59d6d 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4342,9 +4342,7 @@ dnl Substs:
dnl thread_header
dnl
AC_DEFUN([GLIBCXX_ENABLE_THREADS], [
- AC_MSG_CHECKING([for thread model used by GCC])
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
- AC_MSG_RESULT([$target_thread_file])
+ GCC_AC_THREAD_MODEL
GCC_AC_THREAD_HEADER([$target_thread_file])
])
@@ -4354,7 +4352,8 @@ dnl Check if gthread implementation defines the types and functions
dnl required by the c++0x thread library. Conforming gthread
dnl implementations can define __GTHREADS_CXX0X to enable use with c++0x.
dnl
-dnl GLIBCXX_ENABLE_SYMVERS must be done before this.
+dnl GLIBCXX_ENABLE_SYMVERS and GLIBCXX_ENABLE_THREADS must be done
+dnl before this.
dnl
AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
GLIBCXX_ENABLE(libstdcxx-threads,auto,,[enable C++11 threads support])
@@ -4369,7 +4368,6 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
CXXFLAGS="$CXXFLAGS -fno-exceptions \
-I${toplevel_srcdir}/libgcc -I${toplevel_builddir}/libgcc"
- target_thread_file=`$CXX -v 2>&1 | sed -n 's/^Thread model: //p'`
case $target_thread_file in
posix)
CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
--
2.44.1

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,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,221 @@
{
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 =
(builtins.toString ../.)
+ "/${if (gitRelease != null) then "git" else lib.versions.major release_version}";
getVersionFile =
p:
builtins.path {
name = builtins.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 rec {
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 rec {
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 rec {
cc = gccPackages.gcc-unwrapped;
libcxx = null;
bintools = binutilsNoLibc;
extraPackages = [ ];
nixSupport.cc-cflags = [
"-nostartfiles"
];
};
libgcc = callPackage ./libgcc {
stdenv = overrideCC stdenv buildGccPackages.gccNoLibgcc;
};
gccWithLibc = wrapCCWith rec {
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 rec {
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 rec {
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;
inherit (buildGccPackages) gfortran;
};
libstdcxx = callPackage ./libstdcxx {
stdenv = overrideCC stdenv buildGccPackages.gccWithLibatomic;
};
};
}

View File

@ -0,0 +1,249 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
langAda ? false,
langC ? true,
langCC ? true,
langD ? false,
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,
libelf,
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 = [
# Submitted:
# - https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577639.html
# - https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577640.html
# - https://gcc.gnu.org/pipermail/gcc-patches/2021-August/577638.html
#
# In Git: https://github.com/Ericson2314/gcc/tree/prog-target-15
(getVersionFile "gcc/0001-find_a_program-First-search-with-machine-prefix.patch")
(getVersionFile "gcc/0002-driver-for_each_pass-Pass-to-callback-whether-dir-is.patch")
(getVersionFile "gcc/0003-find_a_program-Only-search-for-prefixed-paths-in-und.patch")
# Submitted: https://inbox.sourceware.org/gcc-patches/20210818203840.1550133-1-John.Ericson@Obsidian.Systems/T/#t
# In Git: https://github.com/Ericson2314/gcc/tree/libgcc-custom-threading-model-15
(getVersionFile "gcc/custom-threading-model.patch")
# TODO: fix up and send to upstream
(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
libelf
]
++ 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-languages=${
lib.concatStrings (
lib.intersperse "," (
lib.optional langC "c"
++ lib.optional langCC "c++"
++ lib.optional langD "d"
++ 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,48 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
autoreconfHook269,
monorepoSrc ? null,
runCommand,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libatomic";
inherit version;
src = monorepoSrc;
patches = [
(getVersionFile "gcc/custom-threading-model.patch")
];
enableParallelBuilding = true;
nativeBuildInputs = [
autoreconfHook269
];
postPatch = ''
sourceRoot=$(readlink -e "./libatomic")
'';
preConfigure = ''
mkdir ../build
cd ../build
configureScript=$sourceRoot/configure
chmod +x "$configureScript"
'';
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,205 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
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 = [
(getVersionFile "gcc/custom-threading-model.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 \
insn-modes.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"
"--with-threads=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 = ''
cp gthr-default.h "$out/lib/gcc/${stdenv.hostPlatform.config}/${version}/include"
moveToOutput "lib/gcc/${stdenv.hostPlatform.config}/${version}/include" "$dev"
mkdir -p "$out/lib" "$dev/include"
ln -s "$out/lib/gcc/${stdenv.hostPlatform.config}/${version}"/* "$out/lib"
ln -s "$dev/lib/gcc/${stdenv.hostPlatform.config}/${version}/include"/* "$dev/include/"
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@ -0,0 +1,190 @@
{
lib,
stdenv,
gfortran,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
buildPackages,
autoreconfHook269,
libiberty,
libgcc,
libbacktrace,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libgfortran";
inherit version;
src = monorepoSrc;
outputs = [
"out"
"dev"
];
strictDeps = true;
depsBuildBuild = [ buildPackages.stdenv.cc ];
nativeBuildInputs = [
autoreconfHook269
libiberty
gfortran
];
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"
"--with-threads=single"
# $CC cannot link binaries, let alone run then
"cross_compiling=true"
];
# 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 = ''
moveToOutput "lib/gcc/${stdenv.hostPlatform.config}/${version}/include" "$dev"
mkdir -p "$out/lib" "$dev/include"
ln -s "$out/lib/gcc/${stdenv.hostPlatform.config}/${version}"/* "$out/lib"
ln -s "$dev/lib/gcc/${stdenv.hostPlatform.config}/${version}/include"/* "$dev/include/"
'';
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/";
};
})

View File

@ -0,0 +1,67 @@
{
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,68 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
monorepoSrc ? null,
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 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}/libssp";
configurePlatforms = [
"build"
"host"
];
configureFlags = [
"--disable-dependency-tracking"
"--with-toolexeclibdir=${builtins.placeholder "out" + "/lib"}"
"cross_compiling=true"
"--disable-multilib"
];
preConfigure = ''
mkdir ../../build
cd ../../build
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,87 @@
{
lib,
stdenv,
gcc_meta,
release_version,
version,
getVersionFile,
monorepoSrc ? null,
runCommand,
autoreconfHook269,
gettext,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "libstdcxx";
inherit version;
src = monorepoSrc;
enableParallelBuilding = true;
nativeBuildInputs = [
autoreconfHook269
gettext
];
patches = [
(getVersionFile "gcc/custom-threading-model.patch")
];
postUnpack = ''
mkdir -p ./build
buildRoot=$(readlink -e "./build")
'';
preAutoreconf = ''
sourceRoot=$(readlink -e "./libstdc++-v3")
cd $sourceRoot
'';
postPatch = ''
sed -i \
-e 's/AM_ENABLE_MULTILIB(/AM_ENABLE_MULTILIB(NOPE/' \
-e 's#glibcxx_toolexeclibdir=no#glibcxx_toolexeclibdir=${builtins.placeholder "out"}/libexec#' \
configure.ac
'';
preConfigure = ''
cd "$buildRoot"
configureScript=$sourceRoot/configure
chmod +x "$configureScript"
'';
configureFlags = [
"--disable-dependency-tracking"
"--with-toolexeclibdir=${builtins.placeholder "out"}/lib"
"--with-threads=posix"
"cross_compiling=true"
"--disable-multilib"
"--enable-clocale=gnu"
"--disable-libstdcxx-pch"
"--disable-vtable-verify"
"--enable-libstdcxx-visibility"
"--with-default-libstdcxx-abi=new"
];
outputs = [
"out"
"dev"
];
hardeningDisable = [
# PATH_MAX
"fortify"
];
doCheck = true;
passthru = {
isGNU = true;
};
meta = gcc_meta // {
homepage = "https://gcc.gnu.org/onlinedocs/libstdc++";
description = "GNU C++ Library";
};
})

View File

@ -0,0 +1,32 @@
{
"gcc/fix-collect2-paths.diff" = [
{
after = "15";
path = ../15;
}
];
"gcc/0001-find_a_program-First-search-with-machine-prefix.patch" = [
{
after = "15";
path = ../15;
}
];
"gcc/0002-driver-for_each_pass-Pass-to-callback-whether-dir-is.patch" = [
{
after = "15";
path = ../15;
}
];
"gcc/0003-find_a_program-Only-search-for-prefixed-paths-in-und.patch" = [
{
after = "15";
path = ../15;
}
];
"gcc/custom-threading-model.patch" = [
{
after = "15";
path = ../15;
}
];
}

View File

@ -0,0 +1,69 @@
{
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

@ -5001,6 +5001,17 @@ with pkgs;
gccFun = callPackage ../development/compilers/gcc;
gcc-unwrapped = gcc.cc;
inherit
(rec {
# 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";
mkGCCNGPackages = gccNGPackagesSet.mkPackage;
})
gccNGPackages_15
mkGCCNGPackages
;
wrapNonDeterministicGcc =
stdenv: ccWrapper:
if ccWrapper.isGNU then
@ -6935,7 +6946,7 @@ with pkgs;
});
binutilsNoLibc = wrapBintoolsWith {
bintools = binutils-unwrapped;
libc = targetPackages.preLibcHeaders;
libc = targetPackages.preLibcHeaders or preLibcHeaders;
};
libbfd = callPackage ../development/tools/misc/binutils/libbfd.nix { };