configury: --enable-link-serialization support
authorJakub Jelinek <jakub@redhat.com>
Wed, 18 Nov 2020 19:11:37 +0000 (20:11 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 18 Nov 2020 19:11:37 +0000 (20:11 +0100)
When performing LTO bootstraps, especially when using tmpfs for /tmp,
one can run a machine to halt when using higher levels of parallelism
and a large number of FEs, because there are too many concurrent LTO
link commands running at the same time and each one of them puts most of the
middle-end/backend objects into /tmp.

We have --enable-link-mutex configure option, but --enable-link-mutex has
a big problem that it decreases number of available jobs by the number of
link commands waiting for the lock, so e.g. when doing make -j32 build with
11 different big programs linked with $(LLINKER) we end up with just 22
effective jobs, and with e.g. make -j8 with those 11 different big programs
we actually most likely serialize everything during linking onto a single job.

The following patch implements a new configure option,
--enable-link-serialization, which implements different serialization and
as it doesn't use the mutex, just modifying the old option to be implemented
differently would be strange.  We can deprecate and later remove the old
option.  The new option doesn't use any shell mutexes, but uses make
dependencies.

The option is implemented inside of gcc/ configure and Makefiles,
which means that even inside of gcc/ make all (as well as e.g. make lto-dump)
will serialize and build all previous large binaries when configured this
way.
One can always make -j32 cc1 DO_LINK_SERIALIZATION=
to avoid that.
Furthermore, I've implemented the idea I wrote about, so that
--enable-link-serialization
is the same as
--enable-link-serialization=1
and means the large link commands are serialized, one can (the default)
--disable-link-serialization
which will cause all links to be parallelizable, but one can also
--enable-link-serialization=3
etc. which says that at most 3 of the large link commands can run
concurrently.
And finally I've implemented (only if the serialization is enabled) simple
progress bars for the linking.
With --enable-link-serialization and e.g. the 5 large links I have in my
current tree (cc1, cc1plus, f951, lto1 and lto-dump), before the linking it
prints
Linking |==--      | 20%
and after it
Linking |====      | 40%
(each == characters stand for already finished links, each --
characters stand for the link being started).
With --enable-link-serialization=3 it will change the way the start is
printed, one will get:
Linking |--        | 0%
at the start of cc1 link,
Linking |>>--      | 0%
at the start of the second large link and
Linking |>>>>--    | 0%
at the start of the third large link, where the >> characters stand for
already pending links.  The printing at the end of link command is
the same as with the full serialization, i.e. for the above 3:
Linking |==        | 20%
Linking |====      | 40%
Linking |======    | 60%
but one could actually get them in any order depending on which of those 3
finishes first - to get it 100% accurate I'd need to add some directory with
files representing finished links or similar, doesn't seem worth it.

2020-11-18  Jakub Jelinek  <jakub@redhat.com>

gcc/
* configure.ac: Add $lang.prev rules, INDEX.$lang and SERIAL_LIST and
SERIAL_COUNT variables to Make-hooks.
(--enable-link-serialization): New configure option.
* Makefile.in (DO_LINK_SERIALIZATION, LINK_PROGRESS): New variables.
* doc/install.texi (--enable-link-serialization): Document.
* configure: Regenerated.
gcc/c/
* Make-lang.in (c.serial): New goal.
(.PHONY): Add c.serial c.prev.
(cc1$(exeext)): Call LINK_PROGRESS.
gcc/cp/
* Make-lang.in (c++.serial): New goal.
(.PHONY): Add c++.serial c++.prev.
(cc1plus$(exeext)): Depend on c++.prev.  Call LINK_PROGRESS.
gcc/fortran/
* Make-lang.in (fortran.serial): New goal.
(.PHONY): Add fortran.serial fortran.prev.
(f951$(exeext)): Depend on fortran.prev.  Call LINK_PROGRESS.
gcc/lto/
* Make-lang.in (lto, lto1.serial, lto2.serial): New goals.
(.PHONY): Add lto lto1.serial lto1.prev lto2.serial lto2.prev.
(lto.all.cross, lto.start.encap): Remove dependencies.
($(LTO_EXE)): Depend on lto1.prev.  Call LINK_PROGRESS.
($(LTO_DUMP_EXE)): Depend on lto2.prev.  Call LINK_PROGRESS.
gcc/objc/
* Make-lang.in (objc.serial): New goal.
(.PHONY): Add objc.serial objc.prev.
(cc1obj$(exeext)): Depend on objc.prev.  Call LINK_PROGRESS.
gcc/objcp/
* Make-lang.in (obj-c++.serial): New goal.
(.PHONY): Add obj-c++.serial obj-c++.prev.
(cc1objplus$(exeext)): Depend on obj-c++.prev.  Call LINK_PROGRESS.
gcc/ada/
* gcc-interface/Make-lang.in (ada.serial): New goal.
(.PHONY): Add ada.serial ada.prev.
(gnat1$(exeext)): Depend on ada.prev.  Call LINK_PROGRESS.
gcc/brig/
* Make-lang.in (brig.serial): New goal.
(.PHONY): Add brig.serial brig.prev.
(brig1$(exeext)): Depend on brig.prev.  Call LINK_PROGRESS.
gcc/go/
* Make-lang.in (go.serial): New goal.
(.PHONY): Add go.serial go.prev.
(go1$(exeext)): Depend on go.prev.  Call LINK_PROGRESS.
gcc/jit/
* Make-lang.in (jit.serial): New goal.
(.PHONY): Add jit.serial jit.prev.
($(LIBGCCJIT_FILENAME)): Depend on jit.prev.  Call LINK_PROGRESS.
gcc/d/
* Make-lang.in (d.serial): New goal.
(.PHONY): Add d.serial d.prev.
(d21$(exeext)): Depend on d.prev.  Call LINK_PROGRESS.

15 files changed:
gcc/Makefile.in
gcc/ada/gcc-interface/Make-lang.in
gcc/brig/Make-lang.in
gcc/c/Make-lang.in
gcc/configure
gcc/configure.ac
gcc/cp/Make-lang.in
gcc/d/Make-lang.in
gcc/doc/install.texi
gcc/fortran/Make-lang.in
gcc/go/Make-lang.in
gcc/jit/Make-lang.in
gcc/lto/Make-lang.in
gcc/objc/Make-lang.in
gcc/objcp/Make-lang.in

index 273654cfa2525099ed0d9adc2f9085c8408b096f..778ec09c75d9af1cb9f2d5e7582b948c0397db65 100644 (file)
@@ -1750,6 +1750,8 @@ $(FULL_DRIVER_NAME): ./xgcc$(exeext)
 # Otherwise $(SELFTEST_DEPS) is empty when used from <LANG>/Make-lang.in.
 SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
 
+DO_LINK_SERIALIZATION = @DO_LINK_SERIALIZATION@
+
 # Language makefile fragments.
 
 # The following targets define the interface between us and the languages.
@@ -1767,6 +1769,23 @@ SELFTEST_DEPS = $(GCC_PASSES) stmp-int-hdrs $(srcdir)/testsuite/selftests
 # language hooks, generated by configure
 @language_hooks@
 
+ifeq ($(DO_LINK_SERIALIZATION),)
+LINK_PROGRESS = :
+else
+LINK_PROGRESS = msg="Linking |"; cnt=0; if test "$(2)" = start; then \
+  idx=0; cnt2=$(DO_LINK_SERIALIZATION); \
+  while test $$cnt2 -le $(1); do msg="$${msg}=="; cnt2=`expr $$cnt2 + 1`; idx=`expr $$idx + 1`; done; \
+  cnt=$$idx; \
+  while test $$cnt -lt $(1); do msg="$${msg}>>"; cnt=`expr $$cnt + 1`; done; \
+  msg="$${msg}--"; cnt=`expr $$cnt + 1`; \
+  else \
+  idx=`expr $(1) + 1`; \
+  while test $$cnt -le $(1); do msg="$${msg}=="; cnt=`expr $$cnt + 1`; done; \
+  fi; \
+  while test $$cnt -lt $(SERIAL_COUNT); do msg="$${msg}  "; cnt=`expr $$cnt + 1`; done; \
+  msg="$${msg}| `expr 100 \* $$idx / $(SERIAL_COUNT)`%"; echo "$$msg"
+endif
+
 # Wire in install-gnatlib invocation with `make install' for a configuration
 # with top-level libada disabled.
 gnat_install_lib = @gnat_install_lib@
index 78fe6023e5b42f6fb67113e5d742c5506f5c5511..e41465761c8ebfdc066eec180dcfc84b14a18f4f 100644 (file)
@@ -146,9 +146,10 @@ endif
 
 # Define the names for selecting Ada in LANGUAGES.
 ada: gnat1$(exeext) gnatbind$(exeext)
+ada.serial: gnat1$(exeext)
 
 # Tell GNU Make to ignore these, if they exist.
-.PHONY: ada
+.PHONY: ada ada.serial ada.prev
 
 # Compute the FLAGS to pass for gnattools, now linked with a C++ driver as
 # we're linking against at least libcommon which contains C++ compiled code.
@@ -667,10 +668,13 @@ ada/libgnat/s-excmac.adb: $(srcdir)/ada/libgnat/s-excmac__$(EH_MECHANISM).adb
 # Needs to be built with CC=gcc
 # Since the RTL should be built with the latest compiler, remove the
 #  stamp target in the parent directory whenever gnat1 is rebuilt
-gnat1$(exeext): $(TARGET_ADA_SRCS) $(GNAT1_OBJS) $(ADA_BACKEND) libcommon-target.a $(LIBDEPS)
+gnat1$(exeext): $(TARGET_ADA_SRCS) $(GNAT1_OBJS) $(ADA_BACKEND) libcommon-target.a \
+               $(LIBDEPS) ada.prev
+       @$(call LINK_PROGRESS,$(INDEX.ada),start)
        +$(GCC_LLINK) -o $@ $(GNAT1_OBJS) $(ADA_BACKEND) \
          libcommon-target.a $(LIBS) $(SYSLIBS) $(BACKENDLIBS) $(CFLAGS)
        $(RM) stamp-gnatlib2-rts stamp-tools
+       @$(call LINK_PROGRESS,$(INDEX.ada),end)
 
 gnatbind$(exeext): ada/b_gnatb.o $(CONFIG_H) $(GNATBIND_OBJS) ggc-none.o libcommon-target.a $(LIBDEPS)
        +$(GCC_LINK) -o $@ ada/b_gnatb.o $(GNATBIND_OBJS) ggc-none.o libcommon-target.a $(LIBS) $(SYSLIBS) $(CFLAGS)
index f5538564ed4b5a385865c91a84bb1d42608d2819..dffc7503c14680b3dea3040018023bfc762d2913 100644 (file)
@@ -29,8 +29,9 @@ GCCBRIG_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccbrig|sed \
 
 # The name for selecting brig in LANGUAGES.
 brig: brig1$(exeext)
+brig.serial: brig
 
-.PHONY: brig
+.PHONY: brig brig.serial brig.prev
 
 CFLAGS-brig/brigspec.o += $(DRIVER_DEFINES)
 
@@ -81,15 +82,12 @@ BRIG_OBJS = \
 
 brig_OBJS = $(BRIG_OBJS) brig/brigspec.o
 
-# brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
-#      +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
-#            $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
-
-
-brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+brig1$(exeext): $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBDEPS) brig.prev
+       @$(call LINK_PROGRESS,$(INDEX.brig),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
              $(BRIG_OBJS) attribs.o $(BACKEND) $(LIBS) \
                  $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.brig),end)
 
 # Documentation.
 
