Implemented new API (serial-subdirectories.make and parallel-subdirectories.make) to build subdirectories. aggregate.make is still available for backwards compatibility

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/tools/make/trunk@29592 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Nicola Pero 2010-02-12 22:00:05 +00:00
parent 8341b5cbae
commit 8275342570
13 changed files with 482 additions and 248 deletions

View file

@ -1,3 +1,29 @@
2010-02-12 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented new API to build subdirectories. aggregate.make is
still available for backwards-compatibility, but moving forward
serial-subdirectories.make and parallel-subdirectories.make will
be used (and can be mixed in the same GNUmakefile!) to build
subdirectories, clearly specifying if subdirectories are to build
serially or in parallel.
* aggregate.make: File rewritten to be a wrapper around
serial-subdirectories.make and parallel-subdirectories.make
* parallel-subdirectories.make: New file.
* serial-subdirectories.make: New file.
* Master/aggregate.make: File removed.
* Master/parallel-subdirectories.make: New file.
* Master/serial-subdirectories.make: New file.
* messages.make (ECHO_MAKING_OPERATION_IN_DIRECTORY): New message
used by the new subdirectories code.
* GNUmakefile.in (MAKE_FILES, MASTER_MAKE_FILES): Updated lists of
makefiles.
* Documentation/releasenotes.texi: Updated with new changes.
Also, refer to the next release as 2.4.0 instead of 2.2.1.
* Documentation/news.texi: Same changes.
* RELEASENOTES: Regenerated.
* NEWS: Regenerated.
2010-02-12 Nicola Pero <nicola.pero@meta-innovation.com>
Implemented parallel building of aggregate projects. Whenever you

View file

@ -9,9 +9,12 @@
The currently released version is @samp{@value{GNUSTEP-MAKE-VERSION}}.
@end ifclear
@section Changes in version @samp{2.2.1}
@section Changes in version @samp{2.4.0}
@itemize @bullet
@item New serial-subdirectories.make and parallel-subdirectories.make.
@item Support for parallel building of subdirectories.
@item Support for parallel building of different instances.
@item Support source files in subdirectories without using a subproject.
@item Support header files in sub-subdirectories.
@item Batch-compile Java files (much faster).

View file

