Commits

Peter Eisentraut committed 19e231b

Improved parallel make support

Replace for loops in makefiles with proper dependencies. Parallel
make can now span across directories. Also, make -k and make -q work
properly.

GNU make 3.80 or newer is now required.

Comments (0)

Files changed (30)

 top_builddir = .
 include $(top_builddir)/src/Makefile.global
 
+$(call recurse,all install,src config)
+
 all:
-	$(MAKE) -C src all
-	$(MAKE) -C config all
-	@echo "All of PostgreSQL successfully made. Ready to install."
+	+@echo "All of PostgreSQL successfully made. Ready to install."
 
 docs:
 	$(MAKE) -C doc all
 
+$(call recurse,world,doc src config contrib,all)
 world:
-	$(MAKE) -C doc all
-	$(MAKE) -C src all
-	$(MAKE) -C config all
-	$(MAKE) -C contrib all
-	@echo "PostgreSQL, contrib, and documentation successfully made. Ready to install."
+	+@echo "PostgreSQL, contrib, and documentation successfully made. Ready to install."
 
 html man:
 	$(MAKE) -C doc $@
 
 install:
-	$(MAKE) -C src $@
-	$(MAKE) -C config $@
-	@echo "PostgreSQL installation complete."
+	+@echo "PostgreSQL installation complete."
 
 install-docs:
 	$(MAKE) -C doc install
 
+$(call recurse,install-world,doc src config contrib,install)
 install-world:
-	$(MAKE) -C doc install
-	$(MAKE) -C src install
-	$(MAKE) -C config install
-	$(MAKE) -C contrib install
-	@echo "PostgreSQL, contrib, and documentation installation complete."
+	+@echo "PostgreSQL, contrib, and documentation installation complete."
 
-installdirs uninstall coverage:
-	$(MAKE) -C doc $@
-	$(MAKE) -C src $@
-	$(MAKE) -C config $@
+$(call recurse,installdirs uninstall coverage,doc src config)
 
-distprep:
-	$(MAKE) -C doc $@
-	$(MAKE) -C src $@
-	$(MAKE) -C config $@
-	$(MAKE) -C contrib $@
+$(call recurse,distprep,doc src config contrib)
 
 # clean, distclean, etc should apply to contrib too, even though
 # it's not built by default
+$(call recurse,clean,doc contrib src config)
 clean:
-	$(MAKE) -C doc $@
-	$(MAKE) -C contrib $@
-	$(MAKE) -C src $@
-	$(MAKE) -C config $@
 # Garbage from autoconf:
 	@rm -rf autom4te.cache/
 
 check installcheck installcheck-parallel:
 	$(MAKE) -C src/test $@
 
-installcheck-world:
-	$(MAKE) -C src/test installcheck
-	$(MAKE) -C src/pl installcheck
-	$(MAKE) -C src/interfaces/ecpg installcheck
-	$(MAKE) -C contrib installcheck
+$(call recurse,installcheck-world,src/test src/pl src/interfaces/ecpg contrib,installcheck)
 
 GNUmakefile: GNUmakefile.in $(top_builddir)/config.status
 	./config.status $@
 	rm -rf $(distdir) $(dummy)
 	@echo "Distribution integrity checks out."
 
-.PHONY: dist distdir distcheck docs install-docs
-
-
-# Temporary measure to explore whether we can start requiring GNU make
-# 3.80.  That version also happens to be the version where the
-# .VARIABLES variable was introduced, so this is a simple check.
-ifndef .VARIABLES
-$(warning warning: GNU make 3.80 or newer might become required soon. You are using version $(MAKE_VERSION).)
-endif
+.PHONY: dist distdir distcheck docs install-docs world install-world installcheck-world
 #		start-scripts	\ (does not have a makefile)
 
 
-all install installdirs uninstall distprep clean distclean maintainer-clean:
-	@for dir in $(SUBDIRS); do \
-		$(MAKE) -C $$dir $@ || exit; \
-	done
-
-# We'd like check operations to run all the subtests before failing.
-check installcheck:
-	@CHECKERR=0; for dir in $(SUBDIRS); do \
-		$(MAKE) -C $$dir $@ || CHECKERR=$$?; \
-	done; \
-	exit $$CHECKERR
+$(recurse)

contrib/dblink/Makefile

 PG_CPPFLAGS = -I$(libpq_srcdir)
 OBJS	= dblink.o
 SHLIB_LINK = $(libpq)
