Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

How to make a CPAN Module Distribution

by tachyon (Chancellor)
on Apr 14, 2002 at 20:24 UTC ( [id://158999]=perltutorial: 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 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 :-)

2019-07-28 Athanasius addressed problem of linkrot, as per Consideration by hippo. Links to Test::Lincoln::Stein and RTFM not found. “Behind the GUI lives the Shell” found in The WayBack Machine. Links to perldoc.com and to Perl documentation on PerlMonks converted to Perldoc or MetaCPAN links as appropriate.

Replies are listed 'Best First'.
Re: How to make a CPAN Module Distribution
by lachoy (Parson) on Apr 14, 2002 at 21:11 UTC

    Packaging note: a make tardist will bundle up all the files in MANIFEST to a tarball for you. It's more useful to me than the straight tar and gzip because I tend to have extra (non-distributable) stuff in my module working directory.

    Also, if you're going to use CVS tags to track VERSION numbers of all but your top-level module (recommended for sheer laziness and consistency), remember to do it in the beginning. If you decide to do it later you'll almost certainly wind up confusing CPAN because you get a sub-module with a lower VERSION than your previous distribution's version.

    Update: forgot one other useful thing: You can create a MANIFEST file in the current directory by running:

    $  perl -MExtUtils::Manifest -e 'ExtUtils::Manifest::mkmanifest()'

    Chris
    M-x auto-bs-mode

      I also recommend reading perlnewmod. It is also worth reading perlmod and perlmodlib for general information about writing modules, versions, the CPAN, etc

      Depending on your coding style, you may find ExtUtils::ModuleMaker useful.

      <sig>

      -- simonflk

      </sig>

      update: Sorry lachoy, I meant this as a reply to root doc. God, I haven't done that in a while!

      update 2: Just posted a review of ExtUtils::ModuleMaker with sample code. BTW, if you use Make.pm on Win32, it will do a make dist.

        Thanks for the link to Make.pm. Nice review too.

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: How to make a CPAN Module Distribution
by PodMaster (Abbot) on Jun 08, 2003 at 10:03 UTC
    If you're gonna be distributing your module on CPAN, you should be aware of the following CPAN FAQ item

    How do I report/fix a bug in a module/script?

    Use http://rt.cpan.org/ to open a bug ticket...
    and I'd like to point out that you can also report bugs via RT by sending email to bug-Distribution-Name#rt.cpan.org (# used in place of @ like on rt.cpan.org).

    For example, if you wanted to send a bug report for PPM::Repositories (for example you've discovered a new ppm repository you want added to the list), you would send mail to bug-PPM-Repositories#rt.cpan.org

    So if you're releasing something on CPAN, it's not a bad idea to add the following to your pod (replace the parts in bold with appropriate info)

    =head1 BUGS
    
    To report bugs, go to
    E<lt>http://rt.cpan.org/NoAuth/Bugs.html?Dist=Distribution-NameE<gt>
    or send mail to E<lt>bug-Distribution-Name#rt.cpan.orgE<gt>
    
    Also, be sure to run podchecker to make sure your pod is proper ;)

    update: A common mistake is to include example.pl in the same directory as Makefile.PL. MakeMaker will pick up example.pl (any *.pl file) and install it next to Bar.pm. The easiest workaround is to keep examples in a separate directory (eg or examples) or rename the file to example_pl.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

ExtUtils::MakeMaker::Tutorial (Re: How to make a CPAN Module Distribution)
by QwertyD (Pilgrim) on Jan 07, 2004 at 23:16 UTC

    One of my biggest questions when I started writing modules was "what the heck are all those files in a module distribution, and what are they for?"

    Well, I recently found ExtUtils::MakeMaker::Tutorial, which is an excellent guide to how to structure the files of a module distribution. I don't think it existed when tachyon wrote this node, so it's not his fault that his list additional resources is no longer quite as comprehensive. :-)


    Once it's Turing complete, everything else is just syntactic sugar.
Re: How to make a CPAN Module Distribution
by xdg (Monsignor) on Mar 08, 2004 at 16:21 UTC

    I've recently posted ExtUtils::ModuleMaker::TT to CPAN, which extends ModuleMaker to allow user-customized templates to support personal coding style. Also, it includes makeperlmod -- a new command line script that will read default ModuleMaker values from a config file when generating skeleton distributions. As a side benefit, it can add new skeleton .pm and .t files into an existing ModuleMaker distribution tree.

    -xdg

    Code posted by xdg on PerlMonks is public domain. It has no warranties, express or implied. Posted code may not have been tested. Use at your own risk.

Re: How to make a CPAN Module Distribution
by meonkeys (Chaplain) on Aug 15, 2004 at 02:27 UTC
Re: How to make a CPAN Module Distribution
by petdance (Parson) on Nov 15, 2004 at 21:09 UTC
    The best package for starting a module these days is Module::Starter.

    xoxo,
    Andy

Re: How to make a CPAN Module Distribution
by toolic (Bishop) on Nov 04, 2009 at 15:15 UTC
Re: How to make a CPAN Module Distribution
by Anonymous Monk on Jan 24, 2008 at 20:27 UTC
    Hello, I've made a simple web interface to Module::Starter at http://leto.net/modstarter/ which allows you to choose a few settings, press a button and either view or download a skeleton CPAN module. Hopefully it will be useful to those starting out. Jonathan Leto

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perltutorial [id://158999]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2024-03-19 09:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found