Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Comment on

( #3333=superdoc: 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

In reply to RFC: Some Reflections on Becoming a New CPAN Author by oko1

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others chilling in the Monastery: (18)
    As of 2014-07-30 16:37 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      My favorite superfluous repetitious redundant duplicative phrase is:









      Results (236 votes), past polls