First, module dependencies are declared using a package, not a distribution. If your application uses LWP::UserAgent, you have to declare:
requires 'LWP::UserAgent' => '5.20'; # Known minimum version of the module
instead of "libwww-perl" "5.20"
.
This is useful since when upstream author decides to strip the distribution into sub distributions, downstream module maintainers don't have to change anything.
Retrieving a distribution from a package to distribution is done by parsing 02packages.details.txt
which is distributed under modules/
directory of each CPAN mirror. The format of the module is:
LWP::UserAgent 5.20 G/GA/GAAS/libwww-perl-5.20.tar.gz
where 5.20 is a version number and it could be undef if there's no version specified.
Each CPAN mirror only has an index of the latest package and versions, which could cause issues when you want to retrieve 5.00 of a specific module (package) instead of the latest. Current solutions to this problem are BackPAN::Index and web services like http://beta.metacpan.org/.
Makefile.PL and Build.PL have a "configure", "build", "test" and "install" protocol.
> perl Makefile.PL
> make
> make test
> make install
> perl Build.PL
> perl Build
> perl Build test
> perl Build install
In the "configuration" phase, build tools like ExtUtils::MakeMaker or Module::Build looks for the pre-requisites specified in the perl's @INC path, and emits the specified modules into a file. Traditionally the scanned results are saved into Makefile
in case of EUMM and _build/prereqs
in case of Module::Build. Recently these tools have been improved to save this information into a file called MYMETA.yml and MYMETA.json, so installers can run the configure script and then parse MYMETA.* files to extract this information.
The problem with this "run & see" approach, however, is that where to look if a dependency is satisfied is controlled by the build tools, not installers. For example, if you want to build a self-contained bundle of your dependencies and install them into a local library path, you want to exclude the site_perl
library path of your perl because these modules won't probably be available on other machines.
It is technically possible (see what cpanminus -L option does) but it is really hard to stop Makefile.PL and Build.PL from loading extra library path when scanning modules.
Note that, accidentally being able to load some missing dependency as satisfied should be normally considered fine. For example, if your Makefile.PL has:
requires 'Test::TCP';
and if Test::TCP is installed into site_perl when executing Makefile.PL, that requirement is still dumped into MYMETA files, so the installer can use the information anyway. However, if your Makefile.PL
has a smart depedency detection and does something like:
if (eval { require Test::More 0.90; 1 }) {
# good, we have Test::More 0.9, now load more Test tools!
requires 'Test::TCP', 0.20;
requires 'Test::SharedFork', 0.99;
}
then whether the eval
block succeeds or not depends on the @INC
setup when Makefile.PL or Build.PL is executed.
CPAN Meta Spec has a boolean flag called dynamic_config
which is optional in 1.x and required in 2.0, and in 1.0 it is assumed to be 1
if missing, which indicates whether the configuration requires a dynamic introspection like above.
If the dynamic_config
is set to 0, it means the configuration is static, so the requires
section in the META.yml can be trusted. Installers might still have to run "configure", "build", "test" and "install" to run tests and let build tools to determine which files to install, but this is a relief for installers to figure out whether deps are complete or not.
Most authors do not care about this field and default output of META.yml wouldn't contain this field (which means dynamic_config
is true), but authoring tools like Dist::Zilla allows setting this field properly, assuming the dependencies are specified statically.
We explained that the dependencies are declared based on package names and versions, and CPAN installers will resolve them into a distribution.
There's one last mysterious "name" in a distribution, which is a 'NAME' of the main module and parameters passed to MakeMaker and Module::Build. For example, NAME of the Template-Toolkit-2.22 distribution is Template and the NAME of libwww-perl-6.0.tar.gz is LWP.
This name is used for .packlist location and perllocal.pod (see below) but there's no way to automatically retrieve the field. For most of the distributions, the NAME of the module is the same as the distribution name (except s/::/-/g
), but that can't be assumed always true. So currently cpanm has to use a regular expression to extract it from Makefile
's parameter list or evaluate the _build/build_params
file.
The "Name" field of these modules are used when to determine save .packlist
files in. .packlist
files contain all the file paths installed by the distribution. It is useful to get which files to remove upon uninstalling a distribution.
ExtUtils::MakeMaker currently merges the existing file paths with newly installed file paths, even when the installation prefix is different. For example, if you have Try::Tiny module in your site_perl, and then install the module again into a local library path like /home/miyagawa/perl5/lib/perl5
, the contents of Try/Tiny/.packlist
would be:
/usr/local/lib/perl5/site_perl/5.12.3/Try/Tiny.pm
/home/miyagawa/perl5/lib/perl5/Try/Tiny.pm
This merging behavior is there to keep track of old files stripped from the distribution when to update modules, and prevent these files from lingering around upon installation, but this behavior requires (un)installers to filter out the site_perl paths, upon uninstallation against the local library paths.
Module::Build, on the other hand, doesn't implement this merging behavior.
perllocal.pod is a POD file auto-generated by MakeMaker, and it keeps track of all the module names (explained above) and file paths. Module::Build doesn't support appending information into this file.