@ -4,14 +4,52 @@ The release notes include descriptions of API changes, behavior
changes and other information that might help developers and users
migrate to using a newer version of the make system.
@section Version 2.2.1
@section Version 2.4.0
@table @samp
@item javadoc is run in quiet mode
Starting with version 2.4.0, javadoc is by default executed with the
-quiet option (unless messages=yes is specified), and a ``Generating
javadoc documentation...'' is printed instead.
@item new API to build subdirectories
Before version 2.4.0, aggregate.make was used to step into
subdirectories and build them. It did not support parallel building.
Starting with version 2.4.0, two new makefile fragments have been
introduced: serial-subdirectories.make and
parallel-subdirectories.make. These can be used to build
subdirectories, and encourage (indeed, force) the developer to
explicitly decide if the subdirectories are to be built serially, or
in parallel.
Using parallel-subdirectories.make often produces massively faster
builds (or installs or cleans) during a parallel build on a multicore
machine. But if you use parallel-subdirectories.make, you need to
make sure the different subdirectories are completely independent of
each other. One non-obvious race condition that you may to consider
is the creation of installation directories. If you have two
subdirectories, built in parallel, which install into the same custom
installation directory, there may be a race condition (ie, a
concurrency problem) when you install as they both try to create the
installation directory. In that case, you should manually create the
directory in your top-level GNUmakefile using a 'before-install::'
rule.
aggregate.make is still available if you want or need to be
backwards-compatible with older versions of gnustep-make. It is
normally a wrapper around serial-subdirectories.make, but if you
specify 'GNUSTEP_USE_PARALLEL_AGGREGATE = yes' in your GNUmakefile, it
becomes a wrapper around parallel-subdirectories.make. aggregate.make
will be deprecated in 2012 and removed in 2015, but for the next
couple of years it might be a good solution while you wait for your
users to upgrade their gnustep-make installations.
@item each instance stores object files in its own subdirectory
Before version 2.2.1, there was a single object directory where all
Before version 2.4.0, there was a single object directory where all
object files where stored. In the most common case, this directory
was simply ./obj, so if you compiled file source.m, you'd end up with
./obj/source.m.o. Starting with version 2.2.1, different instances
./obj/source.m.o. Starting with version 2.4.0, different instances
store their object files in different subdirectories; for example, if
the file was compiled as part of tool ToolA, it would end up in
./obj/ToolA.obj/source.m.o, while if compiled as part of ToolB, it
@ -32,37 +70,50 @@ specific instance. It's hard to imagine a situation where this change
of private internals would affect any user; but people with their own
private gnustep-make forks or advanced extensions might be affected.
@item the order in which tools are built is no longer guaranteed
If you use something like ``TOOL_NAME = ToolA ToolB'' to build
multiple tools in the same GNUmakefile, you need to be aware that the
way the tools are built changed in version 2.2.1. Before version
2.2.1, the tools were always built one after the other one, exactly in
the order specified. So, in the example ToolA would be built before
ToolB. Starting with 2.2.1, the tools might be built completely in
parallel if parallel building is enabled. So, the order in which they
are built is no longer defined and your GNUmakefile should not depend
on the order in which tools are specified in the GNUmakefile. Most
GNUmakefiles should be unaffected because rarely people rely on the
order in which tools are built. If your GNUmakefile does depend on
the order in which tools are built, you have a few options. The
preferred option is to identify the code or steps that need to be
executed before some of the tools are built and put them into a
@item the order in which instances are built is no longer guaranteed
If you build more than one tool in the same GNUmakefile by listing
them all in TOOL_NAME as in ``TOOL_NAME = ToolA ToolB', you need to be
aware that the way the instances are built changed in version 2.4.0.
This change affects applications, bundles, ctools, clibraries,
libraries, services, palettes, test-applications, test-libraries,
test-tools, tools. It does not affect Java, resource sets or
documentation. [FIXME: frameworks ?]
Before version 2.4.0, instances were always built one after the other
one, exactly in the order specified. So, in the example ToolA would
be built before ToolB. Starting with 2.4.0, the instances might be
built completely in parallel if parallel building is enabled. So, the
order in which they are built is no longer defined and your
GNUmakefile should not depend on the order in which instances are
specified in the GNUmakefile. Most GNUmakefiles should be unaffected
because they rarely rely on the order in which instances are built.
If your GNUmakefile does depend on the order, you have a few options.
The preferred option is to identify the code or steps that need to be
executed before some of the instances are built and put them into a
before-all:: rule, which is guaranteed to be executed before anything
else. In this way your serialized code is executed first, and the
build can continue in a completely parallel fashion afterwards.
If you just want to force a specific tool (say, ToolA) to be
built before the others, you can always add a 'before-all:: ToolA'
rule which will make sure ToolA is built before the other ones.
Another option is to move your instances into separate subdirectories,
and use serial-subdirectories.make to build them.
serial-subdirectories.make will respect the order and always build
them in the order you require.
If you want to disable parallel building altogether, you can add
GNUSTEP_MAKE_PARALLEL_BUILDING=no just after including common.make, or
pass it on the command-line.
GNUSTEP_MAKE_PARALLEL_BUILDING=no just after including common.make to
prevent a specific GNUmakefile from doing a parallel build.
Please note that this does not affect the relationship between
instances of different types; if you include library.make before
tool.make, for example, the library (or libraries) will still be built
before the tool (or tools). It is the order in which the libraries
(or tools) are built that is no longer guaranteed.
@item support for having source files in subdirectories
Starting with version 2.2.1, it is possible to put source files in
Starting with version 2.4.0, it is possible to put source files in
subdirectories by specifiying them as in xxx_OBJC_FILES =
Source/Beauty.m. This syntax does not work on versions before 2.2.1
Source/Beauty.m. This syntax does not work on versions before 2.4.0
so you should not use it if you want to support older versions of
gnustep-make; previously you had to create a subproject and add a
GNUmakefile in the subdirectory using subproject.make. You can now
@ -70,21 +121,21 @@ spread your source files in multiple subdirectories without using
subprojects.
@item support for having header files in subdirectories
Starting with version 2.2.1, it is possible to put header files in
Starting with version 2.4.0, it is possible to put header files in
subdirectories by specifiying them as in xxx_HEADER_FILES =
Beauty/Beauty.h. This syntax does not work on versions before 2.2.1
Beauty/Beauty.h. This syntax does not work on versions before 2.4.0
so you should not use it if you want to support older versions of
gnustep-make. When headers are put in subdirectories specified in
this way, corresponding subdirectories are created when the header
files are installed. For example Beauty/Beauty.h would be
automatically installed into
GNUSTEP_HEADERS/HEADER_FILES_INSTALL_DIR/Beauty/Beauty.h. To get the
same result in versions before 2.2.1 you would have had to manually
same result in versions before 2.4.0 you would have had to manually
create the header installation subdirectories.
@item support for HEADER_FILES_DIR in framework subproject
Before version 2.2.1, specifying xxx_HEADER_FILES_DIR in a framework
subproject would have no effect. Starting with version 2.2.1, the
Before version 2.4.0, specifying xxx_HEADER_FILES_DIR in a framework
subproject would have no effect. Starting with version 2.4.0, the
variable is now recognized and can be used to have the files in a
subdirectory. You should avoid using the variable in framework
subprojects if you want to support older versions of gnustep-make.
@ -101,7 +152,7 @@ that subdirectory and install it.
@item better cleaning for texinfo documentation
When you build html documentation from texinfo files, the local
directory containing the html files was not being removed when doing a
'make clean'. Starting with version 2.2.1, 'make clean' removes the
'make clean'. Starting with version 2.4.0, 'make clean' removes the
directory too.
@item debug=no made the default
@ -117,7 +168,7 @@ all object files when they are installed.
@item batch-compilation of Java files
gnustep-make used to compile Java files one by one. In most Java
compilers this is very suboptimal. Starting from release 2.2.1,
compilers this is very suboptimal. Starting from release 2.4.0,
gnustep-make will compile all Java files in a Java project with a
single Java compiler invocation. This can significantly speed up
compilation of large projects. To disable it and get the behaviour of

