The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=head1 NAME

makepp_faq -- Frequently asked questions about makepp

=for vc $Id: makepp_faq.pod,v 1.18 2015/07/13 20:54:05 pfeiffer Exp $

=head1 DESCRIPTION

Here you may find installation instructions and some points which are not
obvious from the rest of the documentation.  This shows stumbling blocks,
whereas howto type questions will be found in the L<cookbook|makepp_cookbook>.


=head2 Getting Started

=for comment This chapter through pod2text provides the file INSTALL

=head3 Where to download?

Makepp is hosted on SourceForge and can be downloaded as a source code tarball
or as installation package for Debian F<.deb> based Linuxes or F<.rpm> based
Linuxes from http://sourceforge.net/projects/makepp/files/

Like tons of Perl software, makepp can also be downloaded from CPAN by
clicking the Download link on http://search.cpan.org/dist/makepp/

Makepp is part of Debian GNU/Linux unstable and testing.  This means you can
install it directly via C<apt-get install makepp> or by choosing it from your
preferred package tool like synaptic.

Makepp is part of archlinux and of Gentoo Linux.  Note that distro-specific
suffixes like 2.0-1 or 2.0-r1 is not the release candidate 1, but the final
released version 2.0.

=head3 Can I try it without installing?

Yes, if you want to try makepp on your own makefiles, either put the directory
where you unpacked it into your path, or else run it explicitly like this, with an
absolute or relative path to makepp:

    perl /where/you/unpacked/it/makepp

=head3 How to choose perl version?

You must have Perl 5.8 or newer somewhere on your system.  By default all
uninstalled scripts will use the C<perl> in your path.  But you can run them
with an explicit instance of perl.  The test runner and installation will run
everything with this same instance.

    /path/to/perl /where/you/unpacked/it/makepp

In case some script doesn't properly recognize which C<perl> it is being run
with, you can help it by telling it the path to the same instance of perl via
the C<PERL> variable:

    PERL=/path/to/perl /path/to/perl /where/you/unpacked/it/makepp

This can also be an instance to be searched in your path, if it doesn't
contain a directory separator:

    PERL=perl5.16.2 perl5.16.2 /where/you/unpacked/it/makepp

=head3 How to install?

There are two ways to install, which lead to the same result:

=over

=item configure (alias config.pl)

This allows for traditional style installation:

    ./configure && make test && make install

The only difference between these two is that C<configure> is not a Perl
script, so you can't say C<perl configure>, whereas you can use all the above
variants like C<perl config.pl>.  Valid options are:

=over

=item -b, --bindir=F</path/to/installation/bin>

Where the binaries go (default: I<prefix>/bin).  Makepp's binaries are just
Perl scripts so they are architecture independent.  If you give this option,
but no C<--prefix>, it will strip F</bin> to deduce a I<prefix> for the other
default values.

=item -d, --datadir=F</path/to/installation/share/makepp>

Where to install makepp's library files (default: I<prefix>/share/makepp).

=item -f, --findbin=F<relative/path/to/datadir/from/bindir>

Where to find libraries relative to executables, or 'none' (the default) to
find them in I<datadir>.

=item -h, --htmldir=F</path/to/installation/share/html>

Where the HTML documentation goes (default: I<prefix>/doc/makepp if
I<prefix>/doc exists, else I<datadir>/html), or 'none' if you do not want it
installed.

=item -m, --mandir=/F<path/to/man>

Where the manual pages should reside (default: I<prefix>/share/man if it
exists, else I<prefix>/man), or 'none' if you do not want them installed.

=item --makefile=F</path/to/Makefile>

Specify location where you can write the Makefile (default: .).  Unlike the
other options, which are remembered for the following install step, this file
is created immediately.

=item -p, --prefix=F</path/to/installation>

Specify location where you want to install everything (default: /usr/local).
All other paths are by default relative to this one.

=item -V

=item --version

Print out the version number.

=back

If you want to do a mockup installation to some destdir for packaging your own
distribution, you can give an extra parameter to the last command:

    make DESTDIR=/temporary/destdir install

=item install.pl

This is the backend that performs the actual installation.  You can call it
directly:

    ./install.pl bindir datadir mandir htmldir findbin destdir

