Jul/095
Authoring a CPAN Module
I’ve been authoring CPAN distribution since early 2003 with my first module being Geo::Distance. Since then I’ve authored several other distributions and do my best to keep my RT bug list small and fix FAILs. This process of authoring and maintaining modules on CPAN is in my top-10 list of all-time most educational experiences of my career.
I strongly encourage anyone that wants to become a better developer to take on the task and create a useful distribution for CPAN and/or work on an existing distro. There are plenty of projects out there (such as Moose, DBIx::Class, and Catalyst, to name a few) that need help and can use all the hands that they can get.
Now, if you would instead like to create your own distribution on CPAN, go for it! Its really quite easy and fun. But, it is VERY important that you think long and hard about what you want to release on CPAN. It may seem that every possible task that someone might want to accomplish in Perl is already available on CPAN – this is false. I regularly find myself needing tools that aren’t yet on CPAN. Don’t just write something for the sake of getting something on CPAN – develop something that is useful, of high quality, has a decent suite of automated tests, and doesn’t duplicate a module that is already on CPAN.
Once you developed a module or two, and you are ready to get it out the door, you’ll want to do a couple things. First, create a directory to hold your distribution. Assuming your module is named Acme::Yesterday:
cd Acme-Yesterday
vi Makefile.PL
You’ll want to install Module::Install first, before you go any further as it provides a much easier to configure build/test/install process than the old-school ExtUtils::MakeMaker.
Now, your Makefile.PL will look something like this:
all_from lib/Acme/Yesterday.pm
requires DateTime
test_requires Test::More 0.42
(Notice the first line DOES have a semicolon at the end, while the rest do not)
Next, create a directory to put your module(s):
mkdir lib/Acme
vi lib/Acme/Yesterday.pm
Now, your module will need some minimum requirements such as declaring the version of the distribution, the license type, and a name. Also, most CPAN modules follow a common convention for documentation using POD. Here is the most minimal of a module:
use strict;
use warnings;
our $VERSION = 0.01;
=head1 NAME
Acme::Yesterday - Make time() return the same hour,
second, and even minute as exactly 24 hours ago!
=head1 SYNOPSIS
use Acme::Yesterday;
=head1 DESCRIPTION
I'm an interesting introduction to this module.
=cut
use DateTime;
=head1 METHODS
=head2 some_method
some_method();
Description of some_method().
=cut
sub some_method { ... }
1;
=head1 AUTHOR
Your Name <your@email>
=head1 COPYRIGHT
This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.
Alternatively you can use Module::Starter to create a shell of a module for you.
Now for automated tests. At a minimum you should write a test that verifies that your module can even be loaded. Here’s how to do that:
vi t/00_use.t
The content of 00_use.t should be something like:
use strict;
use warnings;
use Test::More tests => 1;
BEGIN{ use_ok('Acme::Yesterday'); }
You’ll need to make a couple more files:
echo '0.01 - First release.' > Changes
OK, now just sit back and let Module::Install do its work:
make dist
make disttest
Assuming your tests pass when you run `make disttest`, you’re set to put your module on CPAN. The above steps would have now created for you a Acme-Yesterday-0.01.tar.gz. This is the file that you need to upload to CPAN. In order to upload a distribution to CPAN you’ll need to get a pause account. Once your request has been approved you can login to pause, go to the upload page, and upload your tarball. Within an hour or two your new distribution will be availabe on CPAN.
Once you’ve done this you’ll want to clean up your distribution directory as running the various make steps leaves around some files you don’t need:
Good luck!
Leave a comment
No trackbacks yet.

2:39 am on July 16th, 2009
IMHO, using Module::Starter or similar module (not h2xs) is easier.
Also to create distribution, it is better and easier to do it with `make dist`. To do tests fo dist, you can use `make disttest` – it will create standalone directory and will not create new files in dist directory.
6:11 am on July 16th, 2009
This is a big help to newcomers. Now I have a link I can point people to when they ask e how to make a cpan module :)
Since the recommended development best practice is to code everything like a cpan module, even you inhouse work stuff, doing this correctly will really help projects get off to a good start.
A few extras:
– You can skip the manual effort of making the tarball. just after making the manifest you do:
make dist
and that creates the tarball for you.
Also, I usually do a ‘make veryclean’ afterwards to clear out all the temporary files and bits creating the dist usually leaves laying around.
Eventually when you are using a source control system, you will probably need a MANIFEST.SKIP file as well, so that you don’t end up putting your .svn directories into the dist (or .DS_Store files if you are on a Mac).
Another useful trick is to make sure you use the Makefile.PL to properly manage ALL your application dependencies. So each time you need a cpan module for your app, instead of firing up the cpan command shell, you add it in like:
requires ‘Moose’ => ‘0.85′;
and then you do:
Perl Makefile.PL
which will warn you if your dependencies are behind or need installing. Then you can do:
make installdeps
and it will go out to cpan and install everything for you. This is a great way to make sure all your developers stay in sync with dependencies, as well as eases deployment.
Coupled with using Local::Lib this makes managing your Perl development area nice and clean
6:40 am on July 16th, 2009
Hey guys – thanks for the great feedback and additions. I was not aware of `make dist` and `make disttest`, I’ve been doing it manually all these years… sigh. :) Anyways, that’s one of the reasons for posting something like this – to get valuable feedback from the community.
I’ve updated my original post to include the `make dist` and Module::Starter bits.
10:16 pm on July 16th, 2009
use inc::Module::Install::DSL 0.91;
all_from lib/Acme/Yesterday.pm
requires DateTime
test_requires Test::More 0.42
6:35 am on July 17th, 2009
Hey Adam – I updated your comment (removed the extra semicolon) and updated my post to reflect your changes. I didn’t realize there was a DSL module. Very nice.