View file

@ -107,7 +107,8 @@ SVNPREFIX=svn+ssh://svn.gna.org/svn/gnustep/tools/make
MAKE_FILES = aggregate.make application.make bundle.make service.make \
common.make empty.make library-combo.make java.make jni.make library.make \
messages.make rules.make target.make names.make resource-set.make \
messages.make parallel-subdirectories.make rules.make serial-subdirectories.make \
target.make names.make resource-set.make \
tool.make ctool.make test-library.make \
objc.make test-application.make test-tool.make subproject.make \
palette.make gswapp.make gswbundle.make clibrary.make \
@ -116,11 +117,12 @@ MAKE_FILES = aggregate.make application.make bundle.make service.make \
tar-exclude-list gnustep-make-help
MASTER_MAKE_FILES = \
aggregate.make source-distribution.make rpm.make rules.make \
source-distribution.make rpm.make rules.make \
application.make bundle.make clibrary.make ctool.make \
documentation.make framework.make gswapp.make gswbundle.make \
library.make nsis.make objc.make java.make java-tool.make palette.make \
resource-set.make service.make subproject.make test-application.make \
parallel-subdirectories.make resource-set.make serial-subdirectories.make \
service.make subproject.make test-application.make \
test-library.make test-tool.make tool.make
INSTANCE_MAKE_FILES = \

View file

