NAME
cpanfile-faq - cpanfile FAQ
QUESTIONS
Does cpanfile replace Makefile.PL or Build.PL?
No, it doesn't. cpanfile
is a simpler way to declare CPAN dependencies, mainly to your application rather than CPAN distributions.
In fact, most CPAN distributions do not need to switch to cpanfile
unless they absolutely want to take advantage of some of the features (see below). This is considered a new extension for applications and installers.
Why do we need yet another format?
Here are some of the reasons that motivates the new cpanfile format.
- Not everything is a CPAN distribution
-
First of all, it is annoying to write Makefile.PL when what you develop is not a CPAN distirbution.
It gets more painful when you develop a web application that you want to deploy on a different environment using version control system (such as cloud infrastructure), because it requires you to often commit the META file or
inc/
directory (or even worse, botu) to a repository when your build script uses non-core modules such as Module::Install or File::Copy::Recursive.Many web application frameworks generate a boiler-plate
Makefile.PL
for dependency declaration and to let you install dependencies withcpanm --installdeps .
, but that doesn't always mean they are meant to be installed. Things can be often much simpler if you run the application from the checkout directory.With cpanfile, dependencies can be installed either globally or locally using supported tools such as cpanm or carton. Because
cpanfile
lists all the dependencies of your entire application and will be updated over time, it makes perfect sense to commit the file to a version control system, and push the file for a deployment. - More control for the dependencies analysis
-
One of the limitation when I tried to implement a self-contained local::lib library path feature for cpanminus was that the configuration phase runs the build file as a separate perl process, i.e.
perl Makefile.PL
.This makes it so hard for the script to not accidentally load any modules installed in the local
site_perl
directory when determining the dynamic dependencies.For example, JSON module has the following code (simplified):
if (!eval { require JSON::XS } && has_cc()) { $args{PREREQ_PM}{'JSON::XS'} = 2; }
Similary, Any::Moose has:
if (!eval { require Moose }) { $args{PREREQ_PM}{Mouse} = '0.40'; }
Because it uses
eval require
and the build script runs as a separate perl process, whether you have the modules in question in yoursite_perl
directory affects the dependencies configuration, and the installer (cpanm) has no control over it.This eventually results in a library path that is not self-contained and gives runtime errors because of missing dependencies.
With
cpanfile
format, dynamic dependencies based on the list of the modules can be declared like:# FIXME unless (has 'Moose') { requires 'Mouse', '0.40'; }
and installers can decide whether the module in question is installed in the target library path.
- Familiar DSL syntax
-
This is a new file type, but the format and syntax isn't entirely new. The metadata it can declare is exactly a subset of "Prereqs" in CPAN Meta Spec, with some conditionals such as
platform
andperl
.The syntax borrows a lot from Module::Install. Module::Install is a great way to easily declare module metadata such as name, author and dependencies. cpanfile format is simply to extract the dependencies into a separate file, which means most of the developers are familiar with the syntax.
- Complete CPAN Meta Spec v2 support
-
cpanfile
basically allows you to declare CPAN::Meta::Spec prerequisite specification using an easy Perl DSL syntax. This makes it easy to declare per-phase dependencies and newer version 2 features such as conflicts and version ranges.
How can I start using cpanfile
?
First of all, most distributions on CPAN are not required to update to this format.
If your application currently uses Makefile.PL
etc. for dependency declaration because of the current toolchain implementation (e.g. cpanm --installdeps .
), you can upgrade to cpanfile
while keeping the build file based installation working for the backward compatibility.
- Module::Install
-
Use Module::Install::Cpanfile and replace
requires
,test_requires
etc. withcpanfile
. - ExtUtils::MakeMaker
-
XXX
- Module::Build
-
XXX Module::Build::Cpanfile?
- Module::Build::Tiny
-
XXX
- Dist::Zilla