Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??

OK so you have learnt a bit of perl and have a great idea for a module. Here is how you go about making a distribution fit to go on CPAN. For background see Simple Module Tutorial and A Guide to Installing Modules Simon Cozens has a good overview of the process at perlnewmod. This tutorial is more hands on nitty gritty.

So you're all fired up to make your new widget module. Before you start it may be worthwhile to have a look at what already exists. You have many options open to you:

It should be pretty simple to see if it has already been done. If it has you can reinvent the wheel, modify the existing codebase, or add functionality to the existing modules. Alright your mind is made up, so let's get stuck into it.

Building a single module distribution Foo::Bar

Generally speaking you will be writting a module that fits below one of the base CPAN descriptions so lets presume you want to make a distro called Foo::Bar Typically you will start like this:

$ h2xs -AX Foo::Bar

h2xs should be available if you have perl on *nix or Win32. This will write module stubs for you automatically. You will get the following dir/files written into your current directory:

Foo/Bar/Makefile.PL Foo/Bar/Bar.pm Foo/Bar/Changes Foo/Bar/test.pl Foo/Bar/MANIFEST Foo/Bar/README

h2xs even writes you the stubs of your code which you can then just edit (a lot!). Once you have your basic structure you should then rename the Bar directory Foo-Bar-0.01 if you want to follow the accepted norms.

$ mv Bar Foo-Bar-0.01

By default the syntax in this tute is for *nix. On Win32 you will need to read and use \ instead of /. The Win32 equivalent of mv is rn or rename. If you are unfamiliar with shell commands see Behind the GUI lives the Shell for a just the facts overview.

Note that you just throw away the Foo dir :-) To avoid generating the extra directory you just h2xs -AX Bar but you will have to edit your Makefile.PL After this command it will have:

'NAME' => 'Bar' # but you need 'NAME' => 'Foo::Bar' # so fix it!

You should now have a proto-distro that looks like this:

Foo-Bar-0.01/Bar.pm Foo-Bar-0.01/Makefile.PL Foo-Bar-0.01/MANIFEST Foo-Bar-0.01/Changes Foo-Bar-0.01/test.pl Foo-Bar-0.01/README

Building a multi-module distribution

If you want to build a distribution that contains two modules like:

Foo::Bar # will install in Foo/Bar.pm Foo::Bar::Baz # will install in Foo/Bar/Baz.pm