@ -1,172 +0,0 @@
# -*-makefile-*-
# aggregate.make
#
# Master Makefile rules to build a set of GNUstep-base subprojects.
#
# Copyright (C) 1997-2010 Free Software Foundation, Inc.
#
# Author: Scott Christley <scottc@net-community.com>
# Author: Ovidiu Predescu <ovidiu@net-community.com>
# Author: Nicola Pero <nicola.pero@meta-innovation.com>
#
# This file is part of the GNUstep Makefile Package.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# You should have received a copy of the GNU General Public
# License along with this library; see the file COPYING.
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
ifeq ($(RULES_MAKE_LOADED),)
include $(GNUSTEP_MAKEFILES)/rules.make
endif
#
# The list of aggregate project directory names is in the makefile
# variable SUBPROJECTS. The name is unforunate, because it is confusingly
# similar to xxx_SUBPROJECTS, which is used for subprojects.
#
# For this reason, long term we'd like to replace the variable
# SUBPROJECTS with the variable AGGREGATE_PROJECTS. As of February
# 2010, we can't just do it without breaking all GNUmakefiles. So in
# February 2010, we added AGGREGATE_PROJECTS, so that gnustep-make now
# recognizes AGGREGATE_PROJECTS as well as SUBPROJECTS. In a few
# years, when everyone is using a version of gnustep-make that does
# this, we can deprecate SUBPROJECTS and tell everyone to switch to
# AGGREGATE_PROJECTS without breaking anything :-) In other words, the
# following three lines of code are for compatibility with future
# versions of gnustep-make where the variable will be named
# AGGREGATE_PROJECTS.
AGGREGATE_PROJECTS := $(strip $(AGGREGATE_PROJECTS))
ifneq ($(AGGREGATE_PROJECTS),)
SUBPROJECTS := $(AGGREGATE_PROJECTS)
endif
# SUBPROJECTS - which is implemented in this file - are just a list of
# directories; we step in each directory in turn, and run a submake in
# there. The project types in the directories can be anything -
# tools, documentation, libraries, bundles, applications, whatever.
# For example, if your package is composed by a library and then by
# some tools using the library, you could have the library in one
# directory, the tools in another directory, and have a top level
# GNUmakefile which has the two as SUBPROJECTS.
#
# xxx_SUBPROJECTS - which is *not* implemented in this file, I'm just
# explaining it here to make clear the difference - are again a list
# of directories, each of which should contain a *subproject* project
# type (as implemented by subproject.make), which builds stuff into a
# .o file, which is then automatically linked into the xxx instance by
# gnustep-make when the top-level xxx is built. For example, a
# library might be broken into many separate subprojects, each of
# which implementing a logically separated part of the library; the
# top-level GNUmakefile will then build the library, specifying
# xxx_SUBPROJECTS for the library to be those directories.
# gnustep-make will step in all dirs, compile the subprojects, and
# then finally automatically link the subprojects into the main
# library.
SUBPROJECTS := $(strip $(SUBPROJECTS))
# Set this variable to yes to allow parallelizing the build of the
# different aggregate projects in your GNUmakefile.
ifeq ($(GNUSTEP_USE_PARALLEL_AGGREGATE), YES)
GNUSTEP_USE_PARALLEL_AGGREGATE = yes
endif
ifeq ($(GNUSTEP_MAKE_PARALLEL_BUILDING), no)
GNUSTEP_USE_PARALLEL_AGGREGATE = no
endif
ifneq ($(SUBPROJECTS),)
ifneq ($(GNUSTEP_USE_PARALLEL_AGGREGATE), yes)
# Standard, serialized build. Use a subshell.
internal-all internal-install internal-uninstall internal-clean \
internal-distclean internal-check internal-strings::
@ operation=$(subst internal-,,$@); \
abs_build_dir="$(ABS_GNUSTEP_BUILD_DIR)"; \
for f in $(SUBPROJECTS); do \
echo "Making $$operation in $$f..."; \
mf=$(MAKEFILE_NAME); \
if [ ! -f "$$f/$$mf" -a -f "$$f/Makefile" ]; then \
mf=Makefile; \
echo "WARNING: No $(MAKEFILE_NAME) found for aggregate project $$f; using 'Makefile'"; \
fi; \
if [ "$${abs_build_dir}" = "." ]; then \
gsbuild="."; \
else \
gsbuild="$${abs_build_dir}/$$f"; \
fi; \
if $(MAKE) -C $$f -f $$mf $(GNUSTEP_MAKE_NO_PRINT_DIRECTORY_FLAG) --no-keep-going $$operation \
GNUSTEP_BUILD_DIR="$$gsbuild"; then \
:; else exit $$?; \
fi; \
done
else
# Parallel build. Run a parallel submake and build all the projects
# in parallel! Warning: this will massively parallelize your build.
internal-all internal-install internal-uninstall internal-clean \
internal-distclean internal-check internal-strings::
$(ECHO_NOTHING)operation=$(subst internal-,,$@); \
$(MAKE) -f $(MAKEFILE_NAME) --no-print-directory --no-keep-going \
internal-master-aggregate-$$operation \
GNUSTEP_BUILD_DIR="$(GNUSTEP_BUILD_DIR)" \
_GNUSTEP_MAKE_PARALLEL=yes$(END_ECHO)
.PHONY: \
internal-master-aggregate-all \
internal-master-aggregate-install \
internal-master-aggregate-uninstall \
internal-master-aggregate-clean \
internal-master-aggregate-distclean \
internal-master-aggregate-check \
internal-master-aggregate-strings
internal-master-aggregate-all: $(SUBPROJECTS:=.all.aggregate)
internal-master-aggregate-install: $(SUBPROJECTS:=.install.aggregate)
internal-master-aggregate-uninstall: $(SUBPROJECTS:=.uninstall.aggregate)
internal-master-aggregate-clean: $(SUBPROJECTS:=.clean.aggregate)
internal-master-aggregate-distclean: $(SUBPROJECTS:=.distclean.aggregate)
internal-master-aggregate-check: $(SUBPROJECTS:=.check.aggregate)
internal-master-aggregate-strings: $(SUBPROJECTS:=.strings.aggregate)
# See Master/rules.make as to why we use .PRECIOUS instead of .PHONY
# here.
.PRECIOUS: %.aggregate
%.aggregate:
$(ECHO_NOTHING)instance=$(basename $*); \
operation=$(subst .,,$(suffix $*)); \
abs_build_dir="$(ABS_GNUSTEP_BUILD_DIR)"; \
echo "Making $$operation in $$instance..."; \
mf=$(MAKEFILE_NAME); \
if [ ! -f "$$instance/$$mf" -a -f "$$instance/Makefile" ]; then \
mf=Makefile; \
echo "WARNING: No $(MAKEFILE_NAME) found for aggregate project $$instance; using 'Makefile'"; \
fi; \
if [ "$${abs_build_dir}" = "." ]; then \
gsbuild="."; \
else \
gsbuild="$${abs_build_dir}/$$instance"; \
fi; \
if $(MAKE) -C $$instance -f $$mf $(GNUSTEP_MAKE_NO_PRINT_DIRECTORY_FLAG) --no-keep-going $$operation \
GNUSTEP_BUILD_DIR="$$gsbuild" _GNUSTEP_MAKE_PARALLEL=no; then \
:; else exit $$?; \
fi$(END_ECHO)
endif
endif

View file

