The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.
=head1 NAME

makepp -- Compatible but improved replacement for make

=for vc $Id: makepp.pod,v 1.38 2012/05/15 21:26:30 pfeiffer Exp $

=head1 SYNOPSIS

B<makepp> S<[ -e ]> S<[ -C I<dir> ]> S<[ -f I<makefile>]> S<[ -F I<makefile_or_dir> ]>
    S<[ -j I<n>]> S<[ -k ]> S<[ -m I<method> ]> S<[ --noremake-makefiles ]>
    S<[ --nowarn ]> S<[ -q ]> S<[ -R I<dir>]> S<[ --traditional-recursive-make ]>
    S<[ -v ]> S<[ --version ]> S<[ I<VAR=value> ... ]> S<[ I<target> ... ]>

B<mpp> [-options] S<[ I<VAR=value> ... ]> S<[ I<target> ... ]>

=head1 DESCRIPTION

Makepp, a build program which has a number of features that allow for reliable
builds and simpler build files, is a drop-in replacement for GNU make. It
supports L<almost all|makepp_incompatibilities> of the syntax that GNU make
supports, and can be used with makefiles produced by utilities such as
automake. It is called makepp (or make++) because it was designed with special
support for C++, which has since been extended to other languages like Swig or
embedded SQL. Also its relationship to make is analogous to C++'s relationship
to C: it is almost 100% backward compatible but adds a number of new features
and much better ways to write makefiles.

Makepp passes an extensive test-suite, and is used in several big projects.
If you have any issues with the latest CVS version, holler, and we'll try to
fix it quickly.  Makepp runs with any version of Perl since 5.8.

The following manual pages contain further information on how to use
makepp:

=over 4

=item L<Tutorial|makepp_tutorial>

How to write a makefile.  This is mostly intended for someone with little or
no experience using any implementation of make.

=item L<Compilation Tutorial|makepp_tutorial_compilation>

What the Unix compilation commands do.

=item L<Release Notes|makepp_release_notes>

What changed with each release.

=item L<Incompatibilities|makepp_incompatibilities>

What works differently between GNU make and makepp.

=item L<Speedup|makepp_speedup>

Various tips for making makepp go much faster.

=item L<Perl Performance|perl_performance>

Various tips for making Perl (within your makefiles and elsewhere) go faster.

=back

=for html <hr/>

=over

=item L<Cookbook|makepp_cookbook>

Quick answers to "How do I ...?" or "What's the best way to ...?"

=item L<FAQ|makepp_faq>

Quick answers to questions people have stumbled upon.

=back

=for html <hr/>

=over

=item L<Build Algorithm|makepp_build_algorithm>

How makepp's build algorithm differs in fundamental ways from traditional make.

=item L<Build Cache|makepp_build_cache>

A build cache is a directory that stores the results of prior builds in
case they are needed again in the same directory, or in a separate build
in a different directory.

=item L<Build Check Methods|makepp_build_check>

How makepp decides when to build.

=item L<Builtin Commands|makepp_builtins>

Powerful, efficient commands available everwhere makepp 2.0 or newer is.

=item L<Builtin Rules|makepp_builtin>

For very simple programs, you may not need a makefile at all!  These are the
builtin rules that makepp knows about.

=item L<Compatibility|makepp_compatibility>

Where and and with what version of Perl makepp works.

=item L<Extending|makepp_extending>

How you can add functions to makepp by writing your own Perl code.

=item L<Functions|makepp_functions>

Functions for text manipulation and various other purposes.

=item L<Repositories|makepp_repositories>

Repositories are a technique that simplifies both variant builds and keeping a
central set of sources.

=item L<Rules|makepp_rules>

Specifying rules to build files.

=item L<Sandboxes|makepp_sandboxes>

Using sandboxes to partition the build.

=item L<Scanning|makepp_scanning>

How makepp scans for dependencies like include files.

=item L<Signatures|makepp_signatures>

How makepp decides when files have changed.

=item L<Statements|makepp_statements>

Additional directives to control makepp.

=item L<Variables|makepp_variables>

Using variables to simplify rules.

=back

=for html <hr/>

=over

=item L<makepp, mpp|makepp_command>

Command line syntax of the main utility.

=item L<makeppclean, mppc|makeppclean>

An efficient stand-alone cleanup script to remove files generated by makepp.

=item L<makeppgraph, mppg|makeppgraph>

A stand-alone utility to graphically analyze dependencies and the reasons for a rebuild.

=item L<makeppinfo, mppi|makeppinfo>

A stand-alone utility to readably dump the build info makepp remembers about each file.

=item L<makepplog, mppl|makepplog>

A stand-alone utility to analyze dependencies and the reasons for a rebuild.

=item L<makeppreplay, mppr|makeppreplay>

A stand-alone utility to repeat things makepp has done, but much faster.

=back

=for html <hr/>

=over

=item L<Index|makepp_index>

All keywords, functions and operators in makepp.

=back


=head2 Features

=over 4

=item Automatic scanning for include files

Makepp scans automatically for include files.  This obviates the need for
tools like makedepend.  Makepp's scanner works even if the included files
don't exist yet but have to be built.  (This is true no matter where on the
include path they come from, unlike programs that depend on gcc's
S<C<-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.

=item Better system for hierarchical builds

