Building a Distribution with h2xs
29 Mar 01 -

I have discussed using h2xs in a previous article (dated April 27, 2000 in the article archives: see link below), but I think it would good to look at it again in a little more depth in light of the last two articles and because it produces slightly different output in version 5.6.0 than in 5.005.

Let’s say we decide to build our Cool module and we want to be able to package it up and share it (or perhaps upload it to CPAN if you have a CPAN id). We can automate much of the task by using the h2xs utility that comes with perl:

    [jandrew]$ h2xs -XAn Cool
    Writing Cool/
    Writing Cool/Makefile.PL
    Writing Cool/
    Writing Cool/Changes
    Writing Cool/MANIFEST

We used the -X option because we are not creating an XS module, and the -A option because we are not using the Autoloader facility (both are beyond the scope of this article), and the -n option to specify the name of the module (Cool in this case). You can see from the output that it has created a ‘Cool’ directory and written several files in it for us. The one we are really interested in is the file, which is a skeleton of our module. If you are using version 5.005 then the contents of the module file will begin like:

    package Cool;

    use strict;
    use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);

    require Exporter;

    @ISA = qw(Exporter AutoLoader);

    # Items to export into callers namespace by default. Note: do not
    # export names by default without a very good reason. Use
    # EXPORT_OK instead.  Do not simply export all your public
    # functions/methods/constants.

    @EXPORT = qw(

    $VERSION = '0.01';

    # Preloaded methods go here.

    # Autoload methods go after =cut, and are processed by the
    # autosplit program.


There is also stub POD after the END token (see: perldoc perlpod). Unfortunately, even using the -A option, this still tries to include Autoloader in the @ISA array — you should remove that, and delete the the last comment since we aren’t using autoloaded methods.

As you can see, this is the basic structure of the module we previously built by hand, although there I neglected to ‘use strict’ and declare our globals with ‘use vars’ (oversight on my part). You’ll also note that although the @EXPORT array is ready for us to fill, the @EXPORT_OK array isn’t set up — I would simply change that to be @EXPORT_OK if I wanted to export by demand (which I usually do).

All that’s left for us to do here is add put our cool() function into the @EXPORT_OK array and then define that subroutine after the ‘Preloaded methods go here’ comment.

In 5.6.0 the skeleton file begins like:

    package Cool;

    require 5.005_62;
    use strict;
    use warnings;

    require Exporter;

    our @ISA = qw(Exporter);

    # Items to export into callers namespace by default. Note: do not
    # export names by default without a very good reason. Use EXPORT_OK
    # instead.  Do not simply export all your public
    # functions/methods/constants.

    # This allows declaration use Cool ':all'; If you do not need this,
    # moving things directly into @EXPORT or @EXPORT_OK will save memory.

    our %EXPORT_TAGS = ( 'all' => [ qw(

    ) ] );

    our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

    our @EXPORT = qw(

    our $VERSION = '0.01';

    # Preloaded methods go here.


The only differences being that the arrays are now declared with our() which is new in 5.6.0, and we have an %EXPORT_TAGS hash. Using this hash is beyond the scope of this article, and isn’t necessary for our simple module — thus, I suggest simply ignoring or deleting it and removing the @{ $EXPORT_TAGS{‘all’} } expression from the @EXPORT_OK array. As before, all you need to do now is add your function definition and put its name into whichever of the EXPORT arrays you desire.

But there is more to a distribution than simply having a skeleton .pm file built for us — what about those other files? Well, the other files are there to automated building, testing, and installing the module. Once you’ve completed filling your module, you can install it like so:

    perl Makefile.PL
    make test
    make install

And, if you wanted to install it under a private directory:

    perl Makefile.PL PREFIX=/home/jandrew/perl5lib

When installing, perl will create any needed subdirectories under that directory and install the module appropriately. If you are on windows, you’ll probably need to get ‘nmake’ and use that rather than make.

To create up a distributable package (containing your module and all the ancillary files) you need only do:

    make dist

Doing so in my example module directory creates a ‘Cool-0.01.tar.gz’ which I can now send to a friend or upload to my web-site or otherwise distribute. For further module information please see the following perl docs:

    perldoc perlmod
    perldoc perlmodlib
    perldoc perlmodinstall
    perldoc -f use
    perldoc -f require