@ -0,0 +1,99 @@
# -*-makefile-*-
# parallel-subdirectories.make
#
# Master Makefile rules to build a set of subdirectories in parallel.
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# Author: Nicola Pero <nicola.pero@meta-innovation.com>
#
# This file is part of the GNUstep Makefile Package.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# You should have received a copy of the GNU General Public
# License along with this library; see the file COPYING.
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
ifeq ($(RULES_MAKE_LOADED),)
include $(GNUSTEP_MAKEFILES)/rules.make
endif
# The list of subdirectories is in the makefile variable
# PARALLEL_SUBDIRECTORIES.
PARALLEL_SUBDIRECTORIES := $(strip $(PARALLEL_SUBDIRECTORIES))
# This file builds all the PARALLEL_SUBDIRECTORIES in parallel. It
# fires off a parallel submake invocation which starts a submake in
# each of the subdirectories. These submakes are started in parallel
# if a parallel build is being done. The project types in the
# directories can be anything - tools, documentation, libraries,
# bundles, applications, whatever. For example, if your package is
# composed by a bunch of applications and tools that can be built
# independently of each other, you can simply put them into various
# subdirectories, then have a top level GNUmakefile which has them as
# PARALLEL_SUBDIRECTORIES; they will be built in parallel, if possible
# (or in a random serial order if parallel building is not used).
#
# If you do require the subdirectories to be built in strict order,
# you can use serial-subdirectories.make which will build them in the
# specified order.
ifneq ($(PARALLEL_SUBDIRECTORIES),)
# We fire off a submake with _GNUSTEP_MAKE_PARALLEL=yes, so that that
# submake invocation will be able to build its
# 'internal-master-subdirectories-xxx' target in parallel. If the
# build is not parallel, that submake will simply build normally.
internal-all internal-install internal-uninstall \
internal-clean internal-distclean \
internal-check internal-strings::
$(ECHO_NOTHING)operation=$(subst internal-,,$@); \
$(MAKE) -f $(MAKEFILE_NAME) --no-print-directory --no-keep-going \
internal-master-subdirectories-$$operation \
GNUSTEP_BUILD_DIR="$(GNUSTEP_BUILD_DIR)" \
_GNUSTEP_MAKE_PARALLEL=yes$(END_ECHO)
.PHONY: \
internal-master-subdirectories-all \
internal-master-subdirectories-install \
internal-master-subdirectories-uninstall \
internal-master-subdirectories-clean \
internal-master-subdirectories-distclean \
internal-master-subdirectories-check \
internal-master-subdirectories-strings
internal-master-subdirectories-all: $(PARALLEL_SUBDIRECTORIES:=.all.subdirectories)
internal-master-subdirectories-install: $(PARALLEL_SUBDIRECTORIES:=.install.subdirectories)
internal-master-subdirectories-uninstall: $(PARALLEL_SUBDIRECTORIES:=.uninstall.subdirectories)
internal-master-subdirectories-clean: $(PARALLEL_SUBDIRECTORIES:=.clean.subdirectories)
internal-master-subdirectories-distclean: $(PARALLEL_SUBDIRECTORIES:=.distclean.subdirectories)
internal-master-subdirectories-check: $(PARALLEL_SUBDIRECTORIES:=.check.subdirectories)
internal-master-subdirectories-strings: $(PARALLEL_SUBDIRECTORIES:=.strings.subdirectories)
# See Master/rules.make as to why we use .PRECIOUS instead of .PHONY
# here.
.PRECIOUS: %.subdirectories
%.subdirectories:
$(ECHO_NOTHING)directory=$(basename $*); \
operation=$(subst .,,$(suffix $*)); \
abs_build_dir="$(ABS_GNUSTEP_BUILD_DIR)"; \
$(ECHO_MAKING_OPERATION_IN_DIRECTORY) \
if [ "$${abs_build_dir}" = "." ]; then \
gsbuild="."; \
else \
gsbuild="$${abs_build_dir}/$$instance"; \
fi; \
if $(MAKE) -C $$directory -f $(MAKEFILE_NAME) $(GNUSTEP_MAKE_NO_PRINT_DIRECTORY_FLAG) --no-keep-going \
$$operation \
GNUSTEP_BUILD_DIR="$$gsbuild" _GNUSTEP_MAKE_PARALLEL=no; then \
:; else exit $$?; \
fi$(END_ECHO)
endif

View file

