File Coverage

blib/lib/Module/Build/Pluggable/PDL.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package Module::Build::Pluggable::PDL;
2              
3             # ABSTRACT: Plugin to Module::Build to build PDL projets
4              
5 1     1   2552268 use strict;
  1         4  
  1         33  
6 1     1   6 use warnings;
  1         2  
  1         47  
7             our $VERSION = '0.23';
8 1     1   5 use parent qw(Module::Build::Pluggable::Base);
  1         8  
  1         8  
9              
10 1     1   438104 use PDL::Core::Dev;
  0            
  0            
11             use List::MoreUtils qw(first_index);
12             use Config;
13             use Pod::Perldoc;
14              
15             sub HOOK_build {
16             my ($self) = @_;
17              
18             $self->add_before_action_modifier( 'distdir', \&HOOK_distdir );
19             $self->add_action( 'forcepdlpp', \&ACTION_forcepdlpp );
20              
21             $self->process_pd_files;
22              
23             return 1;
24             }
25              
26             sub HOOK_configure {
27             my ($self) = @_;
28              
29             $self->_add_include_dirs( PDL::Core::Dev::whereami_any() . '/Core' );
30              
31             $self->_add_extra_linker_flags( $PDL::Config{MALLOCDBG}->{libs} )
32             if $PDL::Config{MALLOCDBG}->{libs};
33              
34             $self->requires( 'PDL' => '2.006' );
35             $self->build_requires( 'PDL' => '2.006' );
36             $self->build_requires( 'ExtUtils::CBuilder' => '0.23' );
37              
38             return 1;
39             }
40              
41             sub _add_include_dirs {
42             my ( $self, @dirs ) = @_;
43              
44             my $include_dirs = $self->builder->include_dirs;
45             push @$include_dirs, @dirs;
46             $self->builder->include_dirs($include_dirs);
47             }
48              
49             sub _add_extra_linker_flags {
50             my ( $self, @new_flags ) = @_;
51              
52             my $linker_flags = $self->builder->extra_linker_flags;
53             push @$linker_flags, @new_flags;
54             $self->builder->extra_linker_flags($linker_flags);
55             }
56              
57             # Allow the person installing to force a PDL::PP rebuild
58             sub ACTION_forcepdlpp {
59             my $self = shift;
60             warn "self is " . ref $self;
61             $self->log_info("Forcing PDL::PP build\n");
62             $self->{FORCE_PDL_PP_BUILD} = 1;
63             $self->ACTION_build();
64             }
65              
66             # largely based on process_PL_files and process_xs_files in M::B::Base
67             sub process_pd_files {
68             my $self = shift;
69             my $builder = $self->builder;
70              
71             warn "# process_pd_files\n";
72              
73             # Get all the .pd files in lib
74             my $files = $builder->rscan_dir( 'lib', qr/\.pd$/ );
75              
76             # process each in turn
77             for my $file (@$files) {
78             my ( $build_prefix, $prefix, $mod_name ) = $self->_filename2info($file);
79              
80             $self->_convert_to_pm( $file, $build_prefix, $prefix, $mod_name );
81              
82             $self->_add_to_provides( {
83             mod_name => $mod_name,
84             file => $file,
85             version => $builder->dist_version
86             } );
87              
88             $builder->add_to_cleanup( "$build_prefix.pm", "$build_prefix.xs" );
89              
90             # Add the newly created .pm and .xs files to the list of such files?
91             # No, because the current build process looks for all such files and
92             # processes them, and it doesn't create that list until it's actually
93             # processing the .pm and .xs files.
94             }
95             }
96              
97             sub _convert_to_pm {
98             my ( $self, $file, $build_prefix, $prefix, $mod_name ) = @_;
99             my $builder = $self->builder;
100              
101             # see sub run_perl_command (yet undocumented)
102             # PDL::PP's import argument are, in order:
103             # Module name -> for example, PDL::Graphics::PLplot
104             # Package name -> used in package line of the .pm file; for our purposes,
105             # this is identical to Module name.
106             # Prefix -> the extensionless file name, PDL/Graphics/PLplot
107             # .pm and .xs extensions will be added to this when the files are
108             # produced, so this should include a lib/ prefix
109             # Callpack -> an optional argument used for the XS PACKAGE keyword;
110             # if left blank, it will be identical to the module name
111             my $PDL_arg = "-MPDL::PP qw[$mod_name $mod_name $build_prefix]";
112              
113             # Both $self->up_to_date and $self->run_perl_command are undocumented
114             # so they could change in the future:
115             my $up_to_date =
116             $builder->up_to_date( $file, [ "$build_prefix.pm", "$build_prefix.xs" ] );
117              
118             if ( $builder->{FORCE_PDL_PP_BUILD} or not $up_to_date ) {
119             $builder->run_perl_command( [ $PDL_arg, $file ] );
120             }
121             }
122              
123             sub _add_to_provides {
124             my ( $self, $info ) = @_;
125              
126             warn "# provides....$info->{file}\n";
127             $self->builder->meta_merge(
128             'provides',
129             {
130             $info->{mod_name} =>
131             { file => $info->{file}, version => $info->{version} },
132             } );
133             }
134              
135             sub _filename2info {
136             my ( $self, $file ) = @_;
137              
138             # Remove the .pd extension to get the build file prefix, which
139             # says where the .xs and .pm files should be placed when we run
140             # PDL::PP on the .pd file
141             ( my $build_prefix = $file ) =~ s/\.[^.]+$//;
142              
143             # Figure out the file's lib-less prefix, which tells perl where it
144             # will be installed _within_ lib:
145             ( my $prefix = $build_prefix ) =~ s|.*lib/||;
146              
147             # Build the module name (Surely there's a M::B function for this?)
148             ( my $mod_name = $prefix ) =~ s|/|::|g;
149              
150             return ( $build_prefix, $prefix, $mod_name );
151             }
152              
153             sub HOOK_distdir {
154             my ($self) = @_; # $self is MyModuleBuilder (not MBP::PDL)
155              
156             my $files = $self->rscan_dir( 'lib', qr/\.pd$/ );
157             for my $file (@$files) {
158             ( my $build_prefix = $file ) =~ s{\.pd$}{};
159             ( my $prefix = $build_prefix ) =~ s{/?lib/}{};
160             ( my $package = $build_prefix ) =~ s{/}{::}g;
161              
162             # Process .pd into a .pm file with embedded POD
163             # perl -MPDL::PP=PDL::Opt::QP,PDL::Opt::QP,lib/PDL/Opt/QP lib/PDL/Opt/QP.pd
164             my $cmd = sprintf "%s -MPDL::PP=%s,%s,%s %s",
165             $Config{perlpath}, $package, $package, $build_prefix, $file;
166             $self->do_system($cmd) or die "Error running PDL::PP : $@";
167              
168             # Process .pm into .pod using perldoc as an object
169             # && perldoc -u lib/PDL/Opt/QP.pm > lib/PDL/Opt/QP.pod
170             my $poddoc =
171             Pod::Perldoc->new(
172             args => ['-u', '-d', "$build_prefix.pod", "$build_prefix.pm"] );
173             $poddoc->process();
174              
175             $self->add_to_cleanup("$build_prefix.pod");
176             }
177              
178             return 1;
179             }
180              
181             1;
182              
183             __END__