Makepp has a better system for handling builds involving multiple
directories and multiple makefiles.  The traditional technique is to
have make invoke itself recursively in each directory.  Depending on how
complicated the interdependencies are, several recursive passes are
sometimes needed.  This makes the makefiles very complicated if they
guarantee a correct build.  The real problem is that unless dependencies
are trivial (e.g., just one library file), it is almost impossible to
express accurately dependencies of targets in one makefile in terms of
targets from the other makefile.  Unix make isn't smart enough to
realize that a target in one makefile depends on a file that is a target
in a lower-level makefile; it can't take build commands from the
lower-level makefile while it is trying to build the target in the
upper-level makefile.  So the usual solution is to build everything that
can be built with the lower-level makefiles, hoping that that's adequate
to build everything that's needed for the upper-level makefile.

Makepp loads all the needed makefiles in at once, so it has no problem dealing
with situations where a file from 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.  But
if access to the root of your build tree is important (e.g. because that's
where your include directory resides), you can name the makefile in that
directory specially.  Then makepp gives you the path to that directory in a
variable.

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
L<makepp_cookbook/Tips for multiple directories>.

=item Reliable wildcards

Makefiles can use wildcards reliably, because wild cards match either files
that exist, I<or> files that do not yet exist but makepp knows how to build.
So even for a program with dozens of modules, your entire makefile could
simply read something like this:

    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 C<.o> files have been built yet.

=item Reliable builds: remembers build command

Makepp keeps track of the build commands, so that if compilation options
change, files are automatically rebuilt.  This is important to guarantee
correct builds.  (This idea was taken from Bob Sidebothem's "cons" utility,
which was described in the Perl Journal in 1998 and is available from CPAN.)

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 C<SPECIAL_OPTION> option by adding
C<-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 C<-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
C<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.

=item Reliable builds: exact matching of signature

By default, makepp doesn't merely ensure that all targets are newer than
all dependencies; if you replace a dependency with an older file, makepp
knows that it has to rebuild the target, simply because the input file
has changed.  This is another important feature to guarantee correct
builds which was taken from the "cons" utility.

=item Smart signature calculations

Some modifications to source files do not actually require a rebuild.
For example, if you just change a comment line, or if you reindent some
code, there is no particular reason to force a compilation.  For C/C++
compilation, makepp determines whether a file needs recompilation by
computing a cryptographic checksum of the file's contents, ignoring
comments and whitespace, instead of looking at the file time.

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: parser.y
    	yacc -d parser.y

Ordinarily, every time you make even a tiny change to C<parser.y>, every
file that depends on C<y.tab.h> must be rebuilt since the file time of
C<y.tab.h> has changed.  However, most changes to C<parser.y> won't
actually change the contents of C<y.tab.h> (except possibly a comment),
so all that recompilation is unnecessary.

=item Repositories

Makepp can automatically incorporate files from a different directory
tree (the "repository") into the current build tree as needed.  (This
idea was also taken from the "cons" program.)  This has several
interesting uses:

=over 4

=item Variant builds

Suppose you have been compiling your program with optimization on and
debugging off.  Now a bug crops up and you have to recompile everything
with debugging enabled.  Once you find the bug, however, you're going to
turn debugging off and optimization back on, and with most make programs
you would have to recompile all the sources again, even the ones that
did not change.  The procedure would look like this:

    % 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.

=item Development team with common sources

Suppose you have a team of developers working on a standard set of
sources.  Each developer is making independent changes, but doesn't need
to have a copy of the whole source tree.  Using makepp's repositories,
you can have each developer have copies only of the files he has
changed.  Makepp will automatically and temporarily create symbolic
links for the other files that have not been changed to the
corresponding files in the repository.  It can even do this for object
files which exist in the repository and do not need to be recompiled in
the developer's individual directory.

=item Guarantee correct rules

If your rules do somthing which you didn't tell makepp about, the repository
mechanism will not know to fetch those things.  So something that builds
normally but fails from a repository tells you to fix your rules.

=back

=item Automatic inference of needed C<.o> files

Makepp can often infer exactly which objects are actually necessary
without being explicitly told.  If you use this feature, then if one of
your source file includes C<xx.h>, and there is a file called C<xx.o>
that makepp knows how to make, then makepp adds C<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.

=item Correct handling of aliases for directories

Makepp won't be confused by soft links to a directory or by different
relative filenames that refer to the same file.  All directory paths to
a file are recognized, including F<foo>, F<./foo>, F<../src/foo>,
F</auto_mnt/somedisk/bob/src/foo>, and F</users/bob/src/foo>.

=item Filenames with special characters

Makepp can support filenames with colons or spaces or other special
characters that cause trouble for the traditional make.  Just surround
the filename with quotes.  (See L<makepp_rules/Special characters> for
details.)

=item Extensible textual substutition functions

Makepp can use arbitrary Perl subroutines for textual substitution in
the makefile.  If you know Perl, you are not constrained at all by the
set of makepp's builtin textual manipulation functions.

You can also simply write Perl code in your makefile.  You can manipulate Make
variables with the full power of the entire Perl language.  See
L<makepp_variables> for details.

=item Logging of build decisions

By default, makepp makes a log-file viewable with L<makepplog, mppl|makepplog>
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) why.
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.

=item Improved support for parallel builds

Makepp supports parallel compilations, but (unlike other make
implementations) it won't mix output from separate processes which are
running simultaneously.

=item Synonyms for cryptic variables

Makepp supports easier-to-remember synonyms for the cryptic make
variables C<$@>, C<$^>, and C<$E<lt>>.  See L<makepp_variables> for
details.

=back