+SHLIB_PREREQS = submake-libpq
 
 DATA_built = dblink.sql 
 DATA = uninstall_dblink.sql 

doc/src/sgml/installation.sgml

        <primary>make</primary>
       </indexterm>
 
-      <acronym>GNU</> <application>make</> is required; other
-      <application>make</> programs will <emphasis>not</> work.
+      <acronym>GNU</> <application>make</> version 3.80 or newer is required; other
+      <application>make</> programs or older <acronym>GNU</> <application>make</> versions will <emphasis>not</> work.
       <acronym>GNU</> <application>make</> is often installed under
       the name <filename>gmake</filename>; this document will always
       refer to it by that name. (On some systems
 <screen>
 <userinput>gmake --version</userinput>
 </screen>
-      It is recommended to use version 3.79.1 or later.
      </para>
     </listitem>
 
 top_builddir = ..
 include Makefile.global
 
+SUBDIRS = \
+	port \
+	timezone \
+	backend \
+	backend/utils/mb/conversion_procs \
+	backend/snowball \
+	include \
+	interfaces \
+	backend/replication/libpqwalreceiver \
+	bin \
+	pl \
+	makefiles \
+	test/regress
 
-all install installdirs uninstall distprep:
-	$(MAKE) -C port $@
-	$(MAKE) -C timezone $@
-	$(MAKE) -C backend $@
-	$(MAKE) -C backend/utils/mb/conversion_procs $@
-	$(MAKE) -C backend/snowball $@
-	$(MAKE) -C include $@
-	$(MAKE) -C interfaces $@
-	$(MAKE) -C backend/replication/libpqwalreceiver $@
-	$(MAKE) -C bin $@
-	$(MAKE) -C pl $@
-	$(MAKE) -C makefiles $@
-	$(MAKE) -C test/regress $@
+$(recurse)
 
 install: install-local
 
 	rm -f $(addprefix '$(DESTDIR)$(pgxsdir)/$(subdir)'/, Makefile.global Makefile.port Makefile.shlib nls-global.mk)
 
 clean:
-	$(MAKE) -C port $@
-	$(MAKE) -C timezone $@
-	$(MAKE) -C backend $@
-	$(MAKE) -C backend/snowball $@
-	$(MAKE) -C include $@
-	$(MAKE) -C interfaces $@
-	$(MAKE) -C backend/replication/libpqwalreceiver $@
-	$(MAKE) -C bin $@
-	$(MAKE) -C pl $@
-	$(MAKE) -C makefiles $@
 	$(MAKE) -C test $@
 	$(MAKE) -C tutorial NO_PGXS=1 $@
 	$(MAKE) -C test/thread $@
 
 distclean maintainer-clean:
-	$(MAKE) -C port $@
-	$(MAKE) -C timezone $@
-	$(MAKE) -C backend $@
-	$(MAKE) -C backend/snowball $@
-	$(MAKE) -C include $@
-	$(MAKE) -C interfaces $@
-	$(MAKE) -C backend/replication/libpqwalreceiver $@
-	$(MAKE) -C bin $@
-	$(MAKE) -C pl $@
-	$(MAKE) -C makefiles $@
 	$(MAKE) -C test $@
 	$(MAKE) -C tutorial NO_PGXS=1 $@
 	$(MAKE) -C test/thread $@

src/Makefile.global.in

 #
 # Meta configuration
 
-.PHONY: all install install-strip installdirs uninstall clean distclean maintainer-clean distprep check installcheck maintainer-check coverage html man installcheck-parallel world install-world installcheck-world
+standard_targets = all install installdirs uninstall distprep clean distclean maintainer-clean coverage check installcheck
+
+.PHONY: $(standard_targets) install-strip maintainer-check html man installcheck-parallel
 
 # make `all' the default target
 all:
 
 ##########################################################################
 #
+# Recursive make support
+# ----------------------
+# Instead of recursing through subdirectories with a for loop or
+# repeated $(MAKE) -C whatever calls, this is a little smarter: it
+# allows parallel make across directories and lets make -k and -q work
+# correctly.
+
+# This function is only for internal use below.  It should be called
+# with $(eval).  It will set up a target so that it recurses into
+# subdirectories.
+# $1: target name, e.g., all
+# $2: list of subdirs
+# $3: target to run in subdir, usually same as $1
+define _create_recursive_target
+.PHONY: $(patsubst %,$(1)-%-recursive,$(2))
+$(1): $(patsubst %,$(1)-%-recursive,$(2))
+$(2:%=$(1)-%-recursive):
+	$$(MAKE) -C $$(patsubst $(1)-%-recursive,%,$$@) $(3)
+endef
+# Note that the use of $$ on the last line above is important; we want
+# those variables/functions to be evaluated when the rule is run, not
+# when the $(eval) is run to create the rule.  In the case of
+# $$(MAKE), this is necessary to get make -q working.
+
+# Call this function in a makefile.  In the normal case it doesn't
+# need any arguments.
+# $1: targets to make recursive (defaults to list of standard targets)
+# $2: list of subdirs (defaults to SUBDIRS variable)
+# $3: target to run in subdir (defaults to $1)
+recurse = $(foreach target,$(if $1,$1,$(standard_targets)),$(eval $(call _create_recursive_target,$(target),$(if $2,$2,$(SUBDIRS)),$(if $3,$3,$(target)))))
+
+# We need the $(eval) function and order-only prerequisites, which are
+# available in GNU make 3.80.  That also happens to be the version
+# where the .VARIABLES variable was introduced, so this is a simple
+# check.
+ifndef .VARIABLES
+$(error GNU make 3.80 or newer is required.  You are using version $(MAKE_VERSION))
+endif
+
+
+##########################################################################
+#
 # Automatic dependency generation
 # -------------------------------
 # When we configure with --enable-depend then we override the default
 	$(GCOV) -b -f -p -o . $(GCOVFLAGS) $*.c >$*.c.gcov.out
 
 coverage: $(gcda_files:.gcda=.c.gcov) lcov.info
-	$(if $(SUBDIRS),for dir in $(SUBDIRS); do $(MAKE) -C $$dir coverage || exit; done)
 
 .PHONY: coverage-html
 coverage-html: coverage

src/Makefile.shlib

 # OBJS                  List of object files to include in library
 # SHLIB_LINK            If shared library relies on other libraries,
 #                       additional stuff to put in its link command
+# SHLIB_PREREQS         Order-only prerequisites for library build target
 # SHLIB_EXPORTS         (optional) Name of file containing list of symbols to
 #                       export, in the format "function_name  number"
 #
 all-shared-lib: $(shlib)
 
 ifndef haslibarule
-$(stlib): $(OBJS)
+$(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	$(LINK.static) $@ $^
 	$(RANLIB) $@
 endif #haslibarule
 ifneq ($(PORTNAME), aix)
 
 # Normal case
-$(shlib): $(OBJS)
+$(shlib): $(OBJS) | $(SHLIB_PREREQS)
 	$(LINK.shared) -o $@ $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK)
 ifdef shlib_major
 # If we're using major and minor versions, then make a symlink to major-version-only.
 else # PORTNAME == aix
 
 # AIX case
-$(shlib) $(stlib): $(OBJS)
+$(shlib) $(stlib): $(OBJS) | $(SHLIB_PREREQS)
 	$(LINK.static) $(stlib) $^
 	$(RANLIB) $(stlib)
 	$(MKLDEXPORT) $(stlib) >$(exports_file)
 DLL_DEFFILE = lib$(NAME)dll.def
 endif
 
-$(shlib): $(OBJS) $(DLL_DEFFILE)
+$(shlib): $(OBJS) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
 	$(DLLWRAP) -o $@ --dllname $(shlib) $(DLLWRAP_FLAGS) --def $(DLL_DEFFILE) $(OBJS) $(LDFLAGS) $(LDFLAGS_SL) $(SHLIB_LINK)
 
-$(stlib): $(shlib) $(DLL_DEFFILE)
+$(stlib): $(shlib) $(DLL_DEFFILE) | $(SHLIB_PREREQS)
 	$(DLLTOOL) --dllname $(shlib) $(DLLTOOL_LIBFLAGS) --def $(DLL_DEFFILE) --output-lib $@
 
 endif # PORTNAME == cygwin || PORTNAME == win32

src/backend/Makefile

 
 .PHONY: submake-schemapg
 
-catalog/schemapg.h: submake-schemapg
+catalog/schemapg.h: | submake-schemapg
+
+$(top_builddir)/src/port/libpgport_srv.a: | submake-libpgport
 
 
 # The postgres.o target is needed by the rule in Makefile.global that

src/backend/common.mk

 expand_subsys = $(foreach file,$(1),$(if $(filter %/objfiles.txt,$(file)),$(patsubst ../../src/backend/%,%,$(addprefix $(top_builddir)/,$(shell cat $(file)))),$(file)))
 
 # Parallel make trickery
-$(SUBDIROBJS): $(SUBDIRS:%=%-recursive) ;
+$(SUBDIROBJS): | $(SUBDIRS:%=%-recursive) ;
 
 .PHONY: $(SUBDIRS:%=%-recursive)
 $(SUBDIRS:%=%-recursive):
 	$(MAKE) -C $(subst -recursive,,$@) all
 
+$(call recurse,clean)
 clean: clean-local
 clean-local:
-ifdef SUBDIRS
-	for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean || exit; done
-endif
 	rm -f $(subsysfilename) $(OBJS)

src/backend/replication/libpqwalreceiver/Makefile

 
 OBJS = libpqwalreceiver.o
 SHLIB_LINK = $(libpq)
+SHLIB_PREREQS = submake-libpq
 NAME = libpqwalreceiver
 
-all: submake-libpq all-shared-lib
+all: all-shared-lib
 
 include $(top_srcdir)/src/Makefile.shlib
 

src/backend/utils/mb/conversion_procs/Makefile

 	utf8_and_sjis utf8_and_win utf8_and_uhc \
 	utf8_and_euc2004 utf8_and_sjis2004 euc2004_sjis2004
 
+$(recurse)
+
 # conversion_name source_encoding destination_encoding function object
 CONVERSIONS = \
 		ascii_to_mic	SQL_ASCII MULE_INTERNAL ascii_to_mic ascii_and_mic \
 		shift_jis_2004_to_euc_jis_2004 SHIFT_JIS_2004 EUC_JIS_2004 shift_jis_2004_to_euc_jis_2004 euc2004_sjis2004
 
 all: $(SQLSCRIPT)
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
 
 $(SQLSCRIPT): Makefile
 ifeq ($(enable_shared), yes)
 
 install: $(SQLSCRIPT) installdirs
 	$(INSTALL_DATA) $(SQLSCRIPT) '$(DESTDIR)$(datadir)'
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
 
 installdirs:
 	$(MKDIR_P) '$(DESTDIR)$(datadir)' '$(DESTDIR)$(pkglibdir)'
 
 uninstall:
 	rm -f '$(DESTDIR)$(datadir)/$(SQLSCRIPT)'
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
 
 clean distclean maintainer-clean:
 	rm -f $(SQLSCRIPT)
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
 SUBDIRS+=pgevent
 endif
 
-all install installdirs uninstall distprep clean distclean maintainer-clean:
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
+$(recurse)

src/bin/initdb/Makefile

 
 OBJS=	initdb.o encnames.o pqsignal.o $(WIN32RES)
 
-all: submake-libpgport initdb
+all: initdb
 
-initdb: $(OBJS)
+initdb: $(OBJS) | submake-libpgport
 	$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 # We used to pull in all of libpq to get encnames and pqsignal, but that

src/bin/pg_config/Makefile

 override CPPFLAGS += -DVAL_LDFLAGS_SL="\"$(LDFLAGS_SL)\""
 override CPPFLAGS += -DVAL_LIBS="\"$(LIBS)\""
 
-all: submake-libpgport pg_config
+all: pg_config
 
-pg_config: $(OBJS)
+pg_config: $(OBJS) | submake-libpgport
 	$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs

src/bin/pg_controldata/Makefile

 
 OBJS= pg_controldata.o pg_crc.o $(WIN32RES)
 
-all: submake-libpgport pg_controldata
+all: pg_controldata
 
-pg_controldata: $(OBJS)
+pg_controldata: $(OBJS) | submake-libpgport
 	$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 pg_crc.c: $(top_srcdir)/src/backend/utils/hash/pg_crc.c

src/bin/pg_ctl/Makefile

 
 OBJS=	pg_ctl.o $(WIN32RES)
 
-all: submake-libpq submake-libpgport pg_ctl
+all: pg_ctl
 
-pg_ctl: $(OBJS) $(libpq_builddir)/libpq.a
+pg_ctl: $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs

src/bin/pg_dump/Makefile

 kwlookup.c: % : $(top_srcdir)/src/backend/parser/%
 	rm -f $@ && $(LN_S) $< .
 
-all: submake-libpq submake-libpgport pg_dump pg_restore pg_dumpall
+all: pg_dump pg_restore pg_dumpall
 
-pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) $(libpq_builddir)/libpq.a 
+pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_dump.o common.o pg_dump_sort.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) $(libpq_builddir)/libpq.a
+pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(libpq_builddir)/libpq.a
+pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs

