[PATCH] Libraries' configure scripts should not read config-ml.in when multilib is disabled
Currently some multilib variables are initialized, and config.ml.in instantiated, whether or not a multilib build is being performed. I ran into this because I am building the runtime libraries (libatomic right now) separately from GCC. Multilib is disabled, and no multilib variables are set, yet the configure script fails after it cannot find `${multi_basedir}/config-ml.in`. I understand this building them separately is not supported, but am nevertheless hoping the patch can nevertheless be upstreamed on the grounds that this generally cleans up the build system in accordance with the principle that "feature foo" variables need not be written and should not be read when feature foo is disabled. libgcc's configure script, for example, has some similar-looking bespoke m4 script with `. ${libgcc_topdir}/config-ml.in` instead, side-stepping the issue. Perhaps with this fixed, all the libraries could use the same macro. [I suppose I'd be willing to investigate that.] Thanks, John [Continuing from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86746. Did not know this sort of thing should exclusively go to this list. My apologies.] From 3e0e7d6e5cfdc46342fcad5fe6b24b4f47af0d87 Mon Sep 17 00:00:00 2001 Message-Id: <3e0e7d6e5cfdc46342fcad5fe6b24b4f47af0d87.1532988611.git.John.Ericson@Obsidian.Systems> From: John Ericson Date: Mon, 30 Jul 2018 18:06:02 -0400 Subject: [PATCH] multilib: Don't bother with multilib configuration To: gcc-patches@gcc.gnu.org * config/multi.m4: Don't bother with multilib configuration when it is disabled. --- ChangeLog | 5 + config/multi.m4 | 50 +++-- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bc5123c84e..2445071bea4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2018-07-30 John Ericson + + * config/multi.m4: Don't bother with multilib configuration when it + is disabled. + 2018-07-19 DJ Delorie * MAINTAINERS (m32c, msp43, rl78, libiberty, build): Remove myself diff --git a/config/multi.m4 b/config/multi.m4 index bba338a8265..f5081155564 100644 --- a/config/multi.m4 +++ b/config/multi.m4 @@ -20,40 +20,45 @@ AC_ARG_ENABLE(multilib, no) multilib=no ;; *) AC_MSG_ERROR([bad value $enableval for multilib option]) ;; esac], - [multilib=yes]) +[multilib=yes]) -# We may get other options which we leave undocumented: -# --with-target-subdir, --with-multisrctop, --with-multisubdir -# See config-ml.in if you want the gory details. +if test "x$multilib" = xyes; then -if test "$srcdir" = "."; then - if test "$with_target_subdir" != "."; then -multi_basedir="$srcdir/$with_multisrctop../$2" + # We may get other options which we leave undocumented: + # --with-target-subdir, --with-multisrctop, --with-multisubdir + # See config-ml.in if you want the gory details. + + if test "$srcdir" = "."; then +if test "$with_target_subdir" != "."; then + multi_basedir="$srcdir/$with_multisrctop../$2" +else + multi_basedir="$srcdir/$with_multisrctop$2" +fi else -multi_basedir="$srcdir/$with_multisrctop$2" +multi_basedir="$srcdir/$2" + fi + AC_SUBST(multi_basedir) + + # Even if the default multilib is not a cross compilation, + # it may be that some of the other multilibs are. + if test $cross_compiling = no && test $multilib = yes \ + && test "x${with_multisubdir}" != x ; then + cross_compiling=maybe fi -else - multi_basedir="$srcdir/$2" -fi -AC_SUBST(multi_basedir) -# Even if the default multilib is not a cross compilation, -# it may be that some of the other multilibs are. -if test $cross_compiling = no && test $multilib = yes \ - && test "x${with_multisubdir}" != x ; then - cross_compiling=maybe fi -AC_OUTPUT_COMMANDS([ +AC_CONFIG_COMMANDS([config-ml], +[if test "x$multilib" = xyes; then # Only add multilib support code if we just rebuilt the top-level # Makefile. case " $CONFIG_FILES " in *" ]m4_default([$1],Makefile)[ "*) ac_file=]m4_default([$1],Makefile)[ . ${multi_basedir}/config-ml.in ;; -esac], - [ -srcdir="$srcdir" +esac +fi], +[srcdir="$srcdir" host="$host" target="$target" with_multisubdir="$with_multisubdir" @@ -64,4 +69,5 @@ multi_basedir="$multi_basedir" CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} CC="$CC" CXX="$CXX" -GFORTRAN="$GFORTRAN"])])dnl +GFORTRAN="$GFORTRAN"]) +])dnl -- 2.17.1
Re: [PATCH] Libraries' configure scripts should not read config-ml.in when multilib is disabled
On 07/30/18 19:48, Joseph Myers wrote: On the contrary, I think an important principle here is that non-multilib and multilib builds follow the same code paths as far as possible, with the multilib variables just set to trivial values (modulo osdirname) in the case of a non-multilib build - a non-multilib build should be building libraries exactly the same, with the same logic and the same variable settings, as the default multilib in a multilib build. I whole-heatedly agree with that principle. [FWIW, I've taken a similar approach with keeping the cross and native compilation code paths as close as possible. This is why I'm building the libraries separately in the first place.] That said, it is my tentative understanding that the point of having config-ml is to cordon-off all the necessarily-multilib-specific logic so it doesn't pollute everything else. When that script isn't run, I think the Makefiles already contain default "trivial values" for capitalized MULTI* variables (which are the only ones actually used by the build itself), yielding precisely that deduplication of code paths we both want. John
[PATCH] Factor out `find_a_program` helper around `find_a_file`
The helper is for `--print-prog-name` and similar things. Since all executable finding goes through it, we can move the default overrides into that path too. This also ensures that if some is looking for a *non*-program that called `as`, `ld`, etc., weird things don't happen. --- gcc/gcc.c | 59 --- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/gcc/gcc.c b/gcc/gcc.c index 3e98bc7973e..1a74bf92f7a 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -367,6 +367,7 @@ static void putenv_from_prefixes (const struct path_prefix *, const char *, bool); static int access_check (const char *, int); static char *find_a_file (const struct path_prefix *, const char *, int, bool); +static char *find_a_program (const char *); static void add_prefix (struct path_prefix *, const char *, const char *, int, int, int); static void add_sysrooted_prefix (struct path_prefix *, const char *, @@ -3052,22 +3053,7 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, { struct file_at_path_info info; -#ifdef DEFAULT_ASSEMBLER - if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) -return xstrdup (DEFAULT_ASSEMBLER); -#endif - -#ifdef DEFAULT_LINKER - if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0) -return xstrdup (DEFAULT_LINKER); -#endif - -#ifdef DEFAULT_DSYMUTIL - if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, mode) == 0) -return xstrdup (DEFAULT_DSYMUTIL); -#endif - - /* Determine the filename to execute (special case for absolute paths). */ + /* Find the filename in question (special case for absolute paths). */ if (IS_ABSOLUTE_PATH (name)) { @@ -3088,6 +3074,32 @@ find_a_file (const struct path_prefix *pprefix, const char *name, int mode, file_at_path, &info); } +/* Specialization of find_a_file for programs that also takes into account + configure-specified default programs. */ + +static char* +find_a_program (const char *name) +{ + /* Do not search if default matches query. */ + +#ifdef DEFAULT_ASSEMBLER + if (! strcmp (name, "as") && access (DEFAULT_ASSEMBLER, mode) == 0) +return xstrdup (DEFAULT_ASSEMBLER); +#endif + +#ifdef DEFAULT_LINKER + if (! strcmp (name, "ld") && access (DEFAULT_LINKER, mode) == 0) +return xstrdup (DEFAULT_LINKER); +#endif + +#ifdef DEFAULT_DSYMUTIL + if (! strcmp (name, "dsymutil") && access (DEFAULT_DSYMUTIL, mode) == 0) +return xstrdup (DEFAULT_DSYMUTIL); +#endif + + return find_a_file (&exec_prefixes, name, X_OK, false); +} + /* Ranking of prefixes in the sort list. -B prefixes are put before all others. */ @@ -3243,8 +3255,7 @@ execute (void) if (wrapper_string) { - string = find_a_file (&exec_prefixes, - argbuf[0], X_OK, false); + string = find_a_program (argbuf[0]); if (string) argbuf[0] = string; insert_wrapper (wrapper_string); @@ -3269,7 +3280,7 @@ execute (void) if (!wrapper_string) { - string = find_a_file (&exec_prefixes, commands[0].prog, X_OK, false); + string = find_a_program(commands[0].prog); if (string) commands[0].argv[0] = string; } @@ -3284,8 +3295,7 @@ execute (void) commands[n_commands].prog = argbuf[i + 1]; commands[n_commands].argv = &(argbuf.address ())[i + 1]; - string = find_a_file (&exec_prefixes, commands[n_commands].prog, - X_OK, false); + string = find_a_program(commands[n_commands].prog); if (string) commands[n_commands].argv[0] = string; n_commands++; @@ -8556,8 +8566,7 @@ driver::maybe_putenv_COLLECT_LTO_WRAPPER () const if (have_c) lto_wrapper_file = NULL; else -lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", - X_OK, false); +lto_wrapper_file = find_a_program ("lto-wrapper"); if (lto_wrapper_file) { lto_wrapper_file = convert_white_space (lto_wrapper_file); @@ -8671,7 +8680,7 @@ driver::maybe_print_and_exit () const #endif print_prog_name = concat (print_prog_name, use_ld, NULL); } - char *newname = find_a_file (&exec_prefixes, print_prog_name, X_OK, 0); + char *newname = find_a_program (print_prog_name); printf ("%s\n", (newname ? newname : print_prog_name)); return (0); } @@ -9070,7 +9079,7 @@ driver::maybe_run_linker (const char *argv0) const /* We'll use ld if we can't find collect2. */ if (! strcmp (linker_name_spec, "collect2")) { - char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false); + char *s = find_a_program ("collect2"); if (s == NULL) set_static_spec_shared (&linker_name_spec, "ld"); } -- 2.31.1
Re: Optional machine prefix for programs in for -B dirs
OK I have polished off my code in light of previous discussion and will submit it in follow-up emails. As mentioned before, this patch series is on top of the non-behavior-changing cleanup I previously submitted in https://gcc.gnu.org/pipermail/gcc-patches/2021-August/576725.html The first patch implements my original approach of always searching for `$machine-prog`. The next two patches refine that approach by only searching for `$machine-prog` in directories that are not already machine-disambiguated, as discussed. I wanted to include this fuller history to allow both approaches to be compared, but if desired I am happy to submit a v2 patch set with a more condensed history for whichever option is chosen. Thanks, John
[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.c | 25 - 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/gcc/gcc.c b/gcc/gcc.c index f32c7a8de46..7b6b89ac6e9 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -3080,15 +3080,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. @@ -3103,9 +3097,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.31.1
[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.c | 78 --- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/gcc/gcc.c b/gcc/gcc.c index 1a74bf92f7a..710cbfe9a66 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1582,6 +1582,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; @@ -3026,15 +3031,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; @@ -3074,12 +3070,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 @@ -3097,7 +3133,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 @@ -8328,6 +8385,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.31.1
[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.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gcc/gcc.c b/gcc/gcc.c index 710cbfe9a66..f32c7a8de46 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -2766,7 +2766,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; @@ -2827,7 +2827,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; } @@ -2838,7 +2838,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; } @@ -2848,7 +2848,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; } @@ -2876,7 +2876,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; } @@ -2931,7 +2931,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; @@ -3023,7 +3023,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); @@ -3074,7 +3074,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; @@ -5945,7 +5945,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.31.1
[PATCH v2] 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 4b937306ad0..754e622f159 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]) @@ -22,6 +51,9 @@ case $1 in tpf) thread_header=config/s390/gthr-tpf.h ;; vxworks) thread_header=config/gthr-vxworks.h ;; win32) thread_header=config/i386/gthr-win32.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 2a371870c2f..42d2016b7a2 100644 --- a/libatomic/configure.ac +++ b/libatomic/configure.ac @@ -161,9 +161,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 13a80b2551b..1209a0986e0 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -298,9 +298,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 351558dbcda..2b44fbca8fc 100644 --- a/libphobos/m4/
[PATCH] Allow explicitly specifying the thread model for runtime libs
From: John Ericson 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 4b937306ad0..c585b618e40 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" = ''; 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]) @@ -22,6 +51,9 @@ case $1 in tpf) thread_header=config/s390/gthr-tpf.h ;; vxworks) thread_header=config/gthr-vxworks.h ;; win32) thread_header=config/i386/gthr-win32.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 2a371870c2f..42d2016b7a2 100644 --- a/libatomic/configure.ac +++ b/libatomic/configure.ac @@ -161,9 +161,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 13a80b2551b..1209a0986e0 100644 --- a/libgcc/configure.ac +++ b/libgcc/configure.ac @@ -298,9 +298,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