@ -0,0 +1,69 @@
# -*-makefile-*-
# serial-subdirectories.make
#
# Master Makefile rules to build a set of subdirectories in serial sequence.
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# Author: Nicola Pero <nicola.pero@meta-innovation.com>
#
# This file is part of the GNUstep Makefile Package.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# You should have received a copy of the GNU General Public
# License along with this library; see the file COPYING.
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
ifeq ($(RULES_MAKE_LOADED),)
include $(GNUSTEP_MAKEFILES)/rules.make
endif
# The list of subdirectories is in the makefile variable
# SERIAL_SUBDIRECTORIES.
SERIAL_SUBDIRECTORIES := $(strip $(SERIAL_SUBDIRECTORIES))
# This file iterates over the SERIAL_SUBDIRECTORIES, in order, steps
# in each directory in turn, and runs a submake in there. The project
# types in the directories can be anything - tools, documentation,
# libraries, bundles, applications, whatever. For example, if your
# package is composed by a library and then by some tools using the
# library, you could have the library in one directory, the tools in
# another directory, and have a top level GNUmakefile which has the
# two as SERIAL_SUBDIRECTORIES; they will be built in the specified
# order.
#
# If you do not require the subdirectories to be built in strict
# order, you can use parallel-subdirectories.make which will
# parallelize the build of the subdirectories if possible.
ifneq ($(SERIAL_SUBDIRECTORIES),)
# We use a subshell and do the job there to minimize the number of processes we need to spawn
# to perform this job. Note that we don't need to pass _GNUSTEP_MAKE_PARALLEL=no to it (as this
# shouldn't be a parallel Master invocation), but we do it anyway for safety.
internal-all internal-install internal-uninstall \
internal-clean internal-distclean \
internal-check internal-strings::
$(ECHO_NOTHING)operation=$(subst internal-,,$@); \
abs_build_dir="$(ABS_GNUSTEP_BUILD_DIR)"; \
for directory in $(SERIAL_SUBDIRECTORIES); do \
$(ECHO_MAKING_OPERATION_IN_DIRECTORY) \
if [ "$${abs_build_dir}" = "." ]; then \
gsbuild="."; \
else \
gsbuild="$${abs_build_dir}/$$directory"; \
fi; \
if $(MAKE) -C $$directory -f $(MAKEFILE_NAME) $(GNUSTEP_MAKE_NO_PRINT_DIRECTORY_FLAG) --no-keep-going \
$$operation \
GNUSTEP_BUILD_DIR="$$gsbuild" _GNUSTEP_MAKE_PARALLEL=no; then \
:; else exit $$?; \
fi; \
done$(END_ECHO)
endif

8
NEWS
View file