index 7efc7c2c332cd841de85faee9d0082e9ae04d80b..c776ab65f05b9d3a7fd7b6125b21cc21677e9c0a 100644 (file)
 #\f
 # Define the names for selecting c in LANGUAGES.
 c: cc1$(exeext)
+c.serial: c
 
 # Tell GNU make to ignore these if they exist.
-.PHONY: c gcc
+.PHONY: c gcc c.serial
 
 # The C front end driver.  This is different from the drivers for other
 # front ends, because there is no C language specific driver (i.e. nothing
@@ -82,8 +83,10 @@ cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
        fi
 
 cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+       @$(call LINK_PROGRESS,$(INDEX.c),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
          cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.c),end)
 
 cc1.fda: ../stage1-gcc/cc1$(exeext) ../prev-gcc/$(PERF_DATA)
        $(CREATE_GCOV) -binary ../stage1-gcc/cc1$(exeext) -gcov cc1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1
index ba69f73ed9c98281b4d3b9a6c291727047bbac41..f61b815801eaf11a549ddc5aa8e57dfc53e2ed1a 100755 (executable)
@@ -710,6 +710,7 @@ subdirs
 dollar
 gcc_tooldir
 enable_lto
+DO_LINK_SERIALIZATION
 DO_LINK_MUTEX
 MAINT
 zlibinc
