summaryrefslogtreecommitdiffstats
path: root/upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:43:11 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 19:43:11 +0000
commitfc22b3d6507c6745911b9dfcc68f1e665ae13dbc (patch)
treece1e3bce06471410239a6f41282e328770aa404a /upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl
parentInitial commit. (diff)
downloadmanpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.tar.xz
manpages-l10n-fc22b3d6507c6745911b9dfcc68f1e665ae13dbc.zip
Adding upstream version 4.22.0.upstream/4.22.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl')
-rw-r--r--upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl714
1 files changed, 714 insertions, 0 deletions
diff --git a/upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl b/upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl
new file mode 100644
index 00000000..6ca38861
--- /dev/null
+++ b/upstream/archlinux/man3/ExtUtils::MakeMaker::FAQ.3perl
@@ -0,0 +1,714 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
+.ie n \{\
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+. if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{\
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\" ========================================================================
+.\"
+.IX Title "ExtUtils::MakeMaker::FAQ 3perl"
+.TH ExtUtils::MakeMaker::FAQ 3perl 2024-02-11 "perl v5.38.2" "Perl Programmers Reference Guide"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH NAME
+ExtUtils::MakeMaker::FAQ \- Frequently Asked Questions About MakeMaker
+.SH DESCRIPTION
+.IX Header "DESCRIPTION"
+FAQs, tricks and tips for ExtUtils::MakeMaker.
+.SS "Module Installation"
+.IX Subsection "Module Installation"
+.IP "How do I install a module into my home directory?" 4
+.IX Item "How do I install a module into my home directory?"
+If you're not the Perl administrator you probably don't have
+permission to install a module to its default location. Ways of handling
+this with a \fBlot\fR less manual effort on your part are perlbrew
+and local::lib.
+.Sp
+Otherwise, you can install it for your own use into your home directory
+like so:
+.Sp
+.Vb 2
+\& # Non\-unix folks, replace ~ with /path/to/your/home/dir
+\& perl Makefile.PL INSTALL_BASE=~
+.Ve
+.Sp
+This will put modules into \fI~/lib/perl5\fR, man pages into \fI~/man\fR and
+programs into \fI~/bin\fR.
+.Sp
+To ensure your Perl programs can see these newly installed modules,
+set your \f(CW\*(C`PERL5LIB\*(C'\fR environment variable to \fI~/lib/perl5\fR or tell
+each of your programs to look in that directory with the following:
+.Sp
+.Vb 1
+\& use lib "$ENV{HOME}/lib/perl5";
+.Ve
+.Sp
+or if \f(CW$ENV\fR{HOME} isn't set and you don't want to set it for some
+reason, do it the long way.
+.Sp
+.Vb 1
+\& use lib "/path/to/your/home/dir/lib/perl5";
+.Ve
+.IP "How do I get MakeMaker and Module::Build to install to the same place?" 4
+.IX Item "How do I get MakeMaker and Module::Build to install to the same place?"
+Module::Build, as of 0.28, supports two ways to install to the same
+location as MakeMaker.
+.Sp
+We highly recommend the install_base method, its the simplest and most
+closely approximates the expected behavior of an installation prefix.
+.Sp
+1) Use INSTALL_BASE / \f(CW\*(C`\-\-install_base\*(C'\fR
+.Sp
+MakeMaker (as of 6.31) and Module::Build (as of 0.28) both can install
+to the same locations using the "install_base" concept. See
+"INSTALL_BASE" in ExtUtils::MakeMaker for details. To get MM and MB to
+install to the same location simply set INSTALL_BASE in MM and
+\&\f(CW\*(C`\-\-install_base\*(C'\fR in MB to the same location.
+.Sp
+.Vb 2
+\& perl Makefile.PL INSTALL_BASE=/whatever
+\& perl Build.PL \-\-install_base /whatever
+.Ve
+.Sp
+This works most like other language's behavior when you specify a
+prefix. We recommend this method.
+.Sp
+2) Use PREFIX / \f(CW\*(C`\-\-prefix\*(C'\fR
+.Sp
+Module::Build 0.28 added support for \f(CW\*(C`\-\-prefix\*(C'\fR which works like
+MakeMaker's PREFIX.
+.Sp
+.Vb 2
+\& perl Makefile.PL PREFIX=/whatever
+\& perl Build.PL \-\-prefix /whatever
+.Ve
+.Sp
+We highly discourage this method. It should only be used if you know
+what you're doing and specifically need the PREFIX behavior. The
+PREFIX algorithm is complicated and focused on matching the system
+installation.
+.IP "How do I keep from installing man pages?" 4
+.IX Item "How do I keep from installing man pages?"
+Recent versions of MakeMaker will only install man pages on Unix-like
+operating systems by default. To generate manpages on non-Unix operating
+systems, make the "manifypods" target.
+.Sp
+For an individual module:
+.Sp
+.Vb 1
+\& perl Makefile.PL INSTALLMAN1DIR=none INSTALLMAN3DIR=none
+.Ve
+.Sp
+If you want to suppress man page installation for all modules you have
+to reconfigure Perl and tell it 'none' when it asks where to install
+man pages.
+.IP "How do I use a module without installing it?" 4
+.IX Item "How do I use a module without installing it?"
+Two ways. One is to build the module normally...
+.Sp
+.Vb 3
+\& perl Makefile.PL
+\& make
+\& make test
+.Ve
+.Sp
+\&...and then use blib to point Perl at the built but uninstalled module:
+.Sp
+.Vb 2
+\& perl \-Mblib script.pl
+\& perl \-Mblib \-e \*(Aq...\*(Aq
+.Ve
+.Sp
+The other is to install the module in a temporary location.
+.Sp
+.Vb 4
+\& perl Makefile.PL INSTALL_BASE=~/tmp
+\& make
+\& make test
+\& make install
+.Ve
+.Sp
+And then set PERL5LIB to \fI~/tmp/lib/perl5\fR. This works well when you
+have multiple modules to work with. It also ensures that the module
+goes through its full installation process which may modify it.
+Again, local::lib may assist you here.
+.IP "How can I organize tests into subdirectories and have them run?" 4
+.IX Item "How can I organize tests into subdirectories and have them run?"
+Let's take the following test directory structure:
+.Sp
+.Vb 3
+\& t/foo/sometest.t
+\& t/bar/othertest.t
+\& t/bar/baz/anothertest.t
+.Ve
+.Sp
+Now, inside of the \f(CWWriteMakefile()\fR function in your \fIMakefile.PL\fR, specify
+where your tests are located with the \f(CW\*(C`test\*(C'\fR directive:
+.Sp
+.Vb 1
+\& test => {TESTS => \*(Aqt/*.t t/*/*.t t/*/*/*.t\*(Aq}
+.Ve
+.Sp
+The first entry in the string will run all tests in the top-level \fIt/\fR
+directory. The second will run all test files located in any subdirectory under
+\&\fIt/\fR. The third, runs all test files within any subdirectory within any other
+subdirectory located under \fIt/\fR.
+.Sp
+Note that you do not have to use wildcards. You can specify explicitly which
+subdirectories to run tests in:
+.Sp
+.Vb 1
+\& test => {TESTS => \*(Aqt/*.t t/foo/*.t t/bar/baz/*.t\*(Aq}
+.Ve
+.IP "PREFIX vs INSTALL_BASE from Module::Build::Cookbook" 4
+.IX Item "PREFIX vs INSTALL_BASE from Module::Build::Cookbook"
+The behavior of PREFIX is complicated and depends closely on how your
+Perl is configured. The resulting installation locations will vary
+from machine to machine and even different installations of Perl on the
+same machine. Because of this, its difficult to document where prefix
+will place your modules.
+.Sp
+In contrast, INSTALL_BASE has predictable, easy to explain installation
+locations. Now that Module::Build and MakeMaker both have INSTALL_BASE
+there is little reason to use PREFIX other than to preserve your existing
+installation locations. If you are starting a fresh Perl installation we
+encourage you to use INSTALL_BASE. If you have an existing installation
+installed via PREFIX, consider moving it to an installation structure
+matching INSTALL_BASE and using that instead.
+.ie n .IP "Generating *.pm files with substitutions eg of $VERSION" 4
+.el .IP "Generating *.pm files with substitutions eg of \f(CW$VERSION\fR" 4
+.IX Item "Generating *.pm files with substitutions eg of $VERSION"
+If you want to configure your module files for local conditions, or to
+automatically insert a version number, you can use EUMM's \f(CW\*(C`PL_FILES\*(C'\fR
+capability, where it will automatically run each \fI*.PL\fR it finds to
+generate its basename. For instance:
+.Sp
+.Vb 10
+\& # Makefile.PL:
+\& require \*(Aqcommon.pl\*(Aq;
+\& my $version = get_version();
+\& my @pms = qw(Foo.pm);
+\& WriteMakefile(
+\& NAME => \*(AqFoo\*(Aq,
+\& VERSION => $version,
+\& PM => { map { ($_ => "\e$(INST_LIB)/$_") } @pms },
+\& clean => { FILES => join \*(Aq \*(Aq, @pms },
+\& );
+\&
+\& # common.pl:
+\& sub get_version { \*(Aq0.04\*(Aq }
+\& sub process { my $v = get_version(); s/_\|_VERSION_\|_/$v/g; }
+\& 1;
+\&
+\& # Foo.pm.PL:
+\& require \*(Aqcommon.pl\*(Aq;
+\& $_ = join \*(Aq\*(Aq, <DATA>;
+\& process();
+\& my $file = shift;
+\& open my $fh, \*(Aq>\*(Aq, $file or die "$file: $!";
+\& print $fh $_;
+\& _\|_DATA_\|_
+\& package Foo;
+\& our $VERSION = \*(Aq_\|_VERSION_\|_\*(Aq;
+\& 1;
+.Ve
+.Sp
+You may notice that \f(CW\*(C`PL_FILES\*(C'\fR is not specified above, since the default
+of mapping each .PL file to its basename works well.
+.Sp
+If the generated module were architecture-specific, you could replace
+\&\f(CW\*(C`$(INST_LIB)\*(C'\fR above with \f(CW\*(C`$(INST_ARCHLIB)\*(C'\fR, although if you locate
+modules under \fIlib\fR, that would involve ensuring any \f(CW\*(C`lib/\*(C'\fR in front
+of the module location were removed.
+.SS "Common errors and problems"
+.IX Subsection "Common errors and problems"
+.IP """No rule to make target `/usr/lib/perl5/CORE/config.h', needed by `Makefile'""" 4
+.IX Item """No rule to make target `/usr/lib/perl5/CORE/config.h', needed by `Makefile'"""
+Just what it says, you're missing that file. MakeMaker uses it to
+determine if perl has been rebuilt since the Makefile was made. It's
+a bit of a bug that it halts installation.
+.Sp
+Some operating systems don't ship the CORE directory with their base
+perl install. To solve the problem, you likely need to install a perl
+development package such as perl-devel (CentOS, Fedora and other
+Redhat systems) or perl (Ubuntu and other Debian systems).
+.SS "Philosophy and History"
+.IX Subsection "Philosophy and History"
+.IP "Why not just use <insert other build config tool here>?" 4
+.IX Item "Why not just use <insert other build config tool here>?"
+Why did MakeMaker reinvent the build configuration wheel? Why not
+just use autoconf or automake or ppm or Ant or ...
+.Sp
+There are many reasons, but the major one is cross-platform
+compatibility.
+.Sp
+Perl is one of the most ported pieces of software ever. It works on
+operating systems I've never even heard of (see perlport for details).
+It needs a build tool that can work on all those platforms and with
+any wacky C compilers and linkers they might have.
+.Sp
+No such build tool exists. Even make itself has wildly different
+dialects. So we have to build our own.
+.IP "What is Module::Build and how does it relate to MakeMaker?" 4
+.IX Item "What is Module::Build and how does it relate to MakeMaker?"
+Module::Build is a project by Ken Williams to supplant MakeMaker.
+Its primary advantages are:
+.RS 4
+.IP \(bu 8
+pure perl. no make, no shell commands
+.IP \(bu 8
+easier to customize
+.IP \(bu 8
+cleaner internals
+.IP \(bu 8
+less cruft
+.RE
+.RS 4
+.Sp
+Module::Build was long the official heir apparent to MakeMaker. The
+rate of both its development and adoption has slowed in recent years,
+though, and it is unclear what the future holds for it. That said,
+Module::Build set the stage for \fIsomething\fR to become the heir to
+MakeMaker. MakeMaker's maintainers have long said that it is a dead
+end and should be kept functioning, while being cautious about extending
+with new features.
+.RE
+.SS "Module Writing"
+.IX Subsection "Module Writing"
+.ie n .IP "How do I keep my $VERSION up to date without resetting it manually?" 4
+.el .IP "How do I keep my \f(CW$VERSION\fR up to date without resetting it manually?" 4
+.IX Item "How do I keep my $VERSION up to date without resetting it manually?"
+Often you want to manually set the \f(CW$VERSION\fR in the main module
+distribution because this is the version that everybody sees on CPAN
+and maybe you want to customize it a bit. But for all the other
+modules in your dist, \f(CW$VERSION\fR is really just bookkeeping and all that's
+important is it goes up every time the module is changed. Doing this
+by hand is a pain and you often forget.
+.Sp
+Probably the easiest way to do this is using \fIperl-reversion\fR in
+Perl::Version:
+.Sp
+.Vb 1
+\& perl\-reversion \-bump
+.Ve
+.Sp
+If your version control system supports revision numbers (git doesn't
+easily), the simplest way to do it automatically is to use its revision
+number (you are using version control, right?).
+.Sp
+In CVS, RCS and SVN you use \f(CW$Revision\fR$ (see the documentation of your
+version control system for details). Every time the file is checked
+in the \f(CW$Revision\fR$ will be updated, updating your \f(CW$VERSION\fR.
+.Sp
+SVN uses a simple integer for \f(CW$Revision\fR$ so you can adapt it for your
+\&\f(CW$VERSION\fR like so:
+.Sp
+.Vb 1
+\& ($VERSION) = q$Revision$ =~ /(\ed+)/;
+.Ve
+.Sp
+In CVS and RCS version 1.9 is followed by 1.10. Since CPAN compares
+version numbers numerically we use a \fBsprintf()\fR to convert 1.9 to 1.009
+and 1.10 to 1.010 which compare properly.
+.Sp
+.Vb 1
+\& $VERSION = sprintf "%d.%03d", q$Revision$ =~ /(\ed+)\e.(\ed+)/g;
+.Ve
+.Sp
+If branches are involved (ie. \f(CW$Revision:\fR 1.5.3.4$) it's a little more
+complicated.
+.Sp
+.Vb 2
+\& # must be all on one line or MakeMaker will get confused.
+\& $VERSION = do { my @r = (q$Revision$ =~ /\ed+/g); sprintf "%d."."%03d" x $#r, @r };
+.Ve
+.Sp
+In SVN, \f(CW$Revision\fR$ should be the same for every file in the project so
+they would all have the same \f(CW$VERSION\fR. CVS and RCS have a different
+\&\f(CW$Revision\fR$ per file so each file will have a different \f(CW$VERSION\fR.
+Distributed version control systems, such as SVK, may have a different
+\&\f(CW$Revision\fR$ based on who checks out the file, leading to a different \f(CW$VERSION\fR
+on each machine! Finally, some distributed version control systems, such
+as darcs, have no concept of revision number at all.
+.IP "What's this \fIMETA.yml\fR thing and how did it get in my \fIMANIFEST\fR?!" 4
+.IX Item "What's this META.yml thing and how did it get in my MANIFEST?!"
+\&\fIMETA.yml\fR is a module meta-data file pioneered by Module::Build and
+automatically generated as part of the 'distdir' target (and thus
+\&'dist'). See "Module Meta-Data" in ExtUtils::MakeMaker.
+.Sp
+To shut off its generation, pass the \f(CW\*(C`NO_META\*(C'\fR flag to \f(CWWriteMakefile()\fR.
+.IP "How do I delete everything not in my \fIMANIFEST\fR?" 4
+.IX Item "How do I delete everything not in my MANIFEST?"
+Some folks are surprised that \f(CW\*(C`make distclean\*(C'\fR does not delete
+everything not listed in their MANIFEST (thus making a clean
+distribution) but only tells them what they need to delete. This is
+done because it is considered too dangerous. While developing your
+module you might write a new file, not add it to the MANIFEST, then
+run a \f(CW\*(C`distclean\*(C'\fR and be sad because your new work was deleted.
+.Sp
+If you really want to do this, you can use
+\&\f(CWExtUtils::Manifest::manifind()\fR to read the MANIFEST and File::Find
+to delete the files. But you have to be careful. Here's a script to
+do that. Use at your own risk. Have fun blowing holes in your foot.
+.Sp
+.Vb 1
+\& #!/usr/bin/perl \-w
+\&
+\& use strict;
+\&
+\& use File::Spec;
+\& use File::Find;
+\& use ExtUtils::Manifest qw(maniread);
+\&
+\& my %manifest = map {( $_ => 1 )}
+\& grep { File::Spec\->canonpath($_) }
+\& keys %{ maniread() };
+\&
+\& if( !keys %manifest ) {
+\& print "No files found in MANIFEST. Stopping.\en";
+\& exit;
+\& }
+\&
+\& find({
+\& wanted => sub {
+\& my $path = File::Spec\->canonpath($_);
+\&
+\& return unless \-f $path;
+\& return if exists $manifest{ $path };
+\&
+\& print "unlink $path\en";
+\& unlink $path;
+\& },
+\& no_chdir => 1
+\& },
+\& "."
+\& );
+.Ve
+.IP "Which tar should I use on Windows?" 4
+.IX Item "Which tar should I use on Windows?"
+We recommend ptar from Archive::Tar not older than 1.66 with '\-C' option.
+.IP "Which zip should I use on Windows for '[ndg]make zipdist'?" 4
+.IX Item "Which zip should I use on Windows for '[ndg]make zipdist'?"
+We recommend InfoZIP: <http://www.info\-zip.org/Zip.html>
+.SS XS
+.IX Subsection "XS"
+.IP "How do I prevent ""object version X.XX does not match bootstrap parameter Y.YY"" errors?" 4
+.IX Item "How do I prevent ""object version X.XX does not match bootstrap parameter Y.YY"" errors?"
+XS code is very sensitive to the module version number and will
+complain if the version number in your Perl module doesn't match. If
+you change your module's version # without rerunning Makefile.PL the old
+version number will remain in the Makefile, causing the XS code to be built
+with the wrong number.
+.Sp
+To avoid this, you can force the Makefile to be rebuilt whenever you
+change the module containing the version number by adding this to your
+\&\fBWriteMakefile()\fR arguments.
+.Sp
+.Vb 1
+\& depend => { \*(Aq$(FIRST_MAKEFILE)\*(Aq => \*(Aq$(VERSION_FROM)\*(Aq }
+.Ve
+.IP "How do I make two or more XS files coexist in the same directory?" 4
+.IX Item "How do I make two or more XS files coexist in the same directory?"
+Sometimes you need to have two and more XS files in the same package.
+There are three ways: \f(CW\*(C`XSMULTI\*(C'\fR, separate directories, and bootstrapping
+one XS from another.
+.RS 4
+.IP XSMULTI 8
+.IX Item "XSMULTI"
+Structure your modules so they are all located under \fIlib\fR, such that
+\&\f(CW\*(C`Foo::Bar\*(C'\fR is in \fIlib/Foo/Bar.pm\fR and \fIlib/Foo/Bar.xs\fR, etc. Have your
+top-level \f(CW\*(C`WriteMakefile\*(C'\fR set the variable \f(CW\*(C`XSMULTI\*(C'\fR to a true value.
+.Sp
+Er, that's it.
+.IP "Separate directories" 8
+.IX Item "Separate directories"
+Put each XS files into separate directories, each with their own
+\&\fIMakefile.PL\fR. Make sure each of those \fIMakefile.PL\fRs has the correct
+\&\f(CW\*(C`CFLAGS\*(C'\fR, \f(CW\*(C`INC\*(C'\fR, \f(CW\*(C`LIBS\*(C'\fR etc. You will need to make sure the top-level
+\&\fIMakefile.PL\fR refers to each of these using \f(CW\*(C`DIR\*(C'\fR.
+.IP Bootstrapping 8
+.IX Item "Bootstrapping"
+Let's assume that we have a package \f(CW\*(C`Cool::Foo\*(C'\fR, which includes
+\&\f(CW\*(C`Cool::Foo\*(C'\fR and \f(CW\*(C`Cool::Bar\*(C'\fR modules each having a separate XS
+file. First we use the following \fIMakefile.PL\fR:
+.Sp
+.Vb 1
+\& use ExtUtils::MakeMaker;
+\&
+\& WriteMakefile(
+\& NAME => \*(AqCool::Foo\*(Aq,
+\& VERSION_FROM => \*(AqFoo.pm\*(Aq,
+\& OBJECT => q/$(O_FILES)/,
+\& # ... other attrs ...
+\& );
+.Ve
+.Sp
+Notice the \f(CW\*(C`OBJECT\*(C'\fR attribute. MakeMaker generates the following
+variables in \fIMakefile\fR:
+.Sp
+.Vb 7
+\& # Handy lists of source code files:
+\& XS_FILES= Bar.xs \e
+\& Foo.xs
+\& C_FILES = Bar.c \e
+\& Foo.c
+\& O_FILES = Bar.o \e
+\& Foo.o
+.Ve
+.Sp
+Therefore we can use the \f(CW\*(C`O_FILES\*(C'\fR variable to tell MakeMaker to use
+these objects into the shared library.
+.Sp
+That's pretty much it. Now write \fIFoo.pm\fR and \fIFoo.xs\fR, \fIBar.pm\fR
+and \fIBar.xs\fR, where \fIFoo.pm\fR bootstraps the shared library and
+\&\fIBar.pm\fR simply loading \fIFoo.pm\fR.
+.Sp
+The only issue left is to how to bootstrap \fIBar.xs\fR. This is done
+from \fIFoo.xs\fR:
+.Sp
+.Vb 1
+\& MODULE = Cool::Foo PACKAGE = Cool::Foo
+\&
+\& BOOT:
+\& # boot the second XS file
+\& boot_Cool_\|_Bar(aTHX_ cv);
+.Ve
+.Sp
+If you have more than two files, this is the place where you should
+boot extra XS files from.
+.Sp
+The following four files sum up all the details discussed so far.
+.Sp
+.Vb 3
+\& Foo.pm:
+\& \-\-\-\-\-\-\-
+\& package Cool::Foo;
+\&
+\& require DynaLoader;
+\&
+\& our @ISA = qw(DynaLoader);
+\& our $VERSION = \*(Aq0.01\*(Aq;
+\& bootstrap Cool::Foo $VERSION;
+\&
+\& 1;
+\&
+\& Bar.pm:
+\& \-\-\-\-\-\-\-
+\& package Cool::Bar;
+\&
+\& use Cool::Foo; # bootstraps Bar.xs
+\&
+\& 1;
+\&
+\& Foo.xs:
+\& \-\-\-\-\-\-\-
+\& #include "EXTERN.h"
+\& #include "perl.h"
+\& #include "XSUB.h"
+\&
+\& MODULE = Cool::Foo PACKAGE = Cool::Foo
+\&
+\& BOOT:
+\& # boot the second XS file
+\& boot_Cool_\|_Bar(aTHX_ cv);
+\&
+\& MODULE = Cool::Foo PACKAGE = Cool::Foo PREFIX = cool_foo_
+\&
+\& void
+\& cool_foo_perl_rules()
+\&
+\& CODE:
+\& fprintf(stderr, "Cool::Foo says: Perl Rules\en");
+\&
+\& Bar.xs:
+\& \-\-\-\-\-\-\-
+\& #include "EXTERN.h"
+\& #include "perl.h"
+\& #include "XSUB.h"
+\&
+\& MODULE = Cool::Bar PACKAGE = Cool::Bar PREFIX = cool_bar_
+\&
+\& void
+\& cool_bar_perl_rules()
+\&
+\& CODE:
+\& fprintf(stderr, "Cool::Bar says: Perl Rules\en");
+.Ve
+.Sp
+And of course a very basic test:
+.Sp
+.Vb 8
+\& t/cool.t:
+\& \-\-\-\-\-\-\-\-
+\& use Test::More tests => 1;
+\& use Cool::Foo;
+\& use Cool::Bar;
+\& Cool::Foo::perl_rules();
+\& Cool::Bar::perl_rules();
+\& ok 1;
+.Ve
+.Sp
+This tip has been brought to you by Nick Ing-Simmons and Stas Bekman.
+.Sp
+An alternative way to achieve this can be seen in Gtk2::CodeGen
+and Glib::CodeGen.
+.RE
+.RS 4
+.RE
+.SH DESIGN
+.IX Header "DESIGN"
+.SS "MakeMaker object hierarchy (simplified)"
+.IX Subsection "MakeMaker object hierarchy (simplified)"
+What most people need to know (superclasses on top.)
+.PP
+.Vb 9
+\& ExtUtils::MM_Any
+\& |
+\& ExtUtils::MM_Unix
+\& |
+\& ExtUtils::MM_{Current OS}
+\& |
+\& ExtUtils::MakeMaker
+\& |
+\& MY
+.Ve
+.PP
+The object actually used is of the class MY which allows you to
+override bits of MakeMaker inside your Makefile.PL by declaring
+\&\fBMY::foo()\fR methods.
+.SS "MakeMaker object hierarchy (real)"
+.IX Subsection "MakeMaker object hierarchy (real)"
+Here's how it really works:
+.PP
+.Vb 10
+\& ExtUtils::MM_Any
+\& |
+\& ExtUtils::MM_Unix
+\& |
+\& ExtUtils::Liblist::Kid ExtUtils::MM_{Current OS} (if necessary)
+\& | |
+\& ExtUtils::Liblist ExtUtils::MakeMaker |
+\& | | |
+\& | | |\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
+\& ExtUtils::MM
+\& | |
+\& ExtUtils::MY MM (created by ExtUtils::MM)
+\& | |
+\& MY (created by ExtUtils::MY) |
+\& . |
+\& (mixin) |
+\& . |
+\& PACK### (created each call to ExtUtils::MakeMaker\->new)
+.Ve
+.PP
+NOTE: Yes, this is a mess. See
+<http://archive.develooper.com/makemaker@perl.org/msg00134.html>
+for some history.
+.PP
+NOTE: When ExtUtils::MM is loaded it chooses a superclass for MM from
+amongst the ExtUtils::MM_* modules based on the current operating
+system.
+.PP
+NOTE: ExtUtils::MM_{Current OS} represents one of the ExtUtils::MM_*
+modules except ExtUtils::MM_Any chosen based on your operating system.
+.PP
+NOTE: The main object used by MakeMaker is a PACK### object, *not*
+ExtUtils::MakeMaker. It is, effectively, a subclass of MY,
+ExtUtils::MakeMaker, ExtUtils::Liblist and ExtUtils::MM_{Current OS}
+.PP
+NOTE: The methods in MY are simply copied into PACK### rather
+than MY being a superclass of PACK###. I don't remember the rationale.
+.PP
+NOTE: ExtUtils::Liblist should be removed from the inheritance hiearchy
+and simply be called as functions.
+.PP
+NOTE: Modules like File::Spec and Exporter have been omitted for clarity.
+.SS "The MM_* hierarchy"
+.IX Subsection "The MM_* hierarchy"
+.Vb 9
+\& MM_Win95 MM_NW5
+\& \e /
+\& MM_BeOS MM_Cygwin MM_OS2 MM_VMS MM_Win32 MM_DOS MM_UWIN
+\& \e | | | / / /
+\& \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-
+\& | |
+\& MM_Unix |
+\& | |
+\& MM_Any
+.Ve
+.PP
+NOTE: Each direct MM_Unix subclass is also an
+MM_Any subclass. This
+is a temporary hack because MM_Unix overrides some MM_Any methods with
+Unix specific code. It allows the non-Unix modules to see the
+original MM_Any implementations.
+.PP
+NOTE: Modules like File::Spec and Exporter have been omitted for clarity.
+.SH PATCHING
+.IX Header "PATCHING"
+If you have a question you'd like to see added to the FAQ (whether or
+not you have the answer) please either:
+.IP \(bu 2
+make a pull request on the MakeMaker github repository
+.IP \(bu 2
+raise a issue on the MakeMaker github repository
+.IP \(bu 2
+file an RT ticket
+.IP \(bu 2
+email makemaker@perl.org
+.SH AUTHOR
+.IX Header "AUTHOR"
+The denizens of makemaker@perl.org.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+ExtUtils::MakeMaker