@ -3,9 +3,15 @@
The currently released version is `2.2.0'.
1.1 Changes in version `2.2.1'
1.1 Changes in version `2.4.0'
==============================
* New serial-subdirectories.make and parallel-subdirectories.make.
* Support for parallel building of subdirectories.
* Support for parallel building of different instances.
* Support source files in subdirectories without using a subproject.
* Support header files in sub-subdirectories.

View file

@ -5,14 +5,52 @@ The release notes include descriptions of API changes, behavior changes
and other information that might help developers and users migrate to
using a newer version of the make system.
1.1 Version 2.2.1
1.1 Version 2.4.0
=================
`javadoc is run in quiet mode'
Starting with version 2.4.0, javadoc is by default executed with
the -quiet option (unless messages=yes is specified), and a
"Generating javadoc documentation..." is printed instead.
`new API to build subdirectories'
Before version 2.4.0, aggregate.make was used to step into
subdirectories and build them. It did not support parallel
building. Starting with version 2.4.0, two new makefile fragments
have been introduced: serial-subdirectories.make and
parallel-subdirectories.make. These can be used to build
subdirectories, and encourage (indeed, force) the developer to
explicitly decide if the subdirectories are to be built serially,
or in parallel.
Using parallel-subdirectories.make often produces massively faster
builds (or installs or cleans) during a parallel build on a
multicore machine. But if you use parallel-subdirectories.make,
you need to make sure the different subdirectories are completely
independent of each other. One non-obvious race condition that
you may to consider is the creation of installation directories.
If you have two subdirectories, built in parallel, which install
into the same custom installation directory, there may be a race
condition (ie, a concurrency problem) when you install as they
both try to create the installation directory. In that case, you
should manually create the directory in your top-level GNUmakefile
using a 'before-install::' rule.
aggregate.make is still available if you want or need to be
backwards-compatible with older versions of gnustep-make. It is
normally a wrapper around serial-subdirectories.make, but if you
specify 'GNUSTEP_USE_PARALLEL_AGGREGATE = yes' in your
GNUmakefile, it becomes a wrapper around
parallel-subdirectories.make. aggregate.make will be deprecated
in 2012 and removed in 2015, but for the next couple of years it
might be a good solution while you wait for your users to upgrade
their gnustep-make installations.
`each instance stores object files in its own subdirectory'
Before version 2.2.1, there was a single object directory where all
Before version 2.4.0, there was a single object directory where all
object files where stored. In the most common case, this directory
was simply ./obj, so if you compiled file source.m, you'd end up
with ./obj/source.m.o. Starting with version 2.2.1, different
with ./obj/source.m.o. Starting with version 2.4.0, different
instances store their object files in different subdirectories;
for example, if the file was compiled as part of tool ToolA, it
would end up in ./obj/ToolA.obj/source.m.o, while if compiled as
@ -35,61 +73,75 @@ using a newer version of the make system.
people with their own private gnustep-make forks or advanced
extensions might be affected.
`the order in which tools are built is no longer guaranteed'
If you use something like "TOOL_NAME = ToolA ToolB" to build
multiple tools in the same GNUmakefile, you need to be aware that
the way the tools are built changed in version 2.2.1. Before
version 2.2.1, the tools were always built one after the other
one, exactly in the order specified. So, in the example ToolA
would be built before ToolB. Starting with 2.2.1, the tools might
be built completely in parallel if parallel building is enabled.
So, the order in which they are built is no longer defined and
your GNUmakefile should not depend on the order in which tools are
specified in the GNUmakefile. Most GNUmakefiles should be
unaffected because rarely people rely on the order in which tools
are built. If your GNUmakefile does depend on the order in which
tools are built, you have a few options. The preferred option is
to identify the code or steps that need to be executed before some
of the tools are built and put them into a before-all:: rule,
which is guaranteed to be executed before anything else. In this
way your serialized code is executed first, and the build can
`the order in which instances are built is no longer guaranteed'
If you build more than one tool in the same GNUmakefile by listing
them all in TOOL_NAME as in "TOOL_NAME = ToolA ToolB', you need to
be aware that the way the instances are built changed in version
2.4.0.
This change affects applications, bundles, ctools, clibraries,
libraries, services, palettes, test-applications, test-libraries,
test-tools, tools. It does not affect Java, resource sets or
documentation. [FIXME: frameworks ?]
Before version 2.4.0, instances were always built one after the
other one, exactly in the order specified. So, in the example
ToolA would be built before ToolB. Starting with 2.4.0, the
instances might be built completely in parallel if parallel
building is enabled. So, the order in which they are built is no
longer defined and your GNUmakefile should not depend on the order
in which instances are specified in the GNUmakefile. Most
GNUmakefiles should be unaffected because they rarely rely on the
order in which instances are built. If your GNUmakefile does
depend on the order, you have a few options. The preferred option
is to identify the code or steps that need to be executed before
some of the instances are built and put them into a before-all::
rule, which is guaranteed to be executed before anything else. In
this way your serialized code is executed first, and the build can
continue in a completely parallel fashion afterwards.
If you just want to force a specific tool (say, ToolA) to be built
before the others, you can always add a 'before-all:: ToolA' rule
which will make sure ToolA is built before the other ones.
Another option is to move your instances into separate
subdirectories, and use serial-subdirectories.make to build them.
serial-subdirectories.make will respect the order and always build
them in the order you require.
If you want to disable parallel building altogether, you can add
GNUSTEP_MAKE_PARALLEL_BUILDING=no just after including
common.make, or pass it on the command-line.
GNUSTEP_MAKE_PARALLEL_BUILDING=no just after including common.make
to prevent a specific GNUmakefile from doing a parallel build.
Please note that this does not affect the relationship between
instances of different types; if you include library.make before
tool.make, for example, the library (or libraries) will still be
built before the tool (or tools). It is the order in which the
libraries (or tools) are built that is no longer guaranteed.
`support for having source files in subdirectories'
Starting with version 2.2.1, it is possible to put source files in
Starting with version 2.4.0, it is possible to put source files in
subdirectories by specifiying them as in xxx_OBJC_FILES =
Source/Beauty.m. This syntax does not work on versions before
2.2.1 so you should not use it if you want to support older
2.4.0 so you should not use it if you want to support older
versions of gnustep-make; previously you had to create a
subproject and add a GNUmakefile in the subdirectory using
subproject.make. You can now spread your source files in multiple
subdirectories without using subprojects.
`support for having header files in subdirectories'
Starting with version 2.2.1, it is possible to put header files in
Starting with version 2.4.0, it is possible to put header files in
subdirectories by specifiying them as in xxx_HEADER_FILES =
Beauty/Beauty.h. This syntax does not work on versions before
2.2.1 so you should not use it if you want to support older
2.4.0 so you should not use it if you want to support older
versions of gnustep-make. When headers are put in subdirectories
specified in this way, corresponding subdirectories are created
when the header files are installed. For example Beauty/Beauty.h
would be automatically installed into
GNUSTEP_HEADERS/HEADER_FILES_INSTALL_DIR/Beauty/Beauty.h. To get
the same result in versions before 2.2.1 you would have had to
the same result in versions before 2.4.0 you would have had to
manually create the header installation subdirectories.
`support for HEADER_FILES_DIR in framework subproject'
Before version 2.2.1, specifying xxx_HEADER_FILES_DIR in a
Before version 2.4.0, specifying xxx_HEADER_FILES_DIR in a
framework subproject would have no effect. Starting with version
2.2.1, the variable is now recognized and can be used to have the
2.4.0, the variable is now recognized and can be used to have the
files in a subdirectory. You should avoid using the variable in
framework subprojects if you want to support older versions of
gnustep-make.
@ -106,7 +158,7 @@ using a newer version of the make system.
`better cleaning for texinfo documentation'
When you build html documentation from texinfo files, the local
directory containing the html files was not being removed when
doing a 'make clean'. Starting with version 2.2.1, 'make clean'
doing a 'make clean'. Starting with version 2.4.0, 'make clean'
removes the directory too.
`debug=no made the default'
@ -123,7 +175,7 @@ using a newer version of the make system.
`batch-compilation of Java files'
gnustep-make used to compile Java files one by one. In most Java
compilers this is very suboptimal. Starting from release 2.2.1,
compilers this is very suboptimal. Starting from release 2.4.0,
gnustep-make will compile all Java files in a Java project with a
single Java compiler invocation. This can significantly speed up
compilation of large projects. To disable it and get the