@@ -1013,6 +1014,7 @@ with_gc
 with_system_zlib
 enable_maintainer_mode
 enable_link_mutex
+enable_link_serialization
 enable_version_specific_runtime_libs
 enable_plugin
 enable_host_shared
@@ -1768,6 +1770,10 @@ Optional Features:
                           sometimes confusing) to the casual installer
   --enable-link-mutex     avoid linking multiple front-ends at once to avoid
                           thrashing on the build machine
+  --enable-link-serialization
+                          avoid linking multiple GCC front-ends at once using
+                          make dependencies to avoid thrashing on the build
+                          machine
   --enable-version-specific-runtime-libs
                           specify that runtime libraries should be installed
                           in a compiler-specific directory
@@ -19030,7 +19036,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19033 "configure"
+#line 19039 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -19136,7 +19142,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<_LT_EOF
-#line 19139 "configure"
+#line 19145 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -30573,6 +30579,31 @@ else
 fi
 
 
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to serialize linking of multiple front-ends" >&5
+$as_echo_n "checking whether to serialize linking of multiple front-ends... " >&6; }
+  # Check whether --enable-link-serialization was given.
+if test "${enable_link_serialization+set}" = set; then :
+  enableval=$enable_link_serialization; do_link_serialization=$enableval
+else
+  do_link_serialization=no
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $do_link_serialization" >&5
+$as_echo "$do_link_serialization" >&6; }
+
+case "$do_link_serialization" in
+  yes)
+    DO_LINK_SERIALIZATION=1;;
+  [1-9] | [1-9][0-9] | [1-9][0-9][0-9])
+    DO_LINK_SERIALIZATION=$do_link_serialization;;
+  no)
+    DO_LINK_SERIALIZATION=;;
+  *)
+    as_fn_error $? "bad value ${do_link_serialization} given for --enable-link-serialization" "$LINENO" 5 ;;
+esac
+
+
 # --------------
 # Language hooks
 # --------------
        echo "lang.$t: $x" >> Make-hooks
 done
 
