Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
laziness, impatience, and hubris
 
PerlMonks  

RFC: Some Reflections on Becoming a New CPAN Author

by oko1 (Deacon)
on Jan 08, 2011 at 01:24 UTC ( #881186=perlmeditation: print w/ replies, xml ) Need Help??

(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.

# Typical invocation: create a pure Perl module (no C code) called # 'Amazing::Perl::Extension", omit AutoLoader cd ~/development h2xs -XA Amazing::Perl::Extension # You can even declare it as backward-compatible - e.g., w/Perl 5.7.1 h2xs -XA -b 5.7.1 Amazing::Perl::Extension

The above will create a directory called 'Amazing-Perl-Extension' with the following content:

lib/Amazing/Perl/Extension.pm # This is the boilerplate for your mod +ule t/Amazing-Perl-Extension.t # The Test::More-based test for loadin +g it Changes # History/listing of per-version chang +es Makefile.PL # ExtUtils::MakeMaker-based makefile m +aker MANIFEST # Listing of all of the above README # Intro/installation instructions

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:

tar cvzf Amazing-Perl-Extension-0.01.tgz Amazing-Perl-Extension

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":

The value in $VERSION must be quoted:
$VERSION = '0.20';

Ditto the module versions in Makefile.PL:
PREREQ_PM => { Term::ReadKey => '2.30' } # Otherwise, testing scripts will interpret the above as '2.3'
Perl version comparisons must not be quoted, despite the "bareword" appearance - since "$^V" (e.g., v5.10.1) is actually returned as "v" . chr(5) . chr(10) . chr(1). This used to be documented in "perldoc perlvar"... In fact, you must not quote $^V itself, either. The whole thing is pretty non-obvious.
ok($^V ge v5.7.1);
A "legal" way of failing out on unsupported OSes (that specific error string notifies the test script that it's a "valid" failure):
# This is in a separate file in t/*.t - e.g., 't/OS_test.t' use Test::More tests => 1; ok($^O !~ /^(?:MSWin|VMS|dos|MacOS|os2|epoc|cygwin)/i) or BAIL_OUT("OS + unsupported");
Conversely, if you only want to assert the OS on which your extension does work:
use Test::More tests => 1; ok($^O eq 'linux');
The conversion from the POD in your module to the HTML that's displayed on CPAN is only remotely related to the output from 'pod2html'; thus, I can't advise anything besides uploading your best effort, cursing the result, and trying to tweak your POD to produce something different. This might take you a few versions. Or you could just keep the POD ridiculously simple. I'm somewhat anally-retentive (I even spell "anally-retentive" with a hyphen, did you notice?), so I went the former route. Took about half a dozen tries. Arrrgh... sometimes, life's just not worth living. One thing that helps: '=begin text/=end text' are not shown in HTML docs, while '=begin html/=end html' are (while being elided in text).
=head1 ABSTRACT To generate a menu series that looks like this: =begin html <pre> .--------------------------------------------. | 1) Breakfast | 2) Dinner | 3) Lunch | '--------------------------------------------' Item number (1-3, 0 to restart, 'q' to quit)? 2 </pre> =end html =begin text .--------------------------------------------. | 1) Breakfast | 2) Dinner | 3) Lunch | '--------------------------------------------' Item number (1-3, 0 to restart, 'q' to quit)? 2 +++++++++++[New page]++++++++++++++++++++++++++++++ =end text
-- 
Education is not the filling of a pail, but the lighting of a fire.
 -- W. B. Yeats

Comment on RFC: Some Reflections on Becoming a New CPAN Author
Select or Download Code
Re: RFC: Some Reflections on Becoming a New CPAN Author
by Anonymous Monk on Jan 08, 2011 at 03:31 UTC
    (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.)

    Once again in English :)

      Heh. Well, Caveat Lector is Latin for "Let the reader beware", and "Hannibal" is a reference to a freaky cultural icon. The rest is just me still recovering from a rough day of boat maintenance; a mental discipline such as programming makes for a great shift away from mostly mindless physical tasks... but it can take a while to wind down.

      -- 
      Education is not the filling of a pail, but the lighting of a fire.
       -- W. B. Yeats
Re: RFC: Some Reflections on Becoming a New CPAN Author
by Sherm (Sexton) on Jan 08, 2011 at 23:55 UTC
    No need to worry about the version # in the tarball name - "make dist" will make an appropriately-named tarball for you.

      Yeah - I realized that I'd left that out and tried to add it with an update. Twice. It didn't work. Hopefully, this reply will get posted, though. :)

      Just in case, it does, here's what I was trying to add/substitute:

      # The right way to build a package; this will automatically add a vers +ion number # by reading $VERSION inside your .pm file as well as create a META.ym +l index perl Makefile.PL; make test; make dist # The fallback method, just in case; no META.yml, and you'll have to a +ppend the version tar cvzf Amazing-Perl-Extension-0.01.tgz Amazing-Perl-Extension
      -- 
      Education is not the filling of a pail, but the lighting of a fire.
       -- W. B. Yeats
Re: RFC: Some Reflections on Becoming a New CPAN Author
by Anonymous Monk on May 22, 2011 at 17:21 UTC

    Having recently joined the ranks of CPAN authors, I have lived through a very similar process. I would only add that since all of the authors on CPAN have gone through this process, some have made tools which make much of it simpler.

    There are several modules which make managing building and releasing your distribution easier. I have switched to Dist::Zilla for this purpose. You can look at my blog entry on switching and my full distribution on GitHub.

    Also you can preview your POD on CPAN at http://search.cpan.org/pod2html.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://881186]
Approved by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (6)
As of 2014-04-19 02:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (475 votes), past polls