Module::Build
by Dave Rolsky
|
Pages: 1, 2, 3
Consider what happens if we know that we need some piece of
functionality first present in DBD::mysql 2.1013. But perhaps a
release after this, 2.1014, introduced a new bug that breaks our
application. If this bug is fixed in version 2.1015, we could
simply require version 2.1015, but this is not ideal. There's no
reason to force someone who already has 2.1013 to upgrade because of a
bug in a version they don't have.
Fortunately, Module::Build provides a more flexible version
specification option that handles exactly this situation, so we can
write:
Module::Build->new
( module_name => 'My::Module',
license => 'perl',
requires => { 'CGI' => 0,
'DBD::mysql' => '>= 2.1013, != 2.1014',
},
)->create_build_script;
This says that we need a version greater than 2.1013 that is not version 2.1014. Users who have version 2.1013 or version 2.1015 or greater are not forced to upgrade, but anyone with 2.1014 will be.
If we knew that version 3.0 didn't work with your module, we could change our specification:
Module::Build->new
( module_name => 'My::Module',
license => 'perl',
requires => { 'CGI' => 0,
'DBD::mysql' => '>= 2.1013, != 2.1014, < 3.0',
},
)->create_build_script;
If the user does have version 3.0 or greater installed, it will at
least let them know that it won't work with our module.
Unfortunately, the only possible way to use our module at this point
is for the end user to manually downgrade their installation of
DBD::mysql, since Perl does not allow multiple versions of a module
to co-exist peacefully. Still, this is better than letting the module
be installed, only to fail at runtime when it tries to use an outdated
API for DBD::mysql.
There are also other options related to prerequisites, such as "recommends" and "build_requires", which can be helpful for prerequisites that are required to build the module but don't need to be present after installation. There is also a "conflicts" option which can be used to warn a user about potential conflicts between the module they are installing and one they already have.
Action!
As of release 1.15, Module::Build implements the following actions,
most of which are based on existing ExtUtils::MakeMaker
functionality:
- build
This is the default action, and is what happens if you run ./Build without any additional arguments. It is responsible for creating the blib/ directory and copying files into it, as well as compiling XS and C files. If you have any scripts like lib/My/Module.pm.PL, these are also run during this action.
- test, testdb
Runs the module's tests using the
Test::Harnessmodule. The "testdb" action can be used to run the tests under Perl's debugger. Equivalently, a "debugger" parameter can be passed to the "test" action to get the same effect. - clean, realclean
Both actions delete any files created by the "build" action. The "realclean" action also deletes the existing Build script.
- diff
This action is used to compare the files about to be installed with any corresponding files that already exist. This feature is unique to
Module::Build. - install
Installs the module files. As of version 0.15, this doesn't yet create or install any man pages.
- fakeinstall
Tells you what the "install" would do.
- dist
Creates a gzip'd tarball of your distribution.
- manifest
Creates a MANIFEST file for your distribution. - distcheck
Tells you what files are in the build directory but not in the MANIFEST file, and vice versa.
- skipcheck
Tells you what files will not be added to the MANIFEST by the "manifest" action, based on the contents of your MANIFEST.SKIP file.
- distclean
This is a shortcut for "realclean" followed by "distcheck".
- distdir
Creates a directory based on your distribution name and version, and then copies all the files listed in MANIFEST to that directory. This directory is what people will see when they download and unpack your distribution.
Module::Buildalso creates a file called META.yaml which contains meta-data about your distribution. In the future, it may be possible to use a command line tool (written in Perl, of course) to read this file and use its contents to install your distribution, without running the Build.PL script. It also makes the meta-data more readily available to tools like search.cpan.org or the CPAN shell. - disttest
This performs the "distdir" action, switches to the newly created directory, and then runs
perl Build.PL,./Build, and./Build test. This lets you make sure that your distribution is actually installable. - help
Tells you what actions are available. If additional actions are implemented in a distribution, then these are listed here.
Any of these options can be overridden through straightforward
subclassing, so our HTML::Mason example from earlier in this article
might be written something like this:
package MyFancyBuilder;
use base 'Module::Build';
sub ACTION_test {
my $self = shift;
# %MY::APACHE is set in makeconfig.pl.
$ENV{PORT} = $MY::APACHE{port} || 8228;
$ENV{APACHE_DIR} = $MY::APACHE{apache_dir} || ";
$ENV{MASON_VERBOSE} ||= $self->{properties}{verbose};
# _is_maintainer_mode would be another method of our subclass
$ENV{MASON_MAINTAINER} = $self->_is_maintainer_mode();
return $self->SUPER::ACTION_test(@_);
}
This version is actually readable, and is unlikely to break regardless
of changes in the Module::Build internals. This highlights just
how difficult it was to accomplish a simple task using
ExtUtils::MakeMaker, and how natural the pure-Perl solution can be.
The Larger Picture and Backwards Compatibility
One difficulty in getting Module::Build into widespread use is the
fact that support for ExtUtils::MakeMaker is so tightly integrated
into CPAN installers.
While the version of CPAN.pm which ships with 5.8 does not know how to deal with Build.PL, the latest versoin available from CPAN does. It will even install Module::Build for you. As of January 2008, CPANPLUS, another CPAN shell, understands Build.PL but will not install Module::Build for you, but this will be remedied in a future release.
However, old versions of CPAN.pm are still in extremely widespread use, and users won't
necessarily upgrade CPAN.pm before attempting to install a
distribution that relies on Module::Build.