+echo "ifeq (\$(DO_LINK_SERIALIZATION),)" >> Make-hooks
+echo "SERIAL_LIST =" >> Make-hooks
+echo else >> Make-hooks
+lang_cnt=0
+lang_list=
+prev=c.serial
+serialization_languages=c
+for lang in $all_selected_languages
+do
+       test $lang = c && continue
+       if test $lang = lto; then
+               serialization_languages="$serialization_languages lto1 lto2"
+       else
+               serialization_languages="$serialization_languages $lang"
+       fi
+done
+for lang in $serialization_languages
+do
+       test $lang = c && continue
+       lang_cnt=`expr $lang_cnt + 1`
+       lang_list=" $prev$lang_list"
+       prev=${lang}.serial
+done
+echo "SERIAL_LIST = \$(wordlist \$(DO_LINK_SERIALIZATION),$lang_cnt,$lang_list)" >> Make-hooks
+echo endif >> Make-hooks
+echo "SERIAL_COUNT = `expr $lang_cnt + 1`" >> Make-hooks
+echo "INDEX.c = 0" >> Make-hooks
+lang_idx=1
+for lang in $serialization_languages
+do
+       test $lang = c && continue
+       echo "$lang.prev: \$(word $lang_cnt,\$(SERIAL_LIST))" >> Make-hooks
+       echo "INDEX.$lang = $lang_idx" >> Make-hooks
+       lang_cnt=`expr $lang_cnt - 1`
+       lang_idx=`expr $lang_idx + 1`
+done
+
 # --------
 # Option include files
 # --------
