Incompatibilities between makepp and GNU make
makepp_percent_subdirs=1-m option-traditional-recursion optionmakepp_simple_concatenation variableMakepp was designed to be as close as possible to GNU make. However, because of the difference in philosophy (see the makepp_build_algorithm manpage), some of GNU make's features cannot be supported. Others have not been implemented because we 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.
The VPATH variable is currently ignored. vpath statements are
unsupported and will cause errors. Use repositories (see
the makepp_repositories manpage) instead.
Pattern rules only match files in the directory (or if you set
makepp_percent_subdirs=1, 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.
A pattern rule present later in a makefile overrides one that is present earlier. This is backwards from GNU make.
Default rules (pattern rules with no pattern dependencies) are only supported with last_chance.
The set of builtin implicit rules (see the makepp_builtin manpage) is somewhat different from those for GNU make, though the variable names are largely compatible. The builtin rules should successfully compile C/C++/Fortran programs, and in fact may be able to guess the proper libraries in some cases too. Support for Modula-2 and RatFor and other rare languages is deliberately not present, because I kept running into problems with GNU make's rules when I accidently reused the extensions for those languages.
Archive members are not supported, and neither are the associated automatic
variables $%, $(%D), and $(%F).
Leading and trailing whitespace in variable assignments is ignored (even if the whitespace is followed by a comment). For more details on whitespace handling incompatibilities, see Whitespace in variables in the makepp_variables manpage.
Whitespace in variable names is not supported. Neither is beginning a variable name with a numeral. Words with spaces after them (and no colon on the line) are pre- or user-defined statements like
export VAR := value # Not a rule colon
override global VAR = value
repository dir=otherdir
and spaces in expressions delimit a pre- or user-defined function like
$(basename filenames) $(dir filenames) $(firstword words)
Makepp does not attempt to rebuild files included with the 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.) This is normally used for handling include file dependencies, and
is not as useful with makepp since you don't need to do that anyway.
The SHELL variable is currently partially ignored. Makepp always uses
/bin/sh unless /usr/xpg4/bin/sh or /sbin/xpg4/sh is found or unless
you export the SHELL variable in your makefile. But if you do, the command
parser might not fully understand what your shell command does. On Windows
ActiveState Perl you must instead set your SHELL variable before calling
makepp.
Dependencies of anything on the Makefile still work, but are usually unnecessary. This is usually used to force a rebuild when compilation options change. makepp knows when build commands have changed without anything special in the makefile; it stores this on a file-by-file basis. If you change the makefile, it knows exactly which files need recompilation.
Intermediate files are not deleted. (Because makepp insists on having all of
the file dates be the same as they were on the last build, intermediate files
must all be present or else rebuilds will occur.) There is no special status
accorded to intermediate files. This means that the special targets
.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:
Makepp ignores .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.
No special status is accorded to intermediate files and so these targets are not meaningful.
This target is ignored. If you want to ignore errors, put the word
ignore_error (or a minus sign) in front of the command whose exit status is
to be ignored.
This target is ignored. If you want commands not to echo, put the word
noecho (or the @ character) in front of the command which is not
supposed to be echoed, or use the --silent option to makepp.
These targets are not supported and are simply ignored.
Three GNU make functions (eval and value) are not currently
supported.
Double colon rules are not fully supported. (They cannot be: in makepp's paradigm, there cannot be more than one way to update a target.) Currently, each successive double colon rule for a given target simply appends its command string and dependency list to the command string and dependency list for this target. For example, if you write this:
a :: b
&cat b -o a
# Later in your makefile:
a :: c
&cat c -o >>a
it is exactly the same as if you had written
a : b c
&cat b -o a
&cat c -o >>a
This is certainly not what double colon rules are intended for, and it
will not always work, but it does work for targets like clean or for
all the stuff that ExtUtils::MakeMaker puts into its makefiles. Don't
count on it for anything other than legacy makefiles.
The $(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.
-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.
The define statement is supported, but handling of @ preceding it
is done differently. Currently in makepp, @ in front of a variable
which has a multi-line value will only suppress echoing of the first
line. For example,
define echo-lines
&echo line1 -o $@
&echo line2 -o>>$@
endef
x:
@$(echo-lines)
will not suppress printing of &echo line2 as it does in GNU make;
it will only suppress printing of &echo line1.
Makepp does not support the following environment variables (it does not set them up, and it just ignores them):
In makepp, rule actions are expanded before all of the dependencies are guaranteed to have been built. You can work around this by changing rules such as this:
foo: bar
genfoo < $(shell cat bar)
to this:
foo: bar
genfoo < `cat bar`
makepp_percent_subdirs=1By 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 set the variable makepp_percent_subdirs=1
on the command line or near the beginning of a makefile.
-m optionBy 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
(see the makepp_signatures manpage for details). 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.
--traditional-recursion optionRecursive invocations of make are often considered to be an unsafe practice
(see Better system for hierarchical builds in the makepp manpage for details), 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.
In order to be able to use repositories for variant builds, and to help make recursive invocations of make safer, 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.)
You may not invoke several makefiles from the same directory, e.g., the following will not work:
target: dependencies
$(MAKE) -f other_makefile targets
However, this will work:
target: dependencies
cd subdir && $(MAKE) -f other_makefile targets
Changes in environment variables are not passed to the recursive make process; the environment of the parent is used instead.
The 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:
Recursive makes do not execute in parallel, even if the parent does.
Recursive make processes do not know anything about repositories.
Each recursive make process produces its own log file, in the directory it is invoked in, instead of producing one log file for the entire build.
Even with the --traditional-recursive-make option, the environment
variables MAKEOVERRIDES and MFLAGS not set up, and are ignored, so
makefiles that depend on those will not work.
makepp_simple_concatenation variableRc-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/dir
if 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 setting the
makepp_simple_concatenation variable. Note, however, that even with
makepp_simple_concatenation, 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 set
makepp_simple_concatenation and also set T using the technique involving
a dummy variable such as null, as shown above.
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:
Makepp's -m option has to do with signature method selection, whereas GNU
make ignores -m.
Makepp's -q option suppresses makepp's chatty informational messages, which
is different from -q in GNU make.
Makepp's -R option actually does something completely different.
The --stop option stops (puts to sleep) makepp after learning all the
rules, so you can continue editing.
This happens automatically.
Some of these can be easily supported if anyone cares.
Though I have not seen this used, GNU make allows the following:
colon = :
a$(colon) b
echo $^
Makepp expands $(colon) too late for this to work. However it offers the
alternative $[colon] syntax, which can do much more than GNU make, because
it is expanded very early.