View file

@ -1,11 +1,11 @@
#
# -*-makefile-*-
# aggregate.make
#
# Makefile rules to build a set of GNUstep-base subprojects.
#
# Copyright (C) 2002 Free Software Foundation, Inc.
# Copyright (C) 2002 - 2010 Free Software Foundation, Inc.
#
# Author: Nicola Pero <nicola@brainstorm.co.uk>
# Author: Nicola Pero <nicola.pero@meta-innovation.com>
#
# This file is part of the GNUstep Makefile Package.
#
@ -19,12 +19,35 @@
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# This header used to be the only way to build subdirectories before
# gnustep-make 2.4.0 (February 2010). You can still use it (for now)
# to maintain backwards compatibility with older versions of
# gnustep-make. It will be deprecated in February 2012, and removed
# in February 2015.
# To use it, set the SUBPROJECTS variable to the list of your
# subdirectories, and include it. To request parallel building (if
# available), set "GNUSTEP_USE_PARALLEL_AGGREGATE = yes", else serial
# building will be assumed.
# prevent multiple inclusions
ifeq ($(AGGREGATE_MAKE_LOADED),)
AGGREGATE_MAKE_LOADED=yes
ifeq ($(GNUSTEP_INSTANCE),)
include $(GNUSTEP_MAKEFILES)/Master/aggregate.make
ifeq ($(GNUSTEP_USE_PARALLEL_AGGREGATE), yes)
PARALLEL_SUBDIRECTORIES = $(SUBPROJECTS)
include $(GNUSTEP_MAKEFILES)/Master/parallel-subdirectories.make
else
SERIAL_SUBDIRECTORIES = $(SUBPROJECTS)
include $(GNUSTEP_MAKEFILES)/Master/serial-subdirectories.make
endif
endif
endif

View file

@ -88,6 +88,10 @@ ifneq ($(messages),yes)
END_ECHO = )
# Important - the following is special in that it's inside the shell
# code, not at the beginning.
ECHO_MAKING_OPERATION_IN_DIRECTORY = echo "Making $$operation in $$directory ...";
#
# Translation of messages:
#
@ -144,6 +148,8 @@ else
END_ECHO =
ECHO_MAKING_OPERATION_IN_DIRECTORY =
endif
# The following are warnings that are always displayed, no matter if

View file

@ -0,0 +1,35 @@
# -*-makefile-*-
# parallel-subdirectories.make
#
# Makefile rules to build a set of subdirectories in parallel.
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# Author: Nicola Pero <nicola.pero@meta-innovation.com>
#
# This file is part of the GNUstep Makefile Package.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# You should have received a copy of the GNU General Public
# License along with this library; see the file COPYING.
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# This header was introduced in gnustep-make 2.4.0. If you are using
# gnustep-make before 2.4.0, there is no parallel subdirectories
# support. You can use aggregate.make which is similar but does not
# build in parallel.
# prevent multiple inclusions
ifeq ($(PARALLEL_SUBDIRECTORIES_MAKE_LOADED),)
PARALLEL_SUBDIRECTORIES_MAKE_LOADED=yes
ifeq ($(GNUSTEP_INSTANCE),)
include $(GNUSTEP_MAKEFILES)/Master/parallel-subdirectories.make
endif
endif

View file

@ -0,0 +1,34 @@
# -*-makefile-*-
# serial-subdirectories.make
#
# Makefile rules to build a set of subdirectories in serial sequence.
#
# Copyright (C) 2010 Free Software Foundation, Inc.
#
# Author: Nicola Pero <nicola.pero@meta-innovation.com>
#
# This file is part of the GNUstep Makefile Package.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 3
# of the License, or (at your option) any later version.
#
# You should have received a copy of the GNU General Public
# License along with this library; see the file COPYING.
# If not, write to the Free Software Foundation,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# This header was introduced in gnustep-make 2.4.0. If you are using
# gnustep-make before 2.4.0, you can use aggregate.make which does the
# same thing.
# prevent multiple inclusions
ifeq ($(SERIAL_SUBDIRECTORIES_MAKE_LOADED),)
SERIAL_SUBDIRECTORIES_MAKE_LOADED=yes
ifeq ($(GNUSTEP_INSTANCE),)
include $(GNUSTEP_MAKEFILES)/Master/serial-subdirectories.make
endif
endif