Just a Theory

By David E. Wheeler

Posts about Module::Build

pgTAP 0.10 Released, Web Site Launched

Two major announcements this week with regard to pgTAP:

First, I’ve release pgTAP 0.10. The two major categories of changes are compatibility as far back as PostgreSQL 8.0 and new functions for testing database schemas. Here’s a quick example:

BEGIN;
SELECT plan(7);

SELECT has_table( 'users' );
SELECT has_pk('users');
SELECT col_is_fk( 'users', ARRAY[ 'family_name', 'given_name' ]);

SELECT has_table( 'widgets' );
SELECT has_pk( 'widgets' );
SLEECT col_is_pk( 'widgets', 'id' );
SELECT fk_ok(
    'widgets',
    ARRAY[ 'user_family_name', 'user_given_name' ],
    'users',
    ARRAY[ 'family_name', 'given_name' ],
);

SELECT * FROM finish();
ROLLBACK;

Pretty cool, right? Check the documentation for all the details.

Speaking of the documentation, that link goes to the new pgTAP Web site. Not only does it include the complete documentation for pgTAP, but also instructions for integrating pgTAP into your application’s preferred test environment. Right now it includes detailed instructions for Perl + Module::Build and for PostgreSQL, but has only placeholders for PHP and Python. Send me the details on those languages or any others into which you integrate pgTAP tests and I’ll update the page.

Oh, and it has a beer. Enjoy.

I think I’ll take a little time off from pgTAP next week to give Bricolage some much-needed love. But as I’ll be given another talk on pgTAP at PostgreSQL Conference West next month, worry not! I’ll be doing a lot more with pgTAP in the coming weeks.

Oh, and one more thing: I’m looking for consulting work. Give me a shout (david - at - justatheory.com) if you have some PostgreSQL, Perl, Ruby, MySQL, or JavaScript hacking you’d like me to do. I’m free through November.

That is all.

Looking for the comments? Try the old layout.

Apache::TestMB Released!

As I mentioned last week, I’ve been working on a subclass of Module::Build that supports testing with Apache::Test. Today, Geoff announced the release of Apache::Test 1.12. This release includes the new Module::Build subclass, Apache::TestMB. Now anyone using Apache::Test to test their module can convert the build system to Module::Build.

To set an example, I’ve just released MasonX::Interp::WithCallbacks using the new build module. The conversion was simple; in fact, I think that Apache::TestMBis easier to use than Apache::TestMM (which integrates Apache::Test with ExtUtils::MakeMaker). My Makefile.PL had looked like this:

#!perl -w

use strict;
use ExtUtils::MakeMaker;
use File::Spec::Functions qw(catfile catdir);
use constant HAS_APACHE_TEST => eval {require Apache::Test};

# Set up the test suite.
if (HAS_APACHE_TEST) {
    require Apache::TestMM;
    require Apache::TestRunPerl;
    Apache::TestMM->import(qw(test clean));
    Apache::TestMM::filter_args();
    Apache::TestRunPerl->generate_script();
} else {
    print "Skipping Apache test setup.\n";
}

my $clean = join ' ', map { catfile('t', $_) }
  qw(mason TEST logs);

WriteMakefile(
    NAME        => 'MasonX::Interp::WithCallbacks',
    VERSION_FROM    => 'lib/MasonX/Interp/WithCallbacks.pm',
    PREREQ_PM       => { 'HTML::Mason'             => '1.23',
                                'Test::Simple'            => '0.17',
                                'Class::Container'        => '0.09',
                                'Params::CallbackRequest' => '1.11',
                              },
    clean               => { FILES => $clean },
    ($] >= 5.005 ?    ## Add these new keywords supported since 5.005
      (ABSTRACT_FROM    => 'lib/MasonX/Interp/WithCallbacks.pm',
        AUTHOR           => 'David Wheeler <david@kineticode.com>') : ()),
);

The new Build.PL simplifies things quite a bit. It looks like this:

use Module::Build;

my $build_pkg = eval { require Apache::TestMB }
  ? 'Apache::TestMB' : 'Module::Build';

$build_pkg->new(
    module_name        => 'MasonX::Interp::WithCallbacks',
    license            => 'perl',
    requires           => { 'HTML::Mason'             => '1.23',
                                'Test::Simple'            => '0.17',
                                'Class::Container'        => '0.09',
                                'Params::CallbackRequest' => '1.11'
                              },
    build_requires     => { Test::Simple => '0.17' },
    create_makefile_pl => 'passthrough',
    add_to_cleanup     => ['t/mason'],
)->create_build_script;

