Alien-Selenium
view release on metacpan or search on metacpan
inc/My/Module/Build.pm view on Meta::CPAN
=head1 SYNOPSIS
This module works mostly like L<Module::Build> with a few differences
highlighted below. Put this in Build.PL:
=for My::Tests::Below "synopsis" begin
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
=for My::Tests::Below "synopsis" end
=head1 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 L<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.
=head2 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!
=over
=item 1.
If not already done, prepare a skeletal CPAN module that uses
L<Module::Build> as its build support class. L<Module::Starter> and
its companion command C<module-starter(1)> is B<highly> recommended
for this purpose, e.g.
module-starter --mb --module=Main::Screen::Turn::On \
--author='Dominique Quatravaux' --email='domq@cpan.org' --force
=item 2.
create an C<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 L<SEE
ALSO>.)
=item 3.
Amend the Build.PL as highlighted in the L</SYNOPSIS>.
=item 4.
B<VERY IMPORTANT!> Arrange for My::Module::Build and friends to
B<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:
=for My::Tests::Below "META.yml excerpt" begin
no_index:
directory:
- examples
- inc
- t
=for My::Tests::Below "META.yml excerpt" end
(indentation is meaningful - "no_index:" must start at the very first
column and the indenting quantum is exactly 2 spaces, B<no tabs
allowed>)
If you prefer the META.yml file to be built automatically, do a
=for My::Tests::Below "distmeta" begin
./Build manifest
./Build distmeta
=for My::Tests::Below "distmeta" end
and the aforementioned no_index exclusions will be set up
automatically (but B<please double-check nevertheless>).
=back
=head2 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.
=head3 Unit tests
A large fraction of the unit tests are written as perlmodlib-style
__END__ documents attached directly to the module to test. See
L<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.
=head3 Extended C<test> action
inc/My/Module/Build.pm view on Meta::CPAN
=cut
sub process_pm_files {
no warnings "once";
local *copy_if_modified = \*process_pm_file_if_modified;
my $self = shift;
return $self->SUPER::process_pm_files(@_);
}
=item I<process_pm_file_if_modified(%args)>
Does the same as L<copy_file_if_modified> (which it actually replaces
while L<process_pm_files> runs), except that the L</new_pm_filter> is
applied instead of performing a vanilla copy as L<Module::Build> does.
=cut
sub process_pm_file_if_modified {
my ($self, %args) = @_;
my ($from, $to) = @args{qw(from to)};
return if $self->up_to_date($from, $to); # Already fresh
mkpath(dirname($to), 0, 0777);
# Do a filtering copy
print "$from -> $to\n" if $args{verbose};
die "Cannot open $from for reading: $!\n" unless
(my $fromfd = new IO::File($from, "r"));
die "Cannot open $to for writing: $!\n" unless
(my $tofd = new IO::File($to, "w"));
my $filter = $self->new_pm_filter;
while(my $line = <$fromfd>) {
my $moretext = $filter->filter($line);
if (defined($moretext) && length($moretext)) {
$tofd->print($moretext) or
die "Cannot write to $to: $!\n";
}
last if $filter->eof_reached();
}
$tofd->close() or die "Cannot close to $to: $!\n";
}
=item I<new_pm_filter>
Creates and returns a fresh filter object (see
L</My::Module::Build::PmFilter Ancillary Class>) that will be used by
L</process_pm_file_if_modified> to process the text of the .pm files.
Subclasses may find it convenient to overload I<new_pm_filter> in
order to provide a different filter. The filter object should obey
the API set forth in L</My::Module::Build::PmFilter Ancillary Class>,
although it need not inherit from same.
=cut
sub new_pm_filter { My::Module::Build::PmFilter->new }
=item I<find_test_files()>
Overloaded from parent class to treat all .pm files in C<lib/> and
C<t/lib/> as unit tests if they use L<My::Tests::Below>, to look for
C<.t> files in C<examples/>, and to retain C<.t> test files in
C<t/maintainer> if and only if L</maintainer_mode_enabled> is true.
=cut
sub find_test_files {
my $self = shift;
# Short-cut activated by L</ACTION_test>:
return $self->{FORCE_find_test_files_result} if
(defined $self->{FORCE_find_test_files_result});
my @tests = @{$self->SUPER::find_test_files(@_)};
# Short-cut activated by putting a 'test_files' key in the constructor
# arguments:
return @tests if $self->{test_files};
@tests = grep { ! m/^t.maintainer/ } @tests unless
($self->maintainer_mode_enabled());
File::Find::find
({no_chdir => 1, wanted => sub {
push(@tests, $_) if $self->find_test_files_predicate();
}}, $self->find_test_files_in_directories);
return \@tests;
}
=item I<find_test_files_predicate()>
=item I<find_test_files_in_directories()>
Those two methods are used as callbacks by L</find_test_files>;
subclasses of I<My::Module::Build> may therefore find it convenient to
overload them. I<find_test_files_in_directories> should return a list
of the directories in which to search for test files.
I<find_test_files_predicate> gets passed the name of each file found
in these directories in the same way as a L<File::Find> C<wanted> sub
would (that is, using $_ and B<not> the argument list); it should
return a true value iff this file is a test file.
=cut
sub find_test_files_predicate {
my ($self) = @_;
return 1 if m/My.Tests.Below\.pm$/;
return if m/\b[_.]svn\b/; # Subversion metadata
return 1 if m/\.t$/;
my $module = catfile($self->base_dir, $_);
local *MODULE;
unless (open(MODULE, "<", $module)) {
warn "Cannot open $module: $!";
return;
}
return 1 if grep {
m/^require\s+My::Tests::Below\s+unless\s+caller/
} (<MODULE>);
return;
}
sub find_test_files_in_directories {
( run in 1.732 second using v1.01-cache-2.11-cpan-df04353d9ac )