NAME

My::Module::Build - Helper for releasing my (DOMQ's) code to CPAN

SYNOPSIS

This module works mostly like Module::Build with a few differences highlighted below. Put this in Build.PL:

use strict;
use warnings;

## Replace
# use Module::Build;
## with
use FindBin; use lib "$FindBin::Bin/inc";
use My::Module::Build;

## Replace
# my $builder = Module::Build->new(
## With
my $builder = My::Module::Build->new(
   ## ... Use ordinary Module::Build arguments here ...
   build_requires =>    {
         'Acme::Pony'    => 0,
         My::Module::Build->requires_for_build(),
   },
   add_to_no_index => { namespace => [ "My::Private::Stuff" ] },
);

## The remainder of the script works like with stock Module::Build

DESCRIPTION

DOMQ is a guy who releases CPAN packages from time to time - you are probably frobbing into one of them right now.

This module is a subclass to Module::Build by Ken Williams, and a helper that supports DOMQ's coding style for Perl modules so as to facilitate relasing my code to the world.

How to use My::Module::Build for a new CPAN package

This part of the documentation is probably only useful to myself, but hey, you never know - Feel free to share and enjoy!

  1. If not already done, prepare a skeletal CPAN module that uses Module::Build as its build support class. Module::Starter and its companion command module-starter(1) is highly recommended for this purpose, e.g.

    module-starter --mb --module=Main::Screen::Turn::On \
      --author='Dominique Quatravaux' --email='domq@cpan.org' --force
  2. create an inc/ subdirectory at the CPAN module's top level and drop this file there. (While you are there, you could put the rest of the My:: stuff along with it, and the t/maintainer/ test cases - see "SEE ALSO".)

  3. Amend the Build.PL as highlighted in the "SYNOPSIS".

  4. VERY IMPORTANT! Arrange for My::Module::Build and friends to not be indexed on the CPAN, lest the Perl deities' wrath fall upon you. This is done by adding the following lines to the META.yml file:

    no_index:
      directory:
        - examples
        - inc
        - t

    (indentation is meaningful - "no_index:" must start at the very first column and the indenting quantum is exactly 2 spaces, no tabs allowed)

    If you prefer the META.yml file to be built automatically, do a

    ./Build manifest
    ./Build distmeta

    and the aforementioned no_index exclusions will be set up automatically (but please double-check nevertheless).

Coding Style and Practices supported by this module

No, I don't want to go into silly regulations regarding whether I should start a new line before the opening bracket in a sub declaration. This would be coding syntax, or coding grammar. The stuff here is about style, and only the subset thereof that is somehow under control of the CPAN build process.

Unit tests

A large fraction of the unit tests are written as perlmodlib-style __END__ documents attached directly to the module to test. See My::Tests::Below for details. My::Module::Build removes the test footer at build time so as not to waste any resources on the install target platform.

Extended test action

The ./Build test action allows one to specify a list of individual test scripts to run, in a less cumbersome fashion than straight Module::Build:

./Build test t/sometest.t lib/Foo/Bar.pm

For the developper's comfort, if only one test is specified in this way, ACTION_test assumes that verbose mode is wanted (see "test" in Module::Build). This DWIM can be reversed on the command line:

./Build test verbose=0 t/sometest.t

In the case of running a single test, ACTION_test also automatically detects that we are running under Emacs' perldb mode and runs the required test script under the Perl debugger. Running a particular test under Emacs perldb is therefore as simple as typing:

M-x perldb <RET> /path/to/CPAN/module/Build test MyModule.pm

If a relative path is passed (as shown), it is interpreted relative to the current directory set by Emacs (which, except under very bizarre conditions, will be the directory of the file currently being edited). The verbose switch above applies here by default, conveniently causing the test script to run in verbose mode in the debugger.

Like the original "test" in Module::Build, ./Build test accepts supplemental key=value command line switches, as exemplified above with verbose. Additional switches are provided by My::Module::Build:

use_blib=0

Load modules from the source directory (e.g. lib) instead of the build directories (e.g. blib/lib and blib/arch). I use this to debug Inline::C code in a tight tweak-run-tweak-run loop, a situation in which the MD5-on-C-code feature of Inline saves a lot of rebuilds.

full_debugging=1

Sets the FULL_DEBUGGING environment variable to 1 while running ./Build test, in addition to any environment customization already performed by "customize_env". Packages of mine that use Inline enable extra debugging when this environment variable is set.

Dependent Option Graph

This feature wraps around "prompt" in Module::Build, "get_options" in Module::Build and "notes" in Module::Build to streamline the programming of optional features into a ./Build.PL script. Here is a short synopsis for this feature:

my $class = My::Module::Build->subclass(code => <<'CODE');

sub install_everything: Config_Option {
    question => "Install everything",
    default => 1;
}

sub install_module_foo: Config_Option(type="boolean") {
    my $build = shift;
    return (default => 1) # Don't even bother asking the question
       if $build->option_value("install_everything");
    question => "Install module foo",
    default => 0;
}

CODE

my $builder = $class->new(...) # See SYNOPSIS

Options can then be fed from the command line (e.g. ./Build.PL --gender=f) or by answering the questions interactively on the terminal. My::Module::Build will ask the questions at "new" time, in the correct order if they depend on each other (as shown in the example), detect circular dependencies, and die if a mandatory question does not get an appropriate answer.

Syntax

As shown above, options are methods in a subclass to My::Module::Build with a subroutine attribute of the form Config_Option(key1=value1, ...). Right now the following keys are defined:

type

The datatype of this option, either as a word (e.g. "boolean", "integer" or "string") or as a GetOpt::Long qualifier (e.g. "!", "=s" or "=i").

The default is to guess from the name of the option: "install_foo" and "enable_bar" are supposed to be booleans, "baz_port" an integer, and everything else a string.

The name of the method is the internal key for the corresponding option (e.g. for "option_value"). It is also the name of the corresponding command-line switch, except that all underscores are converted to dashes.

The method shall return a (key, value) "flat hash" with the following keys recognized:

question

The question to ask, as text. A question mark is appended automatically for convenience if there isn't already one. If no question is set, My::Module::Build will not ask anything for this question even in interactive mode, and will attempt to use the default value instead (see below).

default

In batch mode, the value to use if none is available from the command line or the persisted answer set from previous attempts to run ./Build.PL. In interactive mode, the value to offer to the user as the default.

mandatory

A Boolean indicating whether answering the question with a non-empty value is mandatory (see also "prompt" for a twist on what "non-empty" exactly means). The default mandatoryness is 1 if default is not returned, 0 if default is returned (even with an undef value).

REFERENCE

Constructors and Class Methods

These are intended to be called directly from Build.PL

new(%named_options)

Overloaded from parent class in order to call "check_maintainer_dependencies" if "maintainer_mode_enabled" is true. Also sets the recursive_test_files property to true by default (see "test_files" in Module::Build), since I like to store maintainer-only tests in t/maintainer (as documented in "find_test_files").

In addition to the %named_options documented in "new" in Module::Build, My::Module::Build provides support for the following switches:

add_to_no_index => $data_structure

Appends the aforementioned directories and/or namespaces to the list that "ACTION_distmeta" stores in META.yml. Useful to hide some of the Perl modules from the CPAN index.

requires_for_build()

Returns a list of packages that are required by My::Module::Build itself, and should therefore be appended to the build_requires hash as shown in "SYNOPSIS".

maintainer_mode_enabled()

Returns true iff we are running "./Build.PL" or "./Build" off a revision control system of some kind. Returns false in all other situations, especially if we are running on an untarred package downloaded from CPAN.

check_maintainer_dependencies()

Checks that the modules required for modifying the CPAN package are installed on the target system, and displays a friendly, non-fatal message otherwise. This method is automatically run from "new" if appropriate (that is, if "maintainer_mode_enabled" is true).

show_warning($message)

Displays a multi-line message $message to the user, and prompts him/her to "Press RETURN to continue".

show_fatal_error($message)

Like "show_warning", but throws an exception after displaying $message.

Methods

These are intended to be called directly from Build.PL

topir

Returns the directory in which Build.PL resides.

package2filename($packagename)

Converts $packagename (e.g. Foo::Bar) into its OS-specific notation (e.g. Foo/Bar.pm).

process_Inline_C_file($filename, @preload_modules)

Arranges for Inline::C code contained in $filename to be compiled into .bs's and .so's. @preload_modules is a list of Perl packages (in Perl use notation, eg Foo::Bar instead of Foo/Bar.pm) that should be loaded with use before starting the Inline install process. Uses a stamp file in blib/stamp to avoid compiling anew if neither $filename nor @preload_modules changed.

use_blib()
use_blib($boolean)

Returns false if the user specified use_blib=0 on the command line, and true otherwise. See "Extended test action" for details. The form with a parameter allows one to set the value that will subsequently be returned by use_blib, thereby overriding the command line.

Dependent Option Graph Methods

option_value($optionname)

Returns the value selected for the option $optionname. From within an option declaration sub, this call may result in the question for $optionname (and its own dependencies, recursively) being asked on the terminal at once. If a loop is detected so doing, option_value() will die with a messsage that starts with the word "RECURSION".

Answers to questions are persisted using Module::Build's ->notes mechanism: outside the option declaration subs, option_value("foo-bar") is therefore an alias for notes("option:foo_bar").

Other Public Methods

Those methods will be called automatically from within the generated ./Build, but on the other hand one probably shouldn't call them directly from Build.PL . One may wish to overload some of them in a package-specific subclass, however.

ACTION_build

Overloaded to add "ACTION_buildXS" as a dependency.

ACTION_dist

Overloaded so that typing ./Build dist does The Right Thing and regenerates everything that is needed in order to create the distribution tarball. This includes the Makefile.PL if so requested (see "create_makefile_pl" in Module::Build::Compat) and the MANIFEST file (see "manifest" in Module::Build). On the other hand, the META.yml file is not regenerated automatically, so that the author has the option of maintaining it by hand.

ACTION_buildXS

Does nothing. Intended for overloading by packages that have XS code, which e.g. may want to call "process_Inline_C_file" there.

ACTION_test

Overloaded to add t/lib and t/inc to the test scripts' @INC (we sometimes put helper test classes in there), and also to implement the features described in "Extended test action". See also "_massage_ARGV" for more bits of the Emacs debugger support code.

ACTION_distmeta

Overloaded to ensure that .pm modules in inc/ don't get indexed and that the add_to_no_index parameter to "new" is honored.

customize_env(%env)

Returns a copy of %env, an environment hash, modified in a package-specific fashion. To be used typically as

local %ENV = $self->customize_env(%ENV);

The default implementation sets PERL_INLINE_BUILD_NOISY to 1 and also sets FULL_DEBUGGING if so directed by the command line (see " ACTION_test").

process_pm_files

Called internally in Build to convert lib/**.pm files into their blib/**.pm counterpart; overloaded here to remove the test suite (see "Unit tests") and standardize the copyright of the files authored by me.

process_pm_file_if_modified(%args)

Does the same as copy_file_if_modified (which it actually replaces while process_pm_files runs), except that the "new_pm_filter" is applied instead of performing a vanilla copy as Module::Build does.

new_pm_filter

Creates and returns a fresh filter object (see "My::Module::Build::PmFilter Ancillary Class") that will be used by "process_pm_file_if_modified" to process the text of the .pm files. Subclasses may find it convenient to overload new_pm_filter in order to provide a different filter. The filter object should obey the API set forth in "My::Module::Build::PmFilter Ancillary Class", although it need not inherit from same.

find_test_files()

Overloaded from parent class to treat all .pm files in lib/ and t/lib/ as unit tests if they use My::Tests::Below, to look for .t files in examples/, and to retain .t test files in t/maintainer if and only if "maintainer_mode_enabled" is true.

find_test_files_predicate()
find_test_files_in_directories()

Those two methods are used as callbacks by "find_test_files"; subclasses of My::Module::Build may therefore find it convenient to overload them. find_test_files_in_directories should return a list of the directories in which to search for test files. find_test_files_predicate gets passed the name of each file found in these directories in the same way as a File::Find wanted sub would (that is, using $_ and not the argument list); it should return a true value iff this file is a test file.

BUGS

The zero-wing easter egg only works through the Makefile.PL compatibility mode. On the other hand, "./Build your time" would not sound quite right, would it?

Perhaps the "Dependent Option Graph" features should be repackaged as a standalone Module::Build plug-in.

SEE ALSO

My::Tests::Below

t/maintainer/*.t