src/bin/pg_resetxlog/Makefile

 
 OBJS= pg_resetxlog.o pg_crc.o $(WIN32RES)
 
-all: submake-libpgport pg_resetxlog
+all: pg_resetxlog
 
-pg_resetxlog: $(OBJS)
+pg_resetxlog: $(OBJS) | submake-libpgport
 	$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 pg_crc.c: $(top_srcdir)/src/backend/utils/hash/pg_crc.c

src/bin/psql/Makefile

 FLEXFLAGS = -Cfe
 
 
-all: submake-libpq submake-libpgport psql
+all: psql
 
-psql: $(OBJS) $(libpq_builddir)/libpq.a
+psql: $(OBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 help.o: sql_help.h

src/bin/scripts/Makefile

 
 override CPPFLAGS := -I$(top_srcdir)/src/bin/pg_dump -I$(top_srcdir)/src/bin/psql -I$(libpq_srcdir) $(CPPFLAGS)
 
-all: submake-libpq $(PROGRAMS)
+all: $(PROGRAMS)
 
 %: %.o $(WIN32RES)
 	$(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-createdb: createdb.o common.o dumputils.o kwlookup.o keywords.o
-createlang: createlang.o common.o print.o mbprint.o
-createuser: createuser.o common.o dumputils.o kwlookup.o keywords.o
-dropdb: dropdb.o common.o dumputils.o kwlookup.o keywords.o
-droplang: droplang.o common.o print.o mbprint.o
-dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o
-clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o
-vacuumdb: vacuumdb.o common.o
-reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o
+createdb: createdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
+createlang: createlang.o common.o print.o mbprint.o | submake-libpq
+createuser: createuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
+dropdb: dropdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
+droplang: droplang.o common.o print.o mbprint.o | submake-libpq
+dropuser: dropuser.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
+clusterdb: clusterdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
+vacuumdb: vacuumdb.o common.o | submake-libpq
+reindexdb: reindexdb.o common.o dumputils.o kwlookup.o keywords.o | submake-libpq
 
 dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/%
 	rm -f $@ && $(LN_S) $< .

src/interfaces/Makefile

 
 SUBDIRS = libpq ecpg
 
-all install installdirs uninstall distprep clean distclean maintainer-clean:
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
+$(recurse)

src/interfaces/ecpg/Makefile

 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-all install installdirs uninstall distprep:
-	$(MAKE) -C include $@
-	$(MAKE) -C pgtypeslib $@
-	$(MAKE) -C ecpglib $@
-	$(MAKE) -C compatlib $@
-	$(MAKE) -C preproc $@
+SUBDIRS = include pgtypeslib ecpglib compatlib preproc
+
+$(recurse)
+
+all-compatlib-recursive: all-ecpglib-recursive
 
 clean distclean maintainer-clean:
-	$(MAKE) -C include $@
-	$(MAKE) -C pgtypeslib $@
-	$(MAKE) -C ecpglib $@
-	$(MAKE) -C compatlib $@
-	$(MAKE) -C preproc $@
 	$(MAKE) -C test clean
 
 check checktcp installcheck: all

src/interfaces/ecpg/compatlib/Makefile

 
 SHLIB_LINK = -L../ecpglib -lecpg -L../pgtypeslib -lpgtypes $(libpq) \
 	$(filter -lintl -lm, $(LIBS)) $(PTHREAD_LIBS)
+SHLIB_PREREQS = submake-ecpglib submake-pgtypeslib
 
 SHLIB_EXPORTS = exports.txt
 
 
 all: all-lib
 
+.PHONY: submake-ecpglib submake-pgtypeslib
+
+submake-ecpglib:
+	$(MAKE) -C $(top_builddir)/src/interfaces/ecpg/ecpglib all
+
+submake-pgtypeslib:
+	$(MAKE) -C $(top_builddir)/src/interfaces/ecpg/pgtypeslib all
+
 # Shared library stuff
 include $(top_srcdir)/src/Makefile.shlib
 

src/interfaces/ecpg/ecpglib/Makefile

 endif
 
 SHLIB_LINK = -L../pgtypeslib -lpgtypes $(libpq) $(filter -lintl -lm, $(LIBS)) $(PTHREAD_LIBS)
+SHLIB_PREREQS = submake-libpq submake-pgtypeslib
 
 SHLIB_EXPORTS = exports.txt
 
 SHLIB_LINK += -lshfolder
 endif
 
-all: libpq pgtypeslib all-lib
+all: all-lib
 
-libpq:
-	$(MAKE) -C $(top_builddir)/src/interfaces/libpq all
-
-pgtypeslib:
+.PHONY: submake-pgtypeslib
+submake-pgtypeslib:
 	$(MAKE) -C $(top_builddir)/src/interfaces/ecpg/pgtypeslib all
 
 # Shared library stuff

src/interfaces/ecpg/preproc/Makefile

 	keywords.o c_keywords.o ecpg_keywords.o kwlookup.o ../ecpglib/typename.o descriptor.o variable.o \
 	$(WIN32RES)
 
-all: submake-libpgport ecpg
+all: ecpg
 
-ecpg: $(OBJS)
+ecpg: $(OBJS) | submake-libpgport
 	$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_EX) $^ $(LIBS) $(PTHREAD_LIBS) -o $@$(X)
 
+../ecpglib/typename.o: ../ecpglib/typename.c
+	$(MAKE) -C $(dir $@) $(notdir $@)
+
 # pgc is compiled as part of preproc
 preproc.o: pgc.c
 
 SUBDIRS += tcl
 endif
 
-all install installdirs uninstall distprep clean distclean maintainer-clean:
-	@for dir in $(SUBDIRS); do $(MAKE) -C $$dir $@ || exit; done
-
-# We'd like check operations to run all the subtests before failing.
-check installcheck:
-	@CHECKERR=0; for dir in $(SUBDIRS); do \
-		$(MAKE) -C $$dir $@ || CHECKERR=$$?; \
-	done; \
-	exit $$CHECKERR
+$(recurse)

src/test/regress/GNUmakefile

 
 # Build regression test driver
 
-all: submake-libpgport pg_regress$(X)
+all: pg_regress$(X)
 
-pg_regress$(X): pg_regress.o pg_regress_main.o
+pg_regress$(X): pg_regress.o pg_regress_main.o | submake-libpgport
 	$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@
 
 # dependencies ensure that path changes propagate
 
 # Tablespace setup
 
-all: tablespace-setup
-
 .PHONY: tablespace-setup
 tablespace-setup:
 	rm -rf ./testtablespace
 
 pg_regress_call = ./pg_regress --inputdir=$(srcdir) --dlpath=. --multibyte=$(MULTIBYTE) $(NOLOCALE)
 
-check: all
+check: all tablespace-setup
 	$(pg_regress_call) --temp-install=./tmp_check --top-builddir=$(top_builddir) --schedule=$(srcdir)/parallel_schedule $(MAXCONNOPT) $(TEMP_CONF)
 
-installcheck: all
+installcheck: all tablespace-setup
 	$(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=$(srcdir)/serial_schedule
 
-installcheck-parallel: all
+installcheck-parallel: all tablespace-setup
 	$(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=$(srcdir)/parallel_schedule $(MAXCONNOPT)
 
 standbycheck: all
 runtest: installcheck
 runtest-parallel: installcheck-parallel
 
-bigtest: all
+bigtest: all tablespace-setup
 	$(pg_regress_call) --psqldir=$(PSQLDIR) --schedule=$(srcdir)/serial_schedule numeric_big 
 
-bigcheck: all
+bigcheck: all tablespace-setup
 	$(pg_regress_call) --temp-install=./tmp_check --top-builddir=$(top_builddir) --schedule=$(srcdir)/parallel_schedule $(MAXCONNOPT) numeric_big
 
 

src/timezone/Makefile

 include $(top_srcdir)/src/backend/common.mk
 
 ifeq (,$(with_system_tzdata))
-all: submake-libpgport zic
+all: zic
 endif
 
 # We could do this test in the action section:
 ZIC= ./zic
 endif
 
-zic: $(ZICOBJS)
+zic: $(ZICOBJS) | submake-libpgport
 	$(CC) $(CFLAGS) $(ZICOBJS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs

src/tools/findoidjoins/Makefile

 
 OBJS= findoidjoins.o
 
-all: submake-libpq submake-libpgport findoidjoins
+all: findoidjoins
 
-findoidjoins: findoidjoins.o $(libpq_builddir)/libpq.a
+findoidjoins: findoidjoins.o | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) findoidjoins.o $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 clean distclean maintainer-clean:

src/tools/fsync/Makefile

 
 OBJS= test_fsync.o
 
-all: submake-libpq submake-libpgport test_fsync
+all: test_fsync
 
-test_fsync: test_fsync.o $(libpq_builddir)/libpq.a
+test_fsync: test_fsync.o | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) test_fsync.o $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 clean distclean maintainer-clean: