File Coverage

builder/Acme/Parataxis/Builder.pm
Criterion Covered Total %
statement 50 50 100.0
branch 2 4 50.0
condition 1 3 33.3
subroutine 15 15 100.0
pod 0 1 0.0
total 68 73 93.1


line stmt bran cond sub pod time code
1             # Based on Module::Build::Tiny which is copyright (c) 2011 by Leon Timmermans, David Golden.
2             # Module::Build::Tiny is free software; you can redistribute it and/or modify it under
3             # the same terms as the Perl 5 programming language system itself.
4 1     1   14 use v5.40;
  1         5  
5 1     1   6 use feature 'class';
  1         2  
  1         254  
6 1     1   7 no warnings 'experimental::class';
  1         2  
  1         229  
7             class #
8             Acme::Parataxis::Builder {
9 1     1   739 use CPAN::Meta;
  1         35964  
  1         36  
10 1     1   602 use ExtUtils::Install qw[pm_to_blib install];
  1         17715  
  1         102  
11 1     1   640 use ExtUtils::InstallPaths 0.002;
  1         5373  
  1         52  
12 1     1   9 use File::Basename qw[basename dirname];
  1         2  
  1         73  
13 1     1   5 use File::Find ();
  1         2  
  1         21  
14 1     1   5 use File::Path qw[mkpath rmtree];
  1         2  
  1         58  
15 1     1   564 use File::Spec::Functions qw[catfile catdir rel2abs abs2rel splitdir curdir];
  1         1057  
  1         109  
16 1     1   921 use JSON::PP 2 qw[encode_json decode_json];
  1         20412  
  1         120  
17              
18             # Not in CORE
19 1     1   1147 use Path::Tiny qw[path];
  1         19198  
  1         118  
20 1     1   618 use ExtUtils::Helpers 0.028 qw[make_executable split_like_shell detildefy];
  1         5452  
  1         3629  
21             #
22             field $action : param //= 'build';
23             field $meta : reader = CPAN::Meta->load_file('META.json');
24              
25             # Params to Build script
26             field $install_base : param //= '';
27             field $installdirs : param //= '';
28             field $uninst : param //= 0; # Make more sense to have a ./Build uninstall command but...
29             field $install_paths : param //= ExtUtils::InstallPaths->new( dist_name => $meta->name );
30             field $verbose : param //= 0;
31             field $dry_run : param //= 0;
32             field $pureperl : param //= 0;
33             field $jobs : param //= 1;
34             field $destdir : param //= '';
35             field $prefix : param //= '';
36             #
37             ADJUST {
38             -e 'META.json' or die "No META information provided\n";
39             }
40             method write_file( $filename, $content ) { path($filename)->spew_raw($content) or die "Could not open $filename: $!\n" }
41             method read_file ($filename) { path($filename)->slurp_utf8 or die "Could not open $filename: $!\n" }
42              
43             method step_build() {
44             for my $pl_file ( find( qr/\.PL$/, 'lib' ) ) {
45             ( my $pm = $pl_file ) =~ s/\.PL$//;
46             system $^X, $pl_file->stringify, $pm and die "$pl_file returned $?\n";
47             }
48              
49             # C Extension Compilation - removed conditional block
50             say 'Building libparataxis...';
51             require Affix::Build; # This module is used for C compilation
52             require Config;
53             require File::Spec;
54             my $arch_dir = catdir(qw[blib arch auto Acme Parataxis]);
55             mkpath( $arch_dir, $verbose );
56             my $build = Affix::Build->new(
57             name => 'parataxis',
58             flags => {
59             cflags => join( ' ',
60             ( $Config::Config{ccflags}, '-std=c11', map { '-I' . $_ } ( File::Spec->catdir( $Config::Config{archlibexp}, 'CORE' ), 'src' ) )
61             ),
62             ldflags => ( $^O eq 'MSWin32' ) ?
63             ( '-L' .
64             File::Spec->catdir( $Config::Config{archlibexp}, 'CORE' ) . ' -l' .
65             ( $Config::Config{libperl} =~ s/^lib//r =~ s/\.a$//r =~ s/\.lib$//r ) .
66             ' -lws2_32' ) : ( $^O eq 'darwin' ? '-undefined dynamic_lookup' : '' )
67             },
68             build_dir => $arch_dir,
69             clean => 0
70             );
71              
72             # Add the C source file to be compiled. It's expected to be in 'lib/Acme/'
73             $build->add('lib/Acme/Parataxis.c');
74             say "Compiling and linking...";
75             $build->compile_and_link();
76             say "Build complete.";
77             my %modules = map { $_ => catfile( 'blib', $_ ) } find( qr/\.pm$/, 'lib' );
78             my %docs = map { $_ => catfile( 'blib', $_ ) } find( qr/\.pod$/, 'lib' );
79             my %scripts = map { $_ => catfile( 'blib', $_ ) } find( qr/(?:)/, 'script' );
80             my %sdocs = map { $_ => delete $scripts{$_} } grep {/.pod$/} keys %scripts;
81             pm_to_blib( { %modules, %docs, %sdocs }, catdir(qw[blib lib auto]) );
82             #
83             mkpath( catdir(qw[blib script]), $verbose );
84             for my $src ( keys %scripts ) {
85             my $dest = $scripts{$src};
86             my $content = path($src)->slurp_raw;
87             $content =~ s{^#!.*perl.*}{#!$^X};
88             path($dest)->spew_raw($content);
89             make_executable($dest);
90             }
91             #
92             my %dist_shared = map { $_ => catfile( qw[blib lib auto share dist], $meta->name, abs2rel( $_, 'share' ) ) } find( qr/(?:)/, 'share' );
93             my %module_shared = map { $_ => catfile( qw[blib lib auto share module], abs2rel( $_, 'module-share' ) ) } find( qr/(?:)/, 'module-share' );
94             pm_to_blib( { %dist_shared, %module_shared }, catdir(qw[blib lib auto]) );
95             mkpath( catdir(qw[blib arch]), $verbose );
96             0;
97             }
98             method step_clean() { rmtree( $_, $verbose ) for qw[blib temp]; 0 }
99              
100             method step_install() {
101             $self->step_build() unless -d 'blib';
102             install(
103             [ from_to => $install_paths->install_map,
104             verbose => $verbose,
105             dry_run => $dry_run,
106             uninstall_shadows => $uninst,
107             skip => undef,
108             always_copy => 1
109             ]
110             );
111             0;
112             }
113             method step_realclean () { rmtree( $_, $verbose ) for qw[blib temp Build _build_params MYMETA.yml MYMETA.json]; 0 }
114              
115             method step_test() {
116             $self->step_build() unless -d 'blib';
117             require TAP::Harness::Env;
118             require Config;
119             my @libs = map { rel2abs( catdir( 'blib', $_ ) ) } qw[arch lib];
120             local $ENV{PERL5LIB} = join( $Config::Config{path_sep}, @libs, ( defined $ENV{PERL5LIB} ? $ENV{PERL5LIB} : () ) );
121             my %test_args = ( ( verbosity => $verbose ), ( jobs => $jobs ), ( color => -t STDOUT ), lib => [@libs], );
122             TAP::Harness::Env->create( \%test_args )->runtests( sort map { $_->stringify } find( qr/\.t$/, 't' ) )->has_errors;
123             }
124              
125             method get_arguments (@sources) {
126             $_ = detildefy($_) for grep {defined} $install_base, $destdir, $prefix, values %{$install_paths};
127             $install_paths = ExtUtils::InstallPaths->new( dist_name => $meta->name );
128             return;
129             }
130              
131             method Build(@args) {
132             my $method = $self->can( 'step_' . $action );
133             $method // die "No such action '$action'\n";
134             exit $method->($self);
135             }
136              
137             method Build_PL() {
138             say sprintf 'Creating new Build script for %s %s', $meta->name, $meta->version;
139             $self->write_file( 'Build', sprintf <<'', $^X, __PACKAGE__, __PACKAGE__ );
140             #!%s
141             use lib 'builder';
142             use %s;
143             use Getopt::Long qw[GetOptionsFromArray];
144             my %%opts = ( @ARGV && $ARGV[0] =~ /\A\w+\z/ ? ( action => shift @ARGV ) : () );
145             GetOptionsFromArray \@ARGV, \%%opts, qw[install_base=s install_path=s%% installdirs=s destdir=s prefix=s config=s%% uninst:1 verbose:1 dry_run:1 jobs=i];
146             %s->new(%%opts)->Build();
147              
148             make_executable('Build');
149             my @env = defined $ENV{PERL_MB_OPT} ? split_like_shell( $ENV{PERL_MB_OPT} ) : ();
150             $self->write_file( '_build_params', encode_json( [ \@env, \@ARGV ] ) );
151             if ( my $dynamic = $meta->custom('x_dynamic_prereqs') ) {
152             my %meta = ( %{ $meta->as_struct }, dynamic_config => 0 );
153             $self->get_arguments( \@env, \@ARGV );
154             require CPAN::Requirements::Dynamic;
155             my $dynamic_parser = CPAN::Requirements::Dynamic->new();
156             my $prereq = $dynamic_parser->evaluate($dynamic);
157             $meta{prereqs} = $meta->effective_prereqs->with_merged_prereqs($prereq)->as_string_hash;
158             $meta = CPAN::Meta->new( \%meta );
159             }
160             $meta->save(@$_) for ['MYMETA.json'];
161             }
162              
163 1     1 0 38068 sub find ( $pattern, $base ) {
  1         3  
  1         3  
  1         3  
164 1 50       11 $base = path($base) unless builtin::blessed $base;
165 15         21 my $blah = $base->visit(
166 15     15   1896 sub ( $path, $state ) {
  15         24  
  15         19  
167 15 50 33     41 $state->{$path} = $path if -f $path && $path =~ $pattern;
168              
169             #~ return \0 if keys %$state == 10;
170             },
171 1         77 { recurse => 1 }
172             );
173 1         135 values %$blah;
174             }
175             };
176             1;