index 28d96d1cba3bc42e757afa6137c6f2513256beff..b2732d17bf48d69f6b44d02d876e9b84caf1e2a8 100644 (file)
@@ -6676,6 +6676,29 @@ else
 fi
 AC_SUBST(DO_LINK_MUTEX)
 
+dnl Whether to prevent multiple GCC front-ends from linking at the same time
+
+AC_MSG_CHECKING([whether to serialize linking of multiple front-ends])
+  AC_ARG_ENABLE(link-serialization,
+[AS_HELP_STRING([--enable-link-serialization],
+               [avoid linking multiple GCC front-ends at once using make
+                dependencies to avoid thrashing on the build machine])],
+      do_link_serialization=$enableval,
+      do_link_serialization=no)
+AC_MSG_RESULT($do_link_serialization)
+
+case "$do_link_serialization" in
+  yes)
+    DO_LINK_SERIALIZATION=1;;
+  [[1-9]] | [[1-9]][[0-9]] | [[1-9]][[0-9]][[0-9]])
+    DO_LINK_SERIALIZATION=$do_link_serialization;;
+  no)
+    DO_LINK_SERIALIZATION=;;
+  *)
+    AC_MSG_ERROR(bad value ${do_link_serialization} given for --enable-link-serialization) ;;
+esac
+AC_SUBST(DO_LINK_SERIALIZATION)
+
 # --------------
 # Language hooks
 # --------------
@@ -6836,6 +6859,43 @@ do
        echo "lang.$t: $x" >> Make-hooks
 done
 
+echo "ifeq (\$(DO_LINK_SERIALIZATION),)" >> Make-hooks
+echo "SERIAL_LIST =" >> Make-hooks
+echo else >> Make-hooks
+lang_cnt=0
+lang_list=
+prev=c.serial
+serialization_languages=c
+for lang in $all_selected_languages
+do
+       test $lang = c && continue
+       if test $lang = lto; then
+               serialization_languages="$serialization_languages lto1 lto2"
+       else
+               serialization_languages="$serialization_languages $lang"
+       fi
+done
+for lang in $serialization_languages
+do
+       test $lang = c && continue
+       lang_cnt=`expr $lang_cnt + 1`
+       lang_list=" $prev$lang_list"
+       prev=${lang}.serial
+done
+echo "SERIAL_LIST = \$(wordlist \$(DO_LINK_SERIALIZATION),$lang_cnt,$lang_list)" >> Make-hooks
+echo endif >> Make-hooks
+echo "SERIAL_COUNT = `expr $lang_cnt + 1`" >> Make-hooks
+echo "INDEX.c = 0" >> Make-hooks
+lang_idx=1
+for lang in $serialization_languages
+do
+       test $lang = c && continue
+       echo "$lang.prev: \$(word $lang_cnt,\$(SERIAL_LIST))" >> Make-hooks
+       echo "INDEX.$lang = $lang_idx" >> Make-hooks
+       lang_cnt=`expr $lang_cnt - 1`
+       lang_idx=`expr $lang_idx + 1`
+done
+
 # --------
 # Option include files
 # --------