Then all you need is this structure (which you can't instantly get from h2xs):

Foo-Bar-0.01/Bar.pm Foo-Bar-0.01/Makefile.PL Foo-Bar-0.01/MANIFEST Foo-Bar-0.01/Changes Foo-Bar-0.01/test.pl Foo-Bar-0.01/README Foo-Bar-0.01/Bar/Baz.pm # in Bar.pm package Foo::Bar; # in Baz.pm package Foo::Bar::Baz; # in Makefile.PL WriteMakefile( 'NAME' => 'Foo::Bar',

So as you can see all you need to do is make a Bar/ directory in your root dir and place Baz.pm in this. If you want h2xs to write the Baz.pm stub.....don't bother! Simply do this:

$ cd Foo-Bar-0.01 $ mkdir Bar $ cp Bar.pm ./Bar/Baz.pm $ cd Bar $ perl -pi.bak -e 's/Foo::Bar/Foo::Bar::Baz/g' Baz.pm $ rm Baz.pm.bak

As you can see all we have done is make a new directory called Bar/ then copy Bar.pm into it renaming it on the fly to Baz.pm. We then use perl to do a quick inplace edit of the package name and voila. Of course you could use an editor but you do know perl right? On Win32 use mkdir and copy and del You also need to use " instead of ' for command line perl under Win32 which is a right royal pain as you have to \ your " if you want them in the script.

ExtUtils::ModuleMaker or Module::Starter can replace h2xs

These modules can replace the use of h2xs for pure perl modules and do a lot of the 'hard' work for you. See a review of ExtUtils::ModuleMaker by simonflk for details and a rather nifty script. Module::Starter installs a script that you use like:
module-starter --module=Foo::Bar,Foo::Bat \ --author="Andy Lester" --email=andy@petdance.com

See its docs for more details.

Tests

OK so you have written your modules. What about some unit tests. Tests are great because every time you modify you module you may break something ;-) If you write some good tests for the API then all you have to do after each edit is run the tests - if you have not broken anything all should be well. If you have broken something you can fix it before you embarass yourself publicly!. I find Test is quite adequate. If you want you can bundle a copy of Test::More or even Test::Lincoln::Stein in your distro to avoid this problem. Asking permission for Test::More would be politic. See the CGI distribution to see Lincoln Stein roll his own test suite and include it. If you want complex tests you can still have them just using Test (which is part of the standard distro so you don't have to bundle it):

use Test; BEGIN { plan tests => 42 } use Widget; ok(1) # module loaded OK my $w = new Widget; $reply = $w->method; @reply = $w->method; ok( $reply ); ok( @reply ); ok( $reply =~ m/something/ ); ok( $reply eq 'some string' ); ok( scalar @reply == 42 ); ok( join '', @reply eq 'some list of stuff' );

You have two choices with tests. You can have all the tests in one file called test.pl in the root dir of your package (the h2xs default) or you can place test in the t/ dir. These test need to be called *.t for example you might have:

Foo-Bar-0.01/t/some_test.t Foo-Bar-0.01/t/test_this.t Foo-Bar-0.01/t/test_that.t

You can make this structure from the standard h2xs output like this:

$ cd Foo-Bar-0.01 $ md t $ cp test.pl ./t/some_test.t $ cp test.pl ./t/other_test.t $ rm test.pl

On Win32 you use del instead of rm.

Packaging your Masterpiece

You will need a tar(1) prgram and gzip(1). You should have them on *nix. On Win32 the CYGWIN distribution effectively gives you a UNIX console window (like the MSDOS console windows) with all the standard unix tools like tar and gzip. You package your distro like this:

$ tar -czf Foo-Bar-0.01.tar.gz Foo-Bar-0.01 # using CYGWIN you need to do it in two steps as the tar -z # option (which uses the tar gzip) produces broken distros # at least with my version of CYGWIN $ tar -cf Foo-Bar-0.01.tar Foo-Bar-0.01 $ gzip Foo-Bar-0.01.tar

You can also make clean make distcheck make manifest and make dist to achieve a similar result. See ExtUtils::MakeMaker Distribution Support for more details. I have problems with these under Win32 and nmake Anyway you are now the proud owner of Foo-Bar-0.01.tar.gz Test that all is ok like this:

$ tar -xzvf Foo-Bar-0.01.tar.gz $ cd Foo-Bar-0.01 $ perl Makefile.PL $ make $ make test $ make install

When you call make test (or nmake on Win32) make looks for any tests to run. Both test.pl and all the t/*.t tests will run. Generally you have one or the other. Test::Harness is called by make to run all the t/*.t tests.

make_manifest.pl

You will find that when you are playing with your distro you will repeat a number of steps over and over. I have a little custom script called make_manifest.pl which does a whole lot of things like:

  • clean out blib/ and all the other Makefile and make crap
  • remove any temp files like .bak files (or any other extensions like .pbp ~ etc)
  • cleans Win32 line endings to *nix standard (otherwise you will have install nightmares)
  • writes HTML files into html/ for all the pod (with CSS support) using Pod::HTML
  • writes a current MANIFEST
You can get a copy of the script from the CGI::Simple distro (it expects to be in the misc/ dir which is where you will find it. Don't forget the CSS if you use this script.

Win32

I do most of my work on Win32 (some on Redhat and FreeBSD). You will need tar and gzip from somewhere to make your distributions. As noted the CYGWIN distribution effectively gives you a UNIX console window (like the MSDOS console windows) with all the standard unix tools like tar and gzip.

Windows line endings and perl distributions are a bad combination. You will need to ensure that all the files in your distro have regular \n line endings not \r\n. I use my make_manifest.pl script to do this but you could write a little File::Find script to process your dirs.

nmake() can be replaced by Make.pm which is a pure perl version of make(). I have not used this personally. You can install it ppm install make and RTFM if you want.

Notes

Finally there are a few practical points.

  • If no one knows how to use it no one will. If there are no docs then I will have to RTFS to work out how to use it. Most people probably won't bother
  • Don't contaminate your user's namspace by Exporting ANYTHING by default (without good reason). Let them ask for the functions they want. Better still go OO.
  • Do write some decent tests
  • Do use some sort of CVS system to keep track of your distro as it develops. You may end up with Foo::Bar packages everywhere and have trouble finding the latest one. Worse you may patch old versions, etc, etc. Just zipping the distro up periodically with the date in the name can be invaluable ie Foo-Bar-0.01-01012002.tar.gz
  • use Carp; see Carp for why and use the carp() and croak() methods instead of warn() and die() which will put these messages in the perspective of the caller rather than the module.
  • use strict; and test with warnings use warnings; # 5.6 and up or $^W = 1. Don't leave $^W = 1 in you distro (your users may not appreciate your module telling them how bad their code is via its activation of gloabal warnings)
  • Remember to update $VERSION
  • Do write some pod. When you write the module Even you may forget how the API works given a little time

Please sir, can I have some more

Sure Oliver, here you go:

Good luck, enjoy and share.

Thanks to Juerd for correcting a Win32 error s/md/mkdir/g and noting my CYGWIN tar -czf workaround. Added make dist thanks to jmcnamara. Added note on research at start thanks to ybiC Added perlnewmod thanks to simonflk (I had forgotten what it was called). R&D links from perlnewmod in true web style :-)


In reply to How to make a CPAN Module Distribution by tachyon

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 lurking in the Monastery: (10)
    As of 2014-10-01 08:52 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      How do you remember the number of days in each month?











      Results (391 votes), past polls