Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

MakeMaker, h2xs, and writing CPAN modules

by perrin (Chancellor)
on Jun 23, 2002 at 22:57 UTC ( [id://176641]=perlquestion: print w/replies, xml ) Need Help??

perrin has asked for the wisdom of the Perl Monks concerning the following question:

I feel a bit foolish asking this, but here goes...

Although I've written many modules over the years, I've never written one for CPAN. Now I'm trying to and finding that the logistics of it are a bit confusing.

As recommended, I started with h2xs. It created a skeleton directory tree like this:

[perrin@charlotte oscon]$ h2xs -AX -n Foo::Bar Writing Foo/Bar/Bar.pm Writing Foo/Bar/Makefile.PL Writing Foo/Bar/test.pl Writing Foo/Bar/Changes Writing Foo/Bar/MANIFEST
Well, this is all good, but now I can't actually load that stub without installing the module, i.e. if I say use Foo::Bar, perl will not find Bar.pm in that structure. I could install the module and edit it, but then how do I bundle it back up for distribution? Do I have to manually copy everything back into place?

Apologies if this is all covered in the MakeMaker docs somewhere that I missed. If someone can give me a good pointer, I'll be happy to RTFM.

For the curious, the module (no, it's not really called Foo::Bar), is part of my presentation for this year's Perl Conference.

Replies are listed 'Best First'.
Re: MakeMaker, h2xs, and writing CPAN modules
by Zaxo (Archbishop) on Jun 23, 2002 at 23:03 UTC

    The use blib '/path/to'; pragmatic is what you want.

    Update: blib.pm will automatically search '..' and above. You need to build your module, but not install it. Then use blib; without any argument works fine from the build directory or any subdirectory of it. If you want to test from another pwd, the argument should be the absolute path to the build directory. Have fun!

    After Compline,
    Zaxo

      Thanks! This works from command-line, but if I make a simple script and try to use it, it fails. Here's an example script:
      #!/usr/bin/perl -w use blib '..';
      And here's the message I get:
      Cannot find blib even in /home/perrin/oscon/../../../../.. BEGIN failed--compilation aborted at ./bench.pl line 3.
        In the usual incantation:
        perl Makefile.PL
        make
        make test
        make install
        
        the build library (blib) is created by the second line make, and is most useful in the third line make test. You cannot use blib before make.

        And if you can't even after that, there is something seriously wrong with your makefile / machine / Perl installation / file system / what not.

Re: MakeMaker, h2xs, and writing CPAN modules
by Ovid (Cardinal) on Jun 24, 2002 at 05:10 UTC

    What I understood you to ask was this: how do I create a distribution so that I can edit my module in place without having to install it? The docs aren't clear, but this is basically how this works. First, edit h2xs and change the $author and $email to your name and email address (otherwise, h2xs will write out spurious information for this and you'll have to edit the results). Then, do this:

    1. h2xs -AX -n Foo::Bar -v .01
    2. Copy your module to Bar.pm
    3. Fill out test.pl or, better yet, create a Foo/Bar/t/ directory and create tests there (be sure to update the MANIFEST)
    4. perl Makefile.pl
    5. make
    6. make test
    7. make dist

    It's the last step that makes a distribution for you!

    Also note the -v argument to h2xs. That tells it what your version number is, so that's automatically created for you, if you're filling in the module manually as opposed to copying one that you've already made. You can skip this if you wish.

    If, for some reason, your tests do not pass, be sure to run make clean, fix your module (and/or tests) and repeat the above steps, from step 4 (perl Makefile.PL), until the tests pass. If you fail to run make clean, any edits you make to Foo/Bar.pm will not be picked up.

    When you run make test, all tests will be run through the test harness, which will load your module from the blib directory that is created. Thus, there is no need to actually install the module.

    Hope this helps.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

      Okay, so you're saying the thing to do is write the module and then use h2xs just to help create the distribution? That sounds reasonable and is basically what I've ended up with, it's just that all of the docs make it sound like you should start with h2xs.

        You can write the module either before or after you use h2xs. I've done both. When the docs are so strident about using h2xs, they're primarily referring to using it for modules that you are going to distribute (see "How To Write a Makefile.PL" in perldoc ExtUtils::MakeMaker).

        If you've already written your module, then use h2xs, though to be frank, using this utility before you start to write the module is easier because the Test::Harness is all ready to go, thus writing tests and using make test is sooooo much simpler.

        Cheers,
        Ovid

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: MakeMaker, h2xs, and writing CPAN modules
by samtregar (Abbot) on Jun 24, 2002 at 00:19 UTC
    Why do you want to use the module without installing it? Is it to test the module during development? If so, put your test code in test.pl and run it with make test. Alternately you can delete test.pl and create a t/ directory containing multiple test scripts with arbitary names that will be run by make test.

    If you're just in the mood to run arbitrary scripts against your development copy of Bar.pm then a quick hack would be:

    $ ln -s Foo/Bar/Bar.pm Foo/Bar.pm $ export PERL5LIB=`pwd`

    Modulo your shell of choice - the above is for bash.

    The blib solution mentioned already will also work but you'll need to do a make to copy Bar.pm into Foo/Bar/blib/ each time you make a change.

    -sam

    PS: I cover all this and more in my upcoming book - Writing Perl Modules for CPAN.

      Thanks, the symlink approach seems to fit what I'm after. There are subclasses in my module (Foo::Bar::Baz) so I guess I'll try linking the directory rather than just one file.

      What I'm trying to do seems like it should be easy: make a module skeleton with h2xs, work on it in place, and finally make a release from it. The "work on it in place" is turning out to be surprisingly difficult. So far I've just installed it into a local directory (so that I don't have to edit it as root) and I'll have to copy it back into my release directory structure when I have a version that's ready to go. I can live with that, but I expected to be able to work on it directly in place after creating it with h2xs.

      I'm using the module in the context of mod_perl, so being able to run it from scripts outside of the module's directory is necessary.

        Ahh - this really sounds like you are making this harder than it should be. I like to have the following kind of structure (below). In the XP fashion I like to write my tests first as I build up the object. I must admit to not using h2xs that much, but we have a template that is used to create new modules which need to inherit from a base class anyways so I guess we're still being structured (whew).
        project/lib/Foo/Bar/Baz.pm project/lib/Foo.pm project/t/test1.t $ cat t/test1.t use lib './lib'; use strict; my $error; BEGIN { use vars qw($TESTCOUNT); use Test; # so we actually do some more stuff # here to load the Test module # since we distribute it with our package # in case the user doesn't have it $TESTCOUNT = 3; plan tests => $TESTCOUNT; # do some other testing eval { Some::module::Needed; }; if( $@ ) { $error =1 } } END { # if we exit prematurely in the test the testcount # will still be okay (assuming we want to bail # when some module isn't installed or # or the network is unavailable, etc. foreach ( $Test::ntest..$TESTCOUN) { skip("unable to run all the tests",1); } } if( $error ) { exit(0) } use Foo; use Foo::Bar::Baz; my $foo = new Foo(-id => '10'); ok($foo); ok($foo->id, '10); my $baz = new Foo::Bar::Baz(-magicword => 'peanutbuttersandwiches'); ok($base->magic, 'peanutbuttersandwiches'); $ perl -I. -w t/test1.t 1..3 ok 1 ok 2 ok 3
        The above wasn't actually run but hopefully I didn't leave any typos in - if you don't want to put things in a lib directory you can always s/lib/ above and all will work (your would be doing use lib '.' instead). You can also have PERL5LIB set to include XXX/project/lib. I may be overzealous using the perl -I. -w for my tests when I have PERL5LIB set, but since often I have version of the toolkit installed while I'm working on the next one, I don't want to get confused about which code I am actually running.

      PPS: I covered this in a Perlmonks tutorial How to make a CPAN Module Distribution. Here, now, and available for free.... There is a good thread around it offering plenty of M to FWR if you need more details or would like to look at some of the alternatives to h2xs.

      Hope you get some mileage.

      cheers

      tachyon

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

Re: MakeMaker, h2xs, and writing CPAN modules
by Matts (Deacon) on Jun 24, 2002 at 07:02 UTC
    I use an alternative script to h2xs that doesn't include all the cruft that h2xs drags along with it. It also does the right thing with the t/ directory (rather than test.pl) and puts the module in its own lib/ directory, so that you can "use lib" to get the right directory for simple tests before installing it.

    You can get my newproj script here.

    Update: I forgot, it also creates a MANIFEST.SKIP for you, which is incredibly useful if you're as forgetful as I am!

Re: MakeMaker, h2xs, and writing CPAN modules
by demerphq (Chancellor) on Jun 24, 2002 at 11:17 UTC
    Hi Perrin,

    Ive had similar issues as you are discussing here, and the approach ive come up with to work around them is as follows:

    • set the enviornment variable PERL5LIB to be the root of your "lib development path". So for my machine its set to
      perl5lib=d:\development\perl\devlib
      Now anything in this path is treated as it would be if it were per/lib or perl/site/lib
    • From this directory use h2xs to create a module framework. There is a trick with this however. Once you do
      h2xs -AXC -n Foo::Bar
      Go into the Bar directory and move everything up 1 level. And then lose the Bar directory.
      move *.* .. rd Bar
    • Now to save yourself some pain (IMO) create a subdirectory of Foo called t. move the created test.pl into /t and rename it test.t
    And now you need to edit the various files created by h2xs. Dont forget to add the /t directory to the MANIFEST, change the A.U.THOR name, specify your prerequisites in the makfile.pm and add documentation.

    Once all of this is done,(assuming i havent forgotten some niggling but important detail) your module should be _both_ useable as normal and usable as per make. Thus once you are happy with the module you should be able to say

    nmake nmake test nmake dist
    A caveat however: this technique has the problem that you can only be developing 1 module at a time in each path/class heirarchy. Ie you cant work on Foo::Bar and Foo::Baz at the same time (the makefiles and etc would overwrite each other.)

    To be honest, normally I develop a module in the devlib _without_ using h2xs first. Then I use h2xs and copy everything but the autogenerated .pm file into the appropriate directory.

    As always with advice like this: YMMV

    Yves / DeMerphq
    ---
    Writing a good benchmark isnt as easy as it might look.

Re: MakeMaker, h2xs, and writing CPAN modules
by strat (Canon) on Jun 24, 2002 at 08:49 UTC
    Hi,

    if I write some code consisting of several modules which are of no use for CPAN (or don't need it for several scripts), I like to keep them with the scripts in a directory structure like, e.g.

    myscript/bin ..... scripts myscript/lib ..... modules myscript/lib/build . for building modules with h2xs myscript/source .. sourcefiles myscript/log ..... for logfiles myscript/doc ..... documentation myscript/work .... working dir(s) myscript/result .. output dir ....
    or the like.

    If I do it this way, I prefer loading modules the following way:

    BEGIN { use FindBin (); use lib "$FindBin::Bin/../lib"; require ModulXY; } # BEGIN
    Btw: I could use "use" instead of require, but since I hardly ever do namespace pollution, I somehow quite satisfied with require.

    For building modules, I use h2xs if there's just a slight change that I could share it on CPAN, and keep several build directories and keep links (under Unix/Linux) from ./lib to the modules untill they are finished.

    So far, my 2 cent...

    Best regards,
    perl -e "s>>*F>e=>y)\*martinF)stronat)=>print,print v8.8.8.32.11.32"

Re: MakeMaker, h2xs, and writing CPAN modules
by TStanley (Canon) on Jun 25, 2002 at 02:15 UTC
    When I created Games::QuizTaker, I wrote the module under a different package name, and used a simple test script to check the functions at various stages. When I was ready for CPAN, I renamed the package, created a directory structure using h2xs, and dropped the module in. I also modified the Makefile.PL to include my name and email address, and wrote the README file and the tests. Then all that was left was to make the distribution file and submit.

    TStanley
    --------
    Never underestimate the power of very stupid people in large groups -- Anonymous
Re: MakeMaker, h2xs, and writing CPAN modules
by Anonymous Monk on Oct 24, 2003 at 14:03 UTC
    Over a year later, I feel like adding, for Googlers, what nobody seems to have mentioned (because it's too obvious?): perl's -I switch.
    For one-time runs of scripts using a module in some special place, or a version different from the installed version:
    perl -I/my/temp/lib myscript.pl
    See perldoc perlrun.
      That doesn't solve the problem. The real issue is that h2xs makes a directory structure that doesn't actually work in place.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://176641]
Approved by jsprat
Front-paged by samtregar
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (7)
As of 2024-03-19 02:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found