One of the main motivations for writing makepp was to make it easy to do reliable builds involving multiple makefiles scattered across several directories. Makepp avoids the problems associated with recursive makes and is much easier to use. It also continues to support the old kludgy way of invoking make recursively, though this is deprecated.
For a discussion of why recursive invocations of make are not encouraged, see the section on recursive make in legacy makefiles.
Makepp's solution is to load all makefiles into the same make process. This way, cross-makefile dependencies can be accurately expressed. Each makefile needs simply to refer to the files it needs, and if these files are built by other makefiles, makepp figures that out automatically. It mixes rules from different makefiles, first executing a rule from one makefile and then a rule from a different makefile, as necessary.
The separate makefiles do not interfere with each other (unless they contain conflicting rules for building the same file) because makepp keeps all variables local to each makefile. It also tags each rule with the directory its makefile was found in, and automatically cd's to that directory before executing the rule.
Each makefile can be written entirely independently of the
others. No makefile needs to know anything about the other
makefiles (unless it explicitly has to load them; see below). In
general (unless you use the -f
option to specify the
location of the makefile), the makefile may assume that all shell
commands are executed with the default directory as the directory
that contains the makefile; it does not have to know where the top
level makefile for the build is. In fact, makefiles which were not
originally designed to work together will usually work together
seamlessly.
The only restriction that this architecture places on makefiles is that there can be only one makefile per directory. Makepp will give an error message if you try to load two makefiles for the same directory. This is for technical internal reasons (the phony targets would get confused).
How does makepp figure out which makefiles are needed? There are two ways (besides explicit invocation of recursive make, which is discouraged): it can guess where the makefiles are, or you can tell it explicitly.
The simplest way of building a system that spans multiple
directories is to allow makepp to figure out automatically
which makefiles need to be loaded. If makepp needs to use
a file, and there is currently no build command known for the
file, makepp first looks in the directory that contains or
will contain that file to see if there is a makefile there. It
first looks for Makeppfile
, then
makefile
, then Makefile
. If one of
these files is found, it is loaded into makepp, and any
build instructions that it contains are now available.
Makepp does not attempt to load makefiles from directories which are not writable. This is because it couldn't build files in such directories anyway, and it assumes that they won't change since the user running makepp can't write to them.
You can also tell makepp to ignore makefiles in
directories by using the no_implicit_load
statment in one of your makefiles. This can be useful if you don't
want to spend the time building a large sub-project which you know
hasn't changed, or if one of your directories contains a file called
"makefile" but it's for some other version of make and contains
directives that makepp does not understand.
Since most existing makefiles are designed to produce output files in the same directory as the makefile, this rule usually finds the relevant build instructions.
Implicit makefile loading can make builds that span even many directories quite simple. Each directory simply needs to contain a makefile that builds anything which is supposed to be contained in that directory. If any other makefile needs to access a file in that directory, it simply lists it in a dependency list; makepp then automatically figures out that it needs to read in another makefile.
For a concrete example of this, see the tutorial section on working with multiple directories.
Implicit loading will not work for you if:
Makeppfile
,
makefile
, or Makefile
. (But why did
you pick such a strange name for your makefile?)
If any of these are true, then you need to use the
load_makefile
statement.
Sometimes implicit makefile loading loads too many makefiles.
For example, if you have many directories which contain makefiles,
but they just contain libraries which are never modified and never
need to be recompiled, then there is no real reason for
makepp to load the makefiles from those directories. You can
make the directories non-writable, or turn off implicit makefile
loading altogether by adding the -noimplicit-load
option to the command line, or turn it off on a
directory-by-directory basis by using the no_implicit_load
statement in one of your makefiles.
Implicit makefile loading is also automatically turned off if
makepp sees a reference to $(MAKE)
anywhere in
your makefile. $(MAKE)
is used for recursive make
invocations in old makefiles. If makepp sees
$(MAKE)
, it assumes that directories are taken care of
explicitly by recursive invocations of make. Experience shows that
implicit loading often gets in the way for legacy makefiles that use
recursive make, and so makepp turns it off.
load_makefile subdir1/Makefile /other/dir/Makeppfile load_makefile VAR=value dir1 dir2
(See the section on makefile syntax for the syntax.)
This causes makepp to load the rules in the specified makefile(s). You must use this statement if:
If you have implicit makefile loading turned on, and you are
using the load_makefile
statement because you need to
override a variable in the other makefile, then the
load_makefile
statement must occur before any rules
that depend on files that the other makefile builds. Otherwise, the
makefile will first be implicitly loaded, and then when you try to
load the makefile again with a different set of variables,
makepp will detect this and give you an error message.