|Just another Perl shrine|
(Note: much of this is written after a day of hard physical labor - chipping and grinding rust, cutting metal, welding, etc. while listening to stuff like Eminem and Rihanna's "Love The Way You Lie" and Delbert McClinton's "Somebody to Love You" at skin-ripping volume all day long, so I may still be under the influence of testosterone and adrenaline; Caveat Lector. Even if your name isn't Hannibal.)
Having recently sunk my teeth into the 50-caliber projectile that is CPAN authorship, I have... um, new stuff to chew on. So, in the best tradition of the Monastery as well as the Open Source culture, I've decided to share the bits I've learned so far; in addition, I wanted to write it up before I forgot these recent growing pains. Hopefully, this will remove or prevent at least a few of the stumbling blocks for anyone who decides to follow the same path.
So, say you have a module - or even a script that you've decided can be modularized and that would benefit the Perl world at large. Great.
The first thing you'll need, as befits anyone who is about to take over the world, is to come up with a name for your magnificent edifice of Perlish brilliance - so head over to the PAUSE site and read "On The Naming of Modules" (reciting "The Naming of Cats is a difficult matter / It isn't just one of your holiday games..." is purely optional, no matter what the documentation says.) Once your head stops spinning from all the (necessarily) conflicting directions, and you've figured out the name for your module as well as the namespace in which it should live, progress to the next step. Just make sure you've picked one of those Sensible, Everyday Names.
(While you cogitate on the deep, dark, and complicated issue of naming, you should spawn off a child process (via Parallel::ForkManager, perhaps) which will open a PAUSE account for you. It might take a while for it to be approved, so it's a good idea to get that started early.)
Now that you've figured out the name and the namespace, you can start by building the layout that's necessary for CPAN packages. This is easy to do; you can use either the 'h2xs' script (comes with Perl) or the 'module-starter' script, which is a command-line interface to Module::Starter. I've found that I prefer 'h2xs' for a number of reasons, including the fact that it makes somewhat fewer assumptions and thus gives a slightly more "naked" skeleton structure. With 'module-starter', I end up having to delete a fair amount of stuff, both files and chunks of file content.
The above will create a directory called 'Amazing-Perl-Extension' with the following content:
You'll be working with all of these at some point, so get familiar with them. I'm not going to go into the details lest this turn into a book, but I'll mention bits of these later. Meanwhile, get out a large crowbar and a can of grease; you'll need to shoehorn your code into Extension.pm. What, you thought it was going to be easy? Ye've got to sweat to earn that shillin', me hearties! Good thing that most of the above are exceptionally well documented, right in the code or in the boilerplate that you'll need to replace/update with your own stuff. Yep, you've got lots of reading to do.
(Hint: think about generalizing your code as much as possible. Then, think about it some more. People are going to be using it on an amazing variety of Perl versions, OSes, and with a wide variety of toolsets - meaning that you can almost never rely on any external tools or output formats. Also, think about the Perl version and OS restrictions that you want to declare; some of the Perl features you're relying on may not have been around in earlier versions... versions that people are still using. Also, UTF-8 is your friend - as long as you do it right. ikegami has written quite a bit about it here in PM.)
Once you've agonized and tested and tested some more, you're satisfied that your feature set and OS/version restrictions define a reasonable chunk of the Perl world that your module will serve, and you've configured everything in the above list to your satisfaction, go ahead and make it into a package. This is easy:
0.01 is the default version number for your module, as initially created by either of the tools I've mentioned. You'll need to increment it for every subsequent upload (PAUSE will not accept a previously-uploaded version number.) There are four places where you'll want to update it: $VERSION in Extension.pm, the latest note in 'Changes', the end of the first line in the README, and in the above tarball name. Once done, head over to PAUSE (hopefully, your child process has terminated with a 'success' flag) and upload your work, either via the PAUSE Web interface or (my preferred method) Neil Bowers' cpan-upload script.
(Meanwhile, spawn off another child process and register your namespace at PAUSE. That might take a bit of time, too, but - heck, 'Parallel::ForkManager->new()' allows you to specify an arbitrary number of children, and 'wait_all_children' works fine - so why worry?)
Soooner or later after doing this, you're going to get an email from somebody called 'cpantesters', in which the subject may start with a threatening-looking 'FAIL'. Do not panic; this is not a blackmail note or an invitation to donate to a political cause. It's the hearty crew that makes CPAN work (and the blessings of all the $DEITIES upon their heads!) - the testers who constantly check the quality of the code uploaded to CPAN by running it on a variety of OSes and Perl versions. If your code does fail, it can be a little tricky figuring it out from the messages... well, this is why those emails have links to the full report inside them, and this is what you'll need to do in order to improve your module. In any case, you're off and running with the process. Just remember to always update your version numbers and put clear, explicit notes in the Changes file.
NOTE: failing is not necessarily bad; FAILing is. The distinction (it's one I'm making - this isn't some special CPAN jargon) is that correctly failing a test - e.g., gracefully exiting the installation procedure if, say, the Perl version is less than the one that you've required - is exactly the right thing to do, but omitting that test and having the module crash when the incorrect Perl version tries to load it is a bad thing, and will lead to you receiving FAIL reports from cpantesters. Just FYI, there are a lot of wrong ways to do these tests (I think I've tried all of those...), but there are only a few right ones. I've tried to list these little traps below.
And now, assuming that you've dragged yourself through all these steps, and that you're a contributing member of the Perl community - which module authors certainly are... THANKS! And good luck. I'll see you on the barricades. :)
Possible stumbling blocks, from my "Notes to self":
-- Education is not the filling of a pail, but the lighting of a fire. -- W. B. Yeats
In reply to RFC: Some Reflections on Becoming a New CPAN Author by oko1