index 6ee4e41266f98ac6f404f5dea8644e4d0e7f09ef..6be4678776b6022ccea966f7bb55ed2a317306ec 100644 (file)
@@ -47,9 +47,10 @@ CP_PLUGIN_HEADERS := cp-tree.h cxx-pretty-print.h name-lookup.h type-utils.h ope
 # into the C++ rule, but that needs a little bit of work
 # to do the right thing within all.cross.
 c++: cc1plus$(exeext)
+c++.serial: c++
 
 # Tell GNU make to ignore these if they exist.
-.PHONY: c++
+.PHONY: c++ c++.serial c++.prev
 
 CFLAGS-cp/g++spec.o += $(DRIVER_DEFINES)
 
@@ -116,9 +117,11 @@ cc1plus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
          $(srcdir)/../move-if-change cc1plus-checksum.c.tmp cc1plus-checksum.c; \
        fi
 
-cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS)
+cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS) c++.prev
+       @$(call LINK_PROGRESS,$(INDEX.c++),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
              $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.c++),end)
 
 ifeq ($(ENABLE_MAINTAINER_RULES), true)
 # Special build rule.  This is a maintainer rule, that is only
index 18d99abab354db7a14bc7d45173b97bee3389239..0242c9cc04e9a07cfe6ba29a47e8ac8e950006f6 100644 (file)
@@ -27,9 +27,10 @@ D_LIBPHOBOS = -DLIBPHOBOS=\"gphobos\"
 
 # The name for selecting d in LANGUAGES.
 d: d21$(exeext)
+d.serial: d
 
 # Tell GNU make to ignore these if they exist.
-.PHONY: d
+.PHONY: d d.serial d.prev
 
 # Create the compiler driver for D.
 CFLAGS-d/d-spec.o += $(DRIVER_DEFINES) $(D_LIBPHOBOS)
@@ -162,9 +163,11 @@ D_ALL_OBJS = $(D_FRONTEND_OBJS) $(D_GENERATED_OBJS) $(D_OBJS) $(D_TARGET_OBJS)
 
 d_OBJS = $(D_ALL_OBJS) d/d-spec.o
 
-d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+d21$(exeext): $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBDEPS) d.prev
+       @$(call LINK_PROGRESS,$(INDEX.d),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
                $(D_ALL_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.d),end)
 
 # Documentation.
 
index e8fd34c64947c97285095d30000ff841243ef615..297831fda551773d36e28409ca8726bbc6ecde3f 100644 (file)
@@ -1564,6 +1564,14 @@ When building GCC, use a mutex to avoid linking the compilers for
 multiple languages at the same time, to avoid thrashing on build
 systems with limited free memory.  The default is not to use such a mutex.
 
+@item --enable-link-serialization
+When building GCC, use make dependencies to serialize linking the compilers for
+multiple languages, to avoid thrashing on build
+systems with limited free memory.  The default is not to add such
+dependencies and thus with parallel make potentially link different
+compilers concurrently.  If the argument is a positive integer, allow
+that number of concurrent link processes for the large binaries.
+
 @item --enable-maintainer-mode
 The build rules that regenerate the Autoconf and Automake output files as
 well as the GCC master message catalog @file{gcc.pot} are normally
index 977db6092bc5eadfc626f2734209217832974988..ea2e49bc086a6688d12c64a19a03b44f16f8e14f 100644 (file)
@@ -72,9 +72,10 @@ fortran_OBJS = $(F95_OBJS) fortran/gfortranspec.o
 #\f
 # Define the names for selecting gfortran in LANGUAGES.
 fortran: f951$(exeext)
+fortran.serial: fortran
 
 # Tell GNU make to ignore files by these names if they exist.
-.PHONY: fortran
+.PHONY: fortran fortran.serial fortran.prev
 
 CFLAGS-fortran/gfortranspec.o += $(DRIVER_DEFINES)
 