The parameters are optional and correspond to the options from the previous
section.  You are prompted for those you don't supply, except for the last
one, which is not normally needed.

=item I<Makefile.PL>

The customary file F<Makefile.PL> is currently only present for technical
reasons.  It will B<not> help you to install.  Therefore, alas, you can't use
tools like C<cpanm> to install in one go.

=back

On some systems whichever C<perl> you end up calling may be a symbolic link to
some precise version C<perl5.m.n>.  In this case perl sees only that one, and
will thus use it to install against.  If you don't want that, use the C<PERL>
variable as described above.  If you install with the second variant, i.e. just
the name of the executable without slashes, the installed scripts will always
search for that one via C</usr/bin/env>.  This makes them a tiny bit slower to
start, for a greater flexibility.

=head3 Why does installation say permission denied?

If you want to install to a system directory like F</usr>, F</usr/local> or
F</opt>, you can only do that if you run the installation as user root.  On
many Unices you can run a command as root, by prepending C<sudo> to it, and
depending on the system entering the either the root password, or yours, as
prompted for.

This is not necessary for the preparatory C<configure> or C<config.pl> step
which only writes a F<Makefile> in the current directory.


=head2 Build Questions

=head3 What are unimportant targets?

Makepp remembers the dependencies of every file.  If any of them need to be
rebuilt, that will be done before rescanning.  But if the build failed, yet
the scan succeeds, because the file isn't even needed anymore, then at the end
the failure will be reported as unimportant.  (The build should not be
attempted, instead letting the rescan do those builds it finds to be
necessary, but that happens in a different place, so this would be difficult.)

=head3 Why does it run this rule 3 times?

GNU make has no makepp style multi target rules.  Instead it interprets this
as a shortcut for three separate rules:

    a b c:
 	echo $@
 	touch a b c

However, it doesn't check why a file is there.  If a file exists (and is newer
than any dependencies) it is happy.  Whichever of the three files gets built
first, provides the other two, so this behaves somewhat like a multitarget
rule -- but can cause race conditions in parallel builds.

A similar rule might have been:

    a b c:
 	touch $@

Gmake indeed runs this one once per required file.  Without knowing what the
command does (it might be a script which internally creates some files), the
two cases can't easily be told apart by makepp.

So as a special compatibility fallback, if a multi target rule action mentions
only old style C<$@> and neither new style C<$(output)> nor C<$(target)> nor their
plural forms, it is treated as separate rules.  This however means running it
repeatedly, as makepp ignores randomly appearing files for which it has no
metadata.

=head3 Why does it complain that a created file is phony?

If you have a command that continues working asynchronously, after it came
back with a success return code, makepp will notice the promised file as
missing and complain.  This can also typically happen on some network file
systems, which may physically write only several seconds later.

If you cannot evite such an unsatisfactory situation, you can ask makepp to be
sloppy about this check with the C<--gullible> option.  But then the next
command which depends on the produced file might still fail.

=head3 Why does it recreate files unnecessarily?

I have observed this on NFS, where due to file attribute caching the timestamp
of the produced file was not yet the one the it finally had.  On the next run
makepp noticed the difference and considered the file unduly modified.  This
got resolved with a mount option of C<acregmin=0>, making attributes visible
immediately.

