|Think about Loose Coupling|
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 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:
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.
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:
You should now have a proto-distro that looks like this:
Building a multi-module distribution
If you want to build a distribution that contains two modules like:
Then all you need is this structure (which you can't instantly get from h2xs):
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:
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 h2xsThese 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:
See its docs for more details.
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):
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:
You can make this structure from the standard h2xs output like this:
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:
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:
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.
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:
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.
Finally there are a few practical points.
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 :-)