makepp [ -e ] [ -C dir ] [ -f makefile] [ -F makefile_or_dir ]
[ -j n] [ -k ] [ -m method ] [ --norc-substitution ]
[ --noremake-makefiles ] [ --nowarn ] [ --percent-subdirs ]
[ -q ] [ -R dir] [ --traditional-recursive-make ]
[ -v ] [ --version ]
Makepp is a build program like make that supports all the features of GNU make, but has a number of additional features to make writing makefiles much easier and to make builds much safer.
Makepp runs with any version of perl since 5.003_03. I have seen it occasionlly trip a nasty bug in perl 5.6.0 on linux which causes makepp to spit out all kinds of strange error messages, so I don't recommend running with perl 5.6.0; however, this is apparently rare so if you have 5.6.0 you might well be ok.
The following manual pages contain further information on how to use makepp:
makepp_command Command line syntax
makepp_tutorial How to write a makefile. This is mostly
intended for someone with little or no
experience using any implementation of make.
makepp_cookbook Quick answers to "How do I ...?" or
"What's the best way to ...?"
makepp_build_algorithm How makepp's build algorithm differs in
fundamental ways from traditional make
makepp_builtin For very simple programs, you may not
need a makefile at all! These are the
builtin rules that makepp knows about.
makepp_rules Specifying rules to build files
makepp_variables Using variables to simplify rules
makepp_functions Functions for text manipulation
makepp_statements Additional directives to control makepp
makepp_scanning How makepp scans for dependencies like include
files
makepp_signatures How makepp decides when to rebuild files
makepp_repositories Repositories are a technique that simplifies
both variant builds and keeping a central
set of sources
makepp_extending How you can add functions to makepp by writing
your own perl code.
makepp_incompatibilities What works differently between GNU make
and makepp.
makepp_release_notes What changed with each release.
-MM -MG option.) Makepp has a flexible system for doing this which is
based on scanning the build command; you can adapt it for other languages or
build commands by writing a perl subroutine.
Makepp loads all the makefiles in at once, so it has no problem dealing with situations where a file in one makefile depends on a file produced by a different makefile. Makepp cd's automatically to the directory containing the makefile before executing a command from a makefile, so each makefile may be written independently without knowledge of the top-level build directory.
Makepp also can figure out where all the makefiles for the entire project are without being told, if each makefile is in the same directory as the files it is supposed to produce. This can also simplify makefiles a great deal.
For more details on building with multiple directories, see makepp_cookbook/Tips for multiple directories.
CXX = g++
CXXFLAGS = -g
%.o : %.c
$(CXX) $(CXXFLAGS) -c $(input) -o $(output)
my_program: *.o
$(CXX) $(inputs) -o $(output)
and this will work even if none of the .o files have been built yet.
To illustrate why this is important, consider the following structure definition:
class ABC {
int x;
#ifndef SPECIAL_OPTION
int y;
#endif
int z;
};
Now suppose you decide to turn on the SPECIAL_OPTION option by adding
-DSPECIAL_OPTION to the command line. A recompilation of everything
is needed, but a traditional unix make will not detect this, and will
only recompile source files which have actually changed. As a result,
some of your modules will be compiled with -DSPECIAL_OPTION, and others
won't. After a very frustrating debugging session, you will discover
that all that needs to be done is to rebuild everything. Then you will
curse make and hopefully switch to an improved implementation of it,
like makepp. At least, that's what I did.
As another example, suppose that you are working on a project which is
pretty well debugged, so it's usually compiled with -O2. Now you run
into a bug which you need to look at in the debugger. Code compiled
with optimization is difficult to examine in the debugger, so you want
to recompile your code so that you can look at it. If your makefile is
set up to store the compiler options in the usual variables, you can
just do this:
makepp CFLAGS=-g CXXFLAGS=-g
and makepp will know that the command line has changed for all the modules. Then when you've found your bug, just type
makepp
and it will be recompiled with optimization. You don't need to type
make clean when you change build options.
Some makefiles (e.g., those for the linux kernel) go to incredible lengths to force recompilation when the compile command changes. With makepp, it's taken care of automatically--you don't have to do anything.
This is particularly useful if you have include files that are generated by files that change, and yet the generated include files themselves seldom change. Suppose you have a complicated yacc grammar in your program, with a build rule like this:
y.tab.c y.tab.h:
yacc -d parser.y
Ordinarily, every time you make even a tiny change to parser.y, every
file that depends on y.tab.h must be rebuilt since the file time of
y.tab.h has changed. However, most changes to parser.y won't
actually change the contents of y.tab.h (except possibly a comment),
so all that recompilation is unnecessary.
% makepp CFLAGS=-O2 # Compile everything.
# oops, bug discovered here
makepp CFLAGS=-g # Recompiles everything again.
gdb my_program
# ... find the bug
makepp CFLAGS=-O2 # Recompiles everything a third time.
With makepp, you can simply cd to an empty directory, and specify your original directory as a repository. This will create new object files in the empty directory, while leaving your old object files intact. Now you can find the bug in the directory compiled with debug, fix it in your original sources, and then go back to your original directory. Now only the few files that you changed actually need to be recompiled.
The entire procedure would look like this:
% makepp CFLAGS=-O2 # Compile everything.
# oops, bug discovered here
% mkdir debugging
% cd debugging
% makepp -R .. CFLAGS=-g # Compile with debugging enabled, but
# put objects in debugging subdir.
% gdb my_program
# ... find the bug
% cd .. # Back to original directory.
% makepp CFLAGS=-O2 # Recompiles only those files
# that you changed.
This can be a tremendous savings in time if there are many modules.
.o files
xx.h, and there is a file called xx.o
that makepp knows how to make, then makepp adds xx.o to the link
command line. I don't use non-shared libraries now in many places where
I used to, because makepp can automatically pick out the modules I need.
foo, ./foo, ../src/foo,
/auto_mnt/somedisk/bob/src/foo, and /users/bob/src/foo.
You can also simply write perl code in your makefile. Make variables are actually simply stored as perl variables, so you can manipulate them with the full power of the entire perl language.
.makepp_log that contains a
description of every file that it tried to build, what rule was used to
build it, what it depended on, and (if the file was rebuilt) which
dependency was different. This can be extremely useful for debugging a
makefile--if you're wondering why makepp decided to rebuild a file, or
why it didn't, you can just look in the log file where it explains the
decisions.
$@, $^, and $<. See makepp_variables for
details.