Much nicer, eh?

Looking for the comments? Try the old layout.

Module::Build + Apache::Test is Nearly Here

Over the last couple of days, I whipped up a new class to be added to the Apache HTTP Test Project. The new class, Apache::TestMB, is actually a subclass of Module::Build, and finally provides support for using Apache::Test with Module::Build. You use it just like Module::Build; however, since a lot of modules choose to install themselves even if Apache isn’t installed (because they can be used both inside and outside of mod_perl, e.g., HTML::Mason), I’m suggesting that Build.PL files look like this:

use Module::Build;

my $build_pkg = eval { require Apache::TestMB }
  ? "Apache::TestMB" : "Module::Build";

my $build = $build_pkg->new(
  module_name => "My::Module",
)->create_build_script;

Pretty simple, huh? To judge by the discussion, it will soon be committed to the Apache::Test repository and released to CPAN. My MasonX::Interp::WithCallbacks module will debut with a new Apache::TestMB-powered Build.PL soon afterward.

Looking for the comments? Try the old layout.

Fun with Module::Build Argument Processing

I’ve spend the better part of the last two days working on a custom subclass of Module::Build to build Bricolage 2.0. It’s going to be a lot nicer than the nasty custom Makefile that Bricolage 1.x uses. The reason I’m creating a custom subclass of Module::Build is to be able to do a lot of the extra stuff that building Bricolage requires. Such as:

  • Copying configuration files from conf/ into blib
  • Copying configuration files from conf/ into t for testing
  • Copying configuration files from comp/ into blib
  • Modifying Bricolage::Util::Config to contain a hard-coded reference to the location of bricolage.conf once Bricolage has been installed
  • Modifying the contents of bricolage.conf to reflect build options (forthcoming)
  • Modifying the contents of httpd.conf to reflect build options (forthcoming)

I’m sure there will be more as Bricolage develops (such as building the database!), but this is enough for now. I’ve also been hacking on Module::Build itself to add features I want. For example, I want users to be able to pass options to Build.PL when they call it, so that it can do silent installs. As it is, you can pass options now, but Module::Build’s option processing lacks flexibility. For example, you can pass options like this:

perl Build.PL opt1=val1 opt2=val2

And Module::Build will store the options in a hash like this:

{ "opt1" => "val1",
  "opt2" => "val2" }

It understands options that use --, too; This invocation

perl Build.PL --opt1 val1 --opt2 val2

produces the same hash. But be careful how you specify arguments! For example, Modul::Build doesn’t understand unary options or options that use both -- and =>! To whit, this invocation

perl Build.PL --loud --opt1=val1 --opt2=val2 --foobar

Yields a hash like this:

{ "loud" => "--opt1=val1",
  "opt2=val2" => "--foobar" }

Certainly not what I would expect! So to get great flexibility, I sent a patch to the Module::Build mail list adding a new parameter to new(): get_options. This is an array reference of options that will be passed to Getopt::Long::GetOptions() before Module::Build parses arguments. It stores the results in the same hash as Module::Build normally does, and options not specified in get_options will be processed by Module::Build just as before. But it gives a whole lot more control over what gets grabbed. For example, if I were to try to get that last example to do what I want, all I’d need to do is pass in the appropriate Getopt::Long specs:

my $build = Module::Build->new(
    module_name => "Spangly",
    get_options => [ "loud+", "opt1=s", "opt2=s", "foobar" ],
);

Now, the hash yielded is:

{ "loud"   => "1",
  "opt1"   => "val1",
  "opt2"   => "val2",
  "foobar" => "1" }

Isn’t that nicer? And because the full suite of Getopt::Long specification is supported, you can get even fancier:

my $loud = 0;
my $build = Module::Build->new(
    module_name => "Spangly",
    get_options => [ "loud+" => \$loud, "foobar!" ],
);

Now this invocation:

perl Build.PL --loud --loud --nofoobar

…sets the $loudscalar to 2, while the args hash is simply { "foobar" => "0" }. Cool, eh?

Now I’ve just been discussing the patch with Dave Rolsky on the mail list, and he argues that, while this is a good idea in principal, he’d rather see a data-structure based argument list rather than Getopt::Long’s magical strings. Perhaps Module::Build will end up “Borging” some of the ideas from Getopt::Simple. But either way, I think that better argument processing is on the way for Module::Build.

Looking for the comments? Try the old layout.

More about…