This can also happen with repositories, e.g. if someone else has built in the
repository with C<umask 066> or using a compiler that bars others from reading
the produced file.  This will also happen if either the repository or your
build tree shares a common path prefix with some dependencies
(e.g. F</opt/repository> and F</opt/sometool>, in which case makepp will
remember the path once as relative, and once as absolute, looking like changed
dependencies.

=head3 Does the C source file or the object file depend on headers?

It depends on your viewpoint.  If a prototype in a header changes, the
programmer may have to adapt the source code.  So from that viewpoint there is
a dependency.

But for the build this is completely irrelevant.  Here the outputs depend on
the inputs.  If a header file changes this may affect the object file
(e.g. addition of parameters with default values, which the programmer may
ignore, but not the compiler).  So from makepp's viewpoint only the produced
object file depends on the headers, i.e. must be rebuilt when these change.


=head2 Miscellaneous

=head3 Why does makepp selectively detect dependencies?

In this rule why does makepp make F<output> depend on F<input1>, but not on
F<input2>?

    output:
 	zcat <input1 >output
 	zcat input2 >>output

There are three levels to scanning.  The first is the lexer, which tries to
understand the Shell part of the execution.  I.e. which commands get called
and what I/O redirections take place.  This notices F<input1> and F<output>
(even if it had not been declared a target of this rule).

The next step are the command parsers.  Makepp has a few for typical
compilation commands.  These check the command line options to understand what
the command will do.  In the process they pick up dependencies like libraries
(C<cc -llib>), include paths (C<cc -Idir>) and input files.  The task of a
C<zcat> parser would be to know that C<-S> takes an argument, but all other
non option words are filenames (optionally suffixed by F<.gz>), and that C<-->
ends options.  Alas there is no such parser, no more than for hundreds of
other commands.

The third step for some languages is the scanning of input files, to detect
includes as further dependencies.  This does not apply to this example.

=head3 How can I debug makepp?

You can put C<$(print )> around a suspicious expression.  This returns the
unchanged expression, while printing it as a side effect.

You can dump the current directory's (multiply after C<-C> if you want)
makefile with the C<--dump-makefile=file> option, to see how makepp sees it.

Makepp writes a log of everything it does and why.  You can look at that with
L<makepplog, mppl|makepplog> or L<makeppgraph, mppg|makeppgraph>.  You can
make it more verbose by setting the environment variable C<MAKEPP_DEBUG>.

Makepp records all it knows about a file, for reuse on the next run.  Though
it takes some understanding of makepp's internals, dumping it with
L<makeppinfo, mppi|makeppinfo> for one or more files, usually gives a clue
what is wrong.  C<MAKEPP_DEBUG> additionally provides the C<RULE_SOURCE>.

If you are feeling adventurous, use makepp from cvs.  This includes extra
modules that hook into C<perl -d> to better display makepp's internals.

=head3 Is it safe to use?

B<Yes>, it will do exactly what your makefiles say (which many programmers
find hard to understand, since rule based inference is very different from
most programming paradigms).

B<And no>, if you don't trust the makefiles you got, definitely not!  A
makefile is a funny kind of script, the purpose of which is to run commands
that are expected to modify your file system.  Makepp has no means of checking
what harm they will do.

Worse, there are execute always syntaxes, which are performed even with
C<--dry-run> (which does not run the rules, but evaluates everything else).
That might be something like this:

    bad_boy := $(shell rm *)

=head3 Is there a web front-end?

No.  But as for all command line tools, you could access it via
https://code.google.com/p/shellinabox/

You might even set up a little Shell wrapper to allow only calling makepp:

    while read 'args?makepp '; do
 	makepp $args
    done


=head2 External tools

=head3 Can I use cc -M or gcc -MM?

The short answer is yes.  The long answer is that they have the advantage of
knowing the effect of even the last weird compiler option, and sub-includes
hidden in some compiler internal directory, where makepp only comes pretty
close.  The disadvantage is that they have no idea of the build rules, so they
can not reliably depend on yet to-be-built files, which includes files to be
fetched from a L<repository|makepp_repositories>.  And they are not extensible
to other languages, as makepp's L<scanner|makepp_scanning> is.  Usually you
are at least as well off, not resorting to these tools.

Nonetheless, some compilers can produce this as a by-product.  If you'd rather
use this see L<:include|makepp_rules/include_file_or_pattern>.

=head3 Can I use CCache, Compilercache or cachecc1?

The short answer is yes.  The long answer is that these programs need to
repeat the work makepp does, to get a reliable fingerprint of files.  With
traditional makes this even comes too late, because those miss many situations
calling for a recompilation.  With makepp it is just easier to use the built
in L<build cache|makepp_build_cache>, which has the added advantage that it
can handle all kinds of files.

Note that ccache direct mode has a bug
https://bugzilla.samba.org/show_bug.cgi?id=8728 that will ignore change in
include pathes.  This makes F<t/makeppreplay.test> fail with "wrong file:
out".  Export C<CCACHE_NODIRECT=1> to avoid that.

=head1 AUTHOR

Daniel Pfeiffer (occitan@esperanto.org)