@@ -92,11 +93,12 @@ gfortran-cross$(exeext): gfortran$(exeext)
        cp gfortran$(exeext) gfortran-cross$(exeext)
 
 # The compiler itself is called f951.
-f951$(exeext): $(F95_OBJS) \
-               $(BACKEND) $(LIBDEPS) attribs.o
+f951$(exeext): $(F95_OBJS) $(BACKEND) $(LIBDEPS) attribs.o fortran.prev
+       @$(call LINK_PROGRESS,$(INDEX.fortran),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
                $(F95_OBJS) $(BACKEND) $(ZLIB) $(LIBS) attribs.o \
                $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.fortran),end)
 
 gt-fortran-trans.h    : s-gtype; @true
 #\f
index ce711b2cbde8d943c177d008ce9583e7537deeb3..7c586cbb53537b392ae906218af9a5c0bedd7171 100644 (file)
@@ -27,8 +27,9 @@ GCCGO_TARGET_INSTALL_NAME := $(target_noncanonical)-$(shell echo gccgo|sed '$(pr
 
 # The name for selecting go in LANGUAGES.
 go: go1$(exeext)
+go.serial: go
 
-.PHONY: go
+.PHONY: go go.serial go.prev
 
 CFLAGS-go/gospec.o += $(DRIVER_DEFINES)
 
@@ -78,9 +79,11 @@ GO_OBJS = \
 
 go_OBJS = $(GO_OBJS) go/gospec.o
 
-go1$(exeext): $(GO_OBJS) attribs.o $(BACKEND) $(LIBDEPS)
+go1$(exeext): $(GO_OBJS) attribs.o $(BACKEND) $(LIBDEPS) go.prev
+       @$(call LINK_PROGRESS,$(INDEX.go),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
              $(GO_OBJS) attribs.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.go),end)
 
 # Documentation.
 
index 3b543926c982532173fd2627a3cc44760af0090b..012f62d830c8bcea73ad1f3f5d1b3356247a1288 100644 (file)
@@ -81,8 +81,10 @@ jit: $(LIBGCCJIT_FILENAME) \
        $(FULL_DRIVER_NAME)
 endif
 
+jit.serial: $(LIBGCCJIT_FILENAME)
+
 # Tell GNU make to ignore these if they exist.
-.PHONY: jit
+.PHONY: jit jit.serial jit.prev
 
 jit_OBJS = attribs.o \
        jit/dummy-frontend.o \
@@ -117,12 +119,14 @@ $(LIBGCCJIT_FILENAME): $(jit_OBJS) \
        libbackend.a libcommon-target.a libcommon.a \
        $(CPPLIB) $(LIBDECNUMBER) \
        $(LIBDEPS) $(srcdir)/jit/libgccjit.map \
-       $(EXTRA_GCC_OBJS)
+       $(EXTRA_GCC_OBJS) jit.prev
+       @$(call LINK_PROGRESS,$(INDEX.jit),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ -shared \
             $(jit_OBJS) libbackend.a libcommon-target.a libcommon.a \
             $(CPPLIB) $(LIBDECNUMBER) $(EXTRA_GCC_LIBS) $(LIBS) $(BACKENDLIBS) \
             $(EXTRA_GCC_OBJS) \
             $(LIBGCCJIT_EXTRA_OPTS)
+       @$(call LINK_PROGRESS,$(INDEX.jit),end)
 
 # Create symlinks when not building for Windows
 ifeq (,$(findstring mingw,$(target)))
index 0b73f9ef7bbdec2e5736baf291e0b51ba8f3d8dd..4a03f1930c43ba771e92f22936e998379015d2d9 100644 (file)
@@ -41,10 +41,16 @@ lto_dump_OBJS = $(LTO_DUMP_OBJS)
 
 # Rules
 
+lto: $(LTO_EXE) $(LTO_DUMP_EXE)
+lto1.serial: $(LTO_EXE)
+lto2.serial: $(LTO_DUMP_EXE)
+
+.PHONY: lto lto1.serial lto1.prev lto2.serial lto2.prev
+
 # These hooks are used by the main GCC Makefile.  Consult that
 # Makefile for documentation.
-lto.all.cross: $(LTO_EXE) $(LTO_DUMP_EXE)
-lto.start.encap: $(LTO_EXE) $(LTO_DUMP_EXE)
+lto.all.cross:
+lto.start.encap:
 lto.rest.encap:
 lto.tags:
 lto.install-common: installdirs
@@ -84,13 +90,17 @@ lto.stagefeedback:
 # Use strict warnings for this front end.
 lto-warn = $(STRICT_WARN)
 
-$(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS)
+$(LTO_EXE): $(LTO_OBJS) $(BACKEND) $(LIBDEPS) lto1.prev
+       @$(call LINK_PROGRESS,$(INDEX.lto1),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
                $(LTO_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
+       @$(call LINK_PROGRESS,$(INDEX.lto1),end)
 
-$(LTO_DUMP_EXE): $(LTO_DUMP_OBJS) $(BACKEND) $(LIBDEPS)
+$(LTO_DUMP_EXE): $(LTO_DUMP_OBJS) $(BACKEND) $(LIBDEPS) lto2.prev
+       @$(call LINK_PROGRESS,$(INDEX.lto2),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
                $(LTO_DUMP_OBJS) $(BACKEND) $(BACKENDLIBS) $(LIBS)
+       @$(call LINK_PROGRESS,$(INDEX.lto2),end)
 
 lto/lto-dump.o: $(LTO_OBJS)
 
index add1355a0969e5f4b917ac6dd3a8b155b3ae5c49..a19befb68a081da4f944551b62db3ed39dc9f9cf 100644 (file)
 #\f
 # Define the names for selecting Objective-C in LANGUAGES.
 objc: cc1obj$(exeext)
+objc.serial: objc
 
 # Tell GNU make to ignore these if they exist.
-.PHONY: objc
+.PHONY: objc objc.serial objc.prev
 
 # Use maximal warnings for this front end.
 objc-warn = $(STRICT_WARN)
@@ -62,10 +63,13 @@ cc1obj-checksum.c : build/genchecksum$(build_exeext) checksum-options \
         $(BACKEND) $(LIBDEPS) checksum-options > cc1obj-checksum.c.tmp && \
        $(srcdir)/../move-if-change cc1obj-checksum.c.tmp cc1obj-checksum.c
 
-cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(LIBDEPS)
+cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) \
+                $(LIBDEPS) objc.prev
+       @$(call LINK_PROGRESS,$(INDEX.objc),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
              $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o \
              $(BACKEND) $(LIBS) $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.objc),end)
 
 objc.srcextra:
 
index 5bfef2410f22f728ae4ee6cf33cbad794b57be3a..2f6954e37c0b6d76af3052a406c6fca60671c651 100644 (file)
 #\f
 # Define the names for selecting Objective-C++ in LANGUAGES.
 obj-c++: cc1objplus$(exeext)
+obj-c++.serial: obj-c++
 
 # Tell GNU make to ignore these if they exist.
-.PHONY: obj-c++
+.PHONY: obj-c++ obj-c++.serial obj-c++.prev
 
 # Use maximal warnings for this front end.  Also, make ObjC and C++
 # headers accessible.
@@ -66,9 +67,12 @@ cc1objplus-checksum.c : build/genchecksum$(build_exeext) checksum-options \
        $(srcdir)/../move-if-change cc1objplus-checksum.c.tmp \
        cc1objplus-checksum.c
 
-cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
+cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) \
+                    $(LIBDEPS) obj-c++.prev
+       @$(call LINK_PROGRESS,$(INDEX.obj-c++),start)
        +$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
                $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+       @$(call LINK_PROGRESS,$(INDEX.obj-c++),end)
 
 # Objective C++ language specific files.