makepp was designed to be as close as possible to GNU make. However, because of the difference in philosophy, some of GNU make's features cannot be supported; others have not been implemented because I haven't had time. Also, in order to emulate GNU make's behavior precisely, you may in some cases have to add additional command line options to the makepp command line, as noted below. Most of the differences from GNU make are quite technical and only rarely cause problems.
Makepp will give warning messages for many things which
the traditional unix make accepts without flinching. This is
because there are better ways to do them with makepp. If
these warnings annoy you, you can turn them off with the --nowarn
command line option.
xyz.o: CFLAGS := -g
VPATH
variable is currently ignored.
vpath
statements are unsupported and will cause
errors. Use repositories
instead.
--percent-subdirs
option,
in its subdirectories). This means that a rule like this:
%.o: %.c $(CC) $(CFLAGS) -c $(input) -o $(output)
will not be applied to files like
../shared/xyz.c
.
$%
,
$(%D)
, and $(%F)
.
--norc-substitution
.
include
statement unless the makefile contains
a rule for building them before the include statement is seen.
(It will attempt to rebuild the makefile itself, however.)
SHELL
variable is currently ignored.
makepp always uses /bin/sh
.
$?
is equivalent to $+
. See the
section on automatic
variables for the reasons.
.INTERMEDIATE
, .SECONDARY
, and
.PRECIOUS
are ignored.
The only special target that is supported is
.PHONY
. The remaining are simply ingored.
Specifically, GNU make has the following special targets:
.SUFFIXES
.SUFFIXES
except for the
special case of .SUFFIXES
with no dependencies,
like this:
.SUFFIXES:
which tells it not to load any of its default rules.
.INTERMEDIATE
, .SECONDARY
, .PRECIOUS
.IGNORE
ignore_error
(or a minus sign) in front
of the command whose exit status is to be ignored.
.SILENT
Put the word noecho
(or the @
character) in front of the command which is not supposed to
be echoed.
.DELETE_ON_ERROR
.EXPORT_ALL_VARIABLES
.NOEXPORT
These targets are not supported and are simply ignored.
.POSIX
.DEFAULT
origin
, call
,
error
, and warning
.
$(wildcard )
function matches not only
files which exist, but also files which do not yet exist, but
which have a rule which makepp has seen at the time the
$(wildcard )
function is evaluated.
override
statement is not supported.
-include
will not attempt to make the include file
if it doesn't exist. Also, if the file exists but is out of
date with respect to its dependencies, it will not be remade; it
is not considered an implicit target.
This is usually used for files containing dependency
information, and since makepp is able to compute a lot of
this without depending on additional tools,
-include
is not as important as it used to be.
The makefile itself is ordinarily considered an implicit target. It will be rebuilt and reread if any of its dependencies have changed since the last time makepp rebuilt it.
define
statement) are not supported.
MAKEOVERRIDES
MFLAGS
MAKELEVEL
MAKEFILES
By default, %
in a pattern rule does not match
directories. Thus %.c
matches only .c
files in the current directory. If you want it to match files in
subdirectories too, then add the --percent-subdirs
option to the command line. You can also enable this in your
makefile by the assignment percent_subdirs=1
.
By default, makepp will attempt to rebuild all targets if any of the dependencies have
changed since the last build, or if the command has changed.
This is normally what you want. Sometimes, however, you don't want
the target to be rebuilt if it has been modified apart from the
control of makepp (e.g., by editing it, or by running a
program manually to make the file). You can force makepp to
use the traditional make algorithm, which only rebuilds if any of
the targets are newer than the dependencies, by adding the option -m target_newer
to the command line.
As a special exception, any targets which are built while
rebuilding the makefile are automatically checked using the
target_newer
method in order to avoid problems with
configure procedures.
Recursive invocations of make are often considered to be an
unsafe practice (see the section on recursive
make in the discussion of deprecated idioms), but they are
extremely common in existing makefiles. Makepp supports
recursive make for backward compatibility; for new makefiles, it is
much better to use the load_makefile
statement, or makepp's implicit makefile loading
mechanism.
Sometimes recursive make invocations set variables on the command line:
target: dependencies cd subdir && $(MAKE) VAR=val VAR2=val2 some-other-target
If you do this, you may have to add the --noimplicit-load
option to the command line to avoid conflicts between what the
parent process and the child process think the build rules are.
In order to be able to use repositories for variant builds, and to help make recursive invocations of make safter, makepp normally does not actually invoke itself recursively even if you tell it to. Instead, a subprocess communicates with the parent process, and the actual build is done by the parent process.
This works in most cases, but there are a few incompatibilities.
(All of these incompatibilities are removed by adding the --traditional-recursive-make
option to the command line.)
target: dependencies $(MAKE) -f other_makefile targets
However, this will work:
target: dependencies cd subdir && $(MAKE) -f other_makefile targets
MAKEFLAGS
variable is not set up, and
altering it has no effect.
This may seem like a long list of restrictions, but many
makefiles obey them. For example, as far as I know, all makefiles
produced by automake
follow these restrictions.
All of these restrictions go away if you add the
--traditional-recursive-make
option to the command
line, but that has the following undesirable side effects:
Even with the --traditional-recursive-make
option,
there are a few remaining incompatibilities:
MAKEOVERRIDES
and
MFLAGS
not set up, and are ignored.
Rc-style substitution is the default way makepp performs variable substitution into text strings because it very rarely breaks legacy makefiles and is often useful in new makefiles. However, it does introduce occasional incompatibilities in the substitution of variables not surrounded by spaces. For example,
INCLUDE_PREFIX := -I/some/include/dir -I INCLUDES := $(INCLUDE_PREFIX)/other/include/dir
will set INCLUDES
to
-I/some/include/dir/other/include/dir -I/other/include/dirif rc-style substitution is enabled, whereas GNU make would set it to
-I/some/include/dir -I/other/include/dir
There is also an incompatibility in the handling of whitespace in a variable:
null := T := -o $(null) # T contains -o followed by one space. OUTFILE = $(T)outfile
will set OUTFILE
to -ooutfile
if
rc-style substitution is enabled, whereas GNU make would set it to
-o outfile
.
Both of these incompatibilities are removed by the --norc-substitution
option. Note, however, that even with
--norc-substitution
, makepp still treats whitespace
incompatibly in some situations:
T := -o # Don't delete this comment.
GNU make sets T
to contain -o
followed
by a space, whereas makepp strips out the trailing space
anyway. If you want the trailing space, you must specify
--norc-substitution
and also set T
using
the technique involving a dummy variable such as null
,
as shown above.
At present, you may not combine single character options into a
single word. E.g., you may not say
makepp -ejk 2
instead of
makepp -e -j 2 -k
.
Makepp supports a few of make's more useful command line options. The following, however, are not supported, and are ignored after a warning message is printed:
-d
(--debug
)
-i
-I
-l
(--load-average
or
--max-load
)
-n
(--just-print
,
--dry-run
, or --recon
)
-o
(--old-file
or
--assume-old
)
-p
(--print-data-base
)
-q
(--question
)
--no-builtin-rules
)
-R
(--no-builtin-variables
)
-S
(--no-keep-going
or --stop
)
-t
(--touch
)
-w
(--print-directory
)
--no-print-directory
-W
(--what-if
or
--new-file
or --assume-new
)
--warn-undefined-variables
Some of these can be easily supported if anyone cares.
Note that the -q
option at present actually does
something different--it suppresses some of makepp's chatty
informational messages.
The -m
option also has a different function.