File Coverage

blib/lib/Make.pm
Criterion Covered Total %
statement 445 468 95.0
branch 154 178 86.5
condition 25 38 65.7
subroutine 54 57 94.7
pod 21 41 51.2
total 699 782 89.3


line stmt bran cond sub pod time code
1             package Make;
2              
3 1     1   88207 use strict;
  1         12  
  1         29  
4 1     1   5 use warnings;
  1         2  
  1         41  
5              
6             our $VERSION = '2.010';
7              
8 1     1   6 use Carp qw(confess croak);
  1         1  
  1         47  
9 1     1   5 use Config;
  1         2  
  1         46  
10 1     1   6 use Cwd;
  1         2  
  1         59  
11 1     1   6 use File::Spec;
  1         2  
  1         22  
12 1     1   430 use Make::Target ();
  1         2  
  1         21  
13 1     1   392 use Make::Rule ();
  1         3  
  1         23  
14 1     1   798 use File::Temp;
  1         22071  
  1         82  
15 1     1   690 use Text::Balanced qw(extract_bracketed);
  1         10424  
  1         96  
16 1     1   463 use Text::ParseWords qw(parse_line);
  1         1265  
  1         61  
17 1     1   468 use File::Spec::Functions qw(file_name_is_absolute);
  1         868  
  1         67  
18             ## no critic (ValuesAndExpressions::ProhibitConstantPragma)
19 1     1   6 use constant DEBUG => $ENV{MAKE_DEBUG};
  1         2  
  1         7422  
20             ## use critic
21             require Make::Functions;
22              
23             my $DEFAULTS_AST;
24             my %date;
25             my %fs_function_map = (
26             glob => sub { glob $_[0] },
27             fh_open => sub { open my $fh, $_[0], $_[1] or confess "open @_: $!"; $fh },
28             fh_write => sub { my $fh = shift; print {$fh} @_ },
29             file_readable => sub { -r $_[0] },
30             mtime => sub { ( stat $_[0] )[9] },
31             is_abs => sub { goto &file_name_is_absolute },
32             );
33             my @RECMAKE_FINDS = ( \&_find_recmake_cd, );
34              
35             sub _find_recmake_cd {
36 10     10   23 my ($cmd) = @_;
37 10 100       62 return unless $cmd =~ /\bcd\s+([^\s;&]+)\s*(?:;|&&)\s*make\s*(.*)/;
38 5         20 my ( $dir, $makeargs ) = ( $1, $2 );
39 5         867 require Getopt::Long;
40 5         11094 local @ARGV = Text::ParseWords::shellwords($makeargs);
41 5         146 Getopt::Long::GetOptions( "f=s" => \my $makefile );
42 5         706 my ( $vars, $targets ) = parse_args(@ARGV);
43 5         26 return ( $dir, $makefile, $vars, $targets );
44             }
45              
46             ## no critic (Subroutines::RequireArgUnpacking Subroutines::RequireFinalReturn)
47             sub load_modules {
48 11     11 0 37 for (@_) {
49 11         29 my $pkg = $_; # to not mutate inputs
50 11         116 $pkg =~ s#::#/#g;
51             ## no critic (Modules::RequireBarewordIncludes)
52 11 50       35 eval { require "$pkg.pm"; 1 } or die;
  11         127  
  11         46  
53             ## use critic
54             }
55             }
56              
57             sub phony {
58 157     157 0 259 my ( $self, $name ) = @_;
59 157         572 return exists $self->{PHONY}{$name};
60             }
61              
62             sub suffixes {
63 11     11 0 19 my ($self) = @_;
64             ## no critic (Subroutines::ProhibitReturnSort)
65 11         14 return sort keys %{ $self->{'SUFFIXES'} };
  11         97  
66             ## use critic
67             }
68              
69             sub target {
70 241     241 1 3066 my ( $self, $target ) = @_;
71 241 100       501 unless ( exists $self->{Depend}{$target} ) {
72 131         411 my $t = $self->{Depend}{$target} = Make::Target->new( $target, $self );
73 131 100       567 if ( $target =~ /%/ ) {
    100          
74 33         62 $self->{Pattern}{$target} = $t;
75             }
76             elsif ( $target =~ /^\./ ) {
77 61         155 $self->{Dot}{$target} = $t;
78             }
79             }
80 241         678 return $self->{Depend}{$target};
81             }
82              
83             sub has_target {
84 43     43 1 90 my ( $self, $target ) = @_;
85 43 50       88 confess "Trying to has_target undef value" unless defined $target;
86 43         156 return exists $self->{Depend}{$target};
87             }
88              
89             sub targets {
90 15     15 1 1975 my ($self) = @_;
91             ## no critic ( BuiltinFunctions::RequireBlockGrep )
92 15         29 return grep !/%|^\./, keys %{ $self->{Depend} };
  15         607  
93             ## use critic
94             }
95              
96             # Utility routine for patching %.o type 'patterns'
97             my %pattern_cache;
98              
99             sub patmatch {
100 117     117 0 186 my ( $pat, $target ) = @_;
101 117 100       269 return $target if $pat eq '%';
102             ## no critic (BuiltinFunctions::RequireBlockMap)
103             $pattern_cache{$pat} = join '(.*)', map quotemeta, split /%/, $pat
104 85 100       159 if !exists $pattern_cache{$pat};
105             ## use critic
106 85         121 $pat = $pattern_cache{$pat};
107 85 100       1176 if ( $target =~ /^$pat$/ ) {
108 27         128 return $1;
109             }
110 58         187 return;
111             }
112              
113             sub in_dir {
114 114     114 0 258 my ( $fsmap, $dir, $file ) = @_;
115 114 100 66     491 return $file if defined $file and $fsmap->{is_abs}->($file);
116 109 100       732 my @dir = defined($dir) ? split /\//, $dir : ();
117 109         260 my @file = split /\//, $file;
118 109   66     451 while ( @dir and @file and $file[0] eq '..' ) {
      100        
119              
120             # normalise out ../ in $file - no account taken of symlinks
121 2         3 shift @file;
122 2         7 pop @dir;
123             }
124 109         423 join '/', @dir, @file;
125             }
126              
127             sub locate {
128 41     41 0 70 my ( $self, $file ) = @_;
129 41         68 my $fsmap = $self->fsmap;
130 41         60 my $readable = $fsmap->{file_readable};
131 41         65 foreach my $key ( sort keys %{ $self->{Vpath} } ) {
  41         135  
132 21 100       49 next unless defined( my $Pat = patmatch( $key, $file ) );
133 15         25 foreach my $dir ( @{ $self->{Vpath}{$key} } ) {
  15         36  
134 15         53 ( my $maybe_file = $dir ) =~ s/%/$Pat/g;
135 15 100       49 return $maybe_file if $readable->( in_dir $fsmap, $self->{InDir}, $maybe_file );
136             }
137             }
138 38         133 return;
139             }
140              
141             # Convert traditional .c.o rules into GNU-like into %.o : %.c
142             sub dotrules {
143 11     11 0 30 my ($self) = @_;
144 11         29 my @suffix = $self->suffixes;
145 11         37 my $Dot = delete $self->{Dot};
146 11         38 foreach my $f (@suffix) {
147 66         109 foreach my $t ( '', @suffix ) {
148 462         667 delete $self->{Depend}{ $f . $t };
149 462 100       876 next unless my $r = delete $Dot->{ $f . $t };
150 44         56 DEBUG and print STDERR "Pattern %$t : %$f\n";
151 44         108 my $target = $self->target( '%' . $t );
152 44         89 my $thisrule = $r->rules->[-1]; # last-specified
153             die "Failed on pattern rule for '$f$t', no prereqs allowed"
154 44 50       64 if @{ $thisrule->prereqs };
  44         120  
155 44         119 my $rule = Make::Rule->new( '::', [ '%' . $f ], $thisrule->recipe, $thisrule->recipe_raw );
156 44         112 $self->target( '%' . $t )->add_rule($rule);
157             }
158             }
159 11         77 return;
160             }
161              
162             #
163             # Return modified date of name if it exists
164             #
165             sub date {
166 67     67 0 112 my ( $self, $name ) = @_;
167 67         116 my $fsmap = $self->fsmap;
168 67 100       166 unless ( exists $date{$name} ) {
169 48         109 $date{$name} = $self->fsmap->{mtime}->( in_dir $fsmap, $self->{InDir}, $name );
170             }
171 67         425 return $date{$name};
172             }
173              
174             #
175             # See if we can find a %.o : %.c rule for target
176             # .c.o rules are already converted to this form
177             #
178             sub patrule {
179 47     47 1 113 my ( $self, $target, $kind ) = @_;
180 47         63 DEBUG and print STDERR "Trying pattern for $target\n";
181 47         63 foreach my $key ( sort keys %{ $self->{Pattern} } ) {
  47         229  
182 96         189 DEBUG and print STDERR " Pattern $key trying\n";
183 96 100       159 next unless defined( my $Pat = patmatch( $key, $target ) );
184 44         66 DEBUG and print STDERR " Pattern $key matched ($Pat)\n";
185 44         107 my $t = $self->{Pattern}{$key};
186 44         76 foreach my $rule ( @{ $t->rules } ) {
  44         123  
187 44         58 my @dep = @{ $rule->prereqs };
  44         149  
188 44         61 DEBUG and print STDERR " Try rule : @dep\n";
189 44 50       122 next unless @dep;
190 44         59 my @failed;
191 44         72 for my $this_dep (@dep) {
192 44         195 $this_dep =~ s/%/$Pat/g;
193 44 100 66     108 next if $self->date($this_dep) or $self->has_target($this_dep);
194 41         112 my $maybe = $self->locate($this_dep);
195 41 100       94 if ( defined $maybe ) {
196 3         5 $this_dep = $maybe;
197 3         14 next;
198             }
199 38         82 push @failed, $this_dep;
200             }
201 44         52 DEBUG and print STDERR " " . ( @failed ? "Failed: (@failed)" : "Matched (@dep)" ) . "\n";
202 44 100       139 next if @failed;
203 6         96 return Make::Rule->new( $kind, \@dep, $rule->recipe, $rule->recipe_raw );
204             }
205             }
206 41         110 return;
207             }
208              
209             sub evaluate_macro {
210 63     63 0 130 my ( $key, @args ) = @_;
211 63         120 my ( $function_packages, $vars_search_list, $fsmap ) = @args;
212 63         73 my $value;
213 63 100       132 return '' if !length $key;
214 61 100       361 if ( $key =~ /^([\w._]+|\S)(?::(.*))?$/ ) {
    100          
    50          
215 51         129 my ( $var, $subst ) = ( $1, $2 );
216 51         93 foreach my $hash (@$vars_search_list) {
217 70 100       254 last if defined( $value = $hash->{$var} );
218             }
219 51 100       117 $value = '' if !defined $value;
220 51 100       99 if ( defined $subst ) {
221 1         9 my @parts = split /=/, $subst, 2;
222 1 50       7 die "Syntax error: expected form x=y in '$subst'" if @parts != 2;
223 1         11 $value = join ' ', Make::Functions::patsubst( $fsmap, @parts, $value );
224             }
225             }
226             elsif ( $key =~ /([\w._]+)\s+(.*)$/ ) {
227 9         37 my ( $func, $args ) = ( $1, $2 );
228 9         13 my $code;
229 9         28 foreach my $package (@$function_packages) {
230 9 50       90 last if $code = $package->can($func);
231             }
232 9 50       24 die "'$func' not found in (@$function_packages)" if !defined $code;
233             ## no critic (BuiltinFunctions::RequireBlockMap)
234 9         43 $value = join ' ', $code->( $fsmap, map subsvars( $_, @args ), split /\s*,\s*/, $args );
235             ## use critic
236             }
237             elsif ( $key =~ /^\S*\$/ ) {
238              
239             # something clever, expand it
240 1         4 $key = subsvars( $key, @args );
241 1         4 return evaluate_macro( $key, @args );
242             }
243 60         286 return subsvars( $value, @args );
244             }
245              
246             sub subsvars {
247 268     268 1 23057 my ( $remaining, $function_packages, $vars_search_list, $fsmap ) = @_;
248 268 50       634 confess "Trying to expand undef value" unless defined $remaining;
249 268         428 my $ret = '';
250 268         323 my $found;
251 268         304 while (1) {
252 331 100       1068 last unless $remaining =~ s/(.*?)\$//;
253 65         177 $ret .= $1;
254 65         139 my $char = substr $remaining, 0, 1;
255 65 100       293 if ( $char eq '$' ) {
    100          
256 1         2 $ret .= $char; # literal $
257 1         2 substr $remaining, 0, 1, '';
258 1         3 next;
259             }
260             elsif ( $char =~ /[\{\(]/ ) {
261 49         259 ( $found, my $tail ) = extract_bracketed $remaining, '{}()', '';
262 49 100       6855 die "Syntax error in '$remaining'" if !defined $found;
263 47         90 $found = substr $found, 1, -1;
264 47         82 $remaining = $tail;
265             }
266             else {
267 15         35 $found = substr $remaining, 0, 1, '';
268             }
269 62         188 my $value = evaluate_macro( $found, $function_packages, $vars_search_list, $fsmap );
270 62 50       112 if ( !defined $value ) {
271 0         0 warn "Cannot evaluate '$found'\n";
272 0         0 $value = '';
273             }
274 62         114 $ret .= $value;
275             }
276 266         904 return $ret . $remaining;
277             }
278              
279             # Perhaps should also understand "..." and '...' ?
280             # like GNU make will need to understand \ to quote spaces, for deps
281             # also C:\xyz as a non-target (overlap with parse_makefile)
282             sub tokenize {
283 168     168 1 5634 my ( $string, @extrasep ) = @_;
284             ## no critic ( BuiltinFunctions::RequireBlockGrep BuiltinFunctions::RequireBlockMap)
285 168         337 my $pat = join '|', '\s+', map quotemeta, @extrasep;
286 168   100     504 my @toks = grep defined && length, parse_line $pat, 1, $string;
287             ## use critic
288 168         8139 s/\\(\s)/$1/g for @toks;
289 168         424 return \@toks;
290             }
291              
292             sub get_full_line {
293 114     114 0 2539 my ($fh) = @_;
294 114         366 my $final = my $line = <$fh>;
295 114 100       260 return if !defined $line;
296 92         128 my $raw = $line;
297 92         177 $raw =~ s/^\t//;
298 92         433 $final =~ s/\r?\n\z//;
299 92         240 while ( $final =~ /\\$/ ) {
300 4         26 $final =~ s/\s*\\\z//;
301 4         10 $line = <$fh>;
302 4 50       10 last if !defined $line;
303 4         7 my $raw_line = $line;
304 4         13 $raw_line =~ s/^\t//;
305 4         9 $raw .= $raw_line;
306 4         17 $line =~ s/\s*\z//;
307 4         11 $line =~ s/^\s*/ /;
308 4         16 $final .= $line;
309             }
310 92         290 $raw =~ s/\r?\n\z//;
311 92         361 return ( $final, $raw );
312             }
313              
314             sub set_var {
315 48     48 1 510 my ( $self, $name, $value ) = @_;
316 48         196 $self->{Vars}{$name} = $value;
317             }
318              
319             sub vars {
320 178     178 1 259 my ($self) = @_;
321 178         530 $self->{Vars};
322             }
323              
324             sub function_packages {
325 197     197 1 310 my ($self) = @_;
326 197         555 $self->{FunctionPackages};
327             }
328              
329             sub fsmap {
330 343     343 1 492 my ($self) = @_;
331 343         677 $self->{FSFunctionMap};
332             }
333              
334             sub expand {
335 156     156 1 270 my ( $self, $text ) = @_;
336 156         285 return subsvars( $text, $self->function_packages, [ $self->vars, \%ENV ], $self->fsmap );
337             }
338              
339             sub process_ast_bit {
340 99     99 0 321 my ( $self, $type, @args ) = @_;
341 99 50       207 return if $type eq 'comment';
342 99 100       332 if ( $type eq 'include' ) {
    100          
    100          
    50          
343 6         31 my $opt = $args[0];
344 6         26 my ($tokens) = tokenize( $self->expand( $args[1] ) );
345 6         14 foreach my $file (@$tokens) {
346 6 100 50     55 eval {
347 3         13 my $fsmap = $self->fsmap;
348 3         17 $file = in_dir $fsmap, $self->{InDir}, $file;
349 3         11 my $mf = $fsmap->{fh_open}->( '<', $file );
350 3         78 my $ast = parse_makefile($mf);
351 3         16 close($mf);
352 3         50 $self->process_ast_bit(@$_) for @$ast;
353 3         30 1;
354             } or warn $@ if $opt ne '-';
355             }
356             }
357             elsif ( $type eq 'var' ) {
358 15 50       60 $self->set_var( $args[0], defined $args[1] ? $args[1] : "" );
359             }
360             elsif ( $type eq 'vpath' ) {
361 3         14 my ( $pattern, @vpath ) = @args;
362 3         15 $self->{Vpath}{$pattern} = \@vpath;
363             }
364             elsif ( $type eq 'rule' ) {
365 75         203 my ( $targets, $kind, $prereqs, $cmnds, $cmnds_raw ) = @args;
366 75         162 ($prereqs) = tokenize( $self->expand($prereqs) );
367 75         192 ($targets) = tokenize( $self->expand($targets) );
368 75 100 66     449 $self->{Vars}{'.DEFAULT_GOAL'} ||= $targets->[0]
369             if $targets->[0] !~ /%|^\./;
370 75 100 66     398 unless ( @$targets == 1 and $targets->[0] =~ /^\.[A-Z]/ ) {
371 60         135 $self->target($_) for @$prereqs; # so "exist or can be made"
372             }
373 75         339 my $rule = Make::Rule->new( $kind, $prereqs, $cmnds, $cmnds_raw );
374 75         242 $self->target($_)->add_rule($rule) for @$targets;
375             }
376 99         309 return;
377             }
378              
379             #
380             # read makefile (or fragment of one) either as a result
381             # of a command line, or an 'include' in another makefile.
382             #
383             sub parse_makefile {
384 22     22 1 7387 my ($fh) = @_;
385 22         38 my @ast;
386             my $raw;
387 22         72 ( local $_, $raw ) = get_full_line($fh);
388 22         32 while (1) {
389 83 100       168 last unless ( defined $_ );
390 61         142 s/^\s+//;
391 61 100       124 next if !length;
392 58 100       492 if (/^(-?)include\s+(.*)$/) {
    100          
    100          
    100          
    50          
393 6         60 push @ast, [ 'include', $1, $2 ];
394             }
395             elsif (s/^#+\s*//) {
396 1         4 push @ast, [ 'comment', $_ ];
397             }
398             elsif (/^\s*([\w._]+)\s*:?=\s*(.*)$/) {
399 17         87 push @ast, [ 'var', $1, $2 ];
400             }
401             elsif (/^vpath\s+(\S+)\s+([^#]*)/) {
402 4         28 my ( $pattern, $path ) = ( $1, $2 );
403 4         11 my @path = @{ tokenize $path, $Config{path_sep} };
  4         18  
404 4         44 push @ast, [ 'vpath', $pattern, @path ];
405             }
406             elsif (
407             /^
408             \s*
409             ([^:\#]*?)
410             \s*
411             (::?)
412             \s*
413             ((?:[^;\#]*\#.*|.*?))
414             (?:\s*;\s*(.*))?
415             $/sx
416             )
417             {
418 30         156 my ( $target, $kind, $prereqs, $maybe_cmd ) = ( $1, $2, $3, $4 );
419 30 100       76 my @cmnds = defined $maybe_cmd ? ($maybe_cmd) : ();
420 30         53 my @cmnds_raw = @cmnds;
421 30         50 $prereqs =~ s/\s*#.*//;
422 30         125 while ( ( $_, $raw ) = get_full_line($fh) ) {
423 42 100       97 next if /^\s*#/;
424 41 100       128 next if /^\s*$/;
425 33 100       98 last unless /^\t/;
426 19 50       45 next if /^\s*$/;
427 19         46 s/^\s+//;
428 19         43 push @cmnds, $_;
429 19         50 push @cmnds_raw, $raw;
430             }
431 30         109 push @ast, [ 'rule', $target, $kind, $prereqs, \@cmnds, \@cmnds_raw ];
432 30         72 redo;
433             }
434             else {
435 0         0 warn "Ignore '$_'\n";
436             }
437             }
438             continue {
439 31         74 ( $_, $raw ) = get_full_line($fh);
440             }
441 22         62 return \@ast;
442             }
443              
444             sub pseudos {
445 11     11 0 16 my $self = shift;
446 11         23 foreach my $key (qw(SUFFIXES PHONY PRECIOUS PARALLEL)) {
447 44         106 delete $self->{Depend}{ '.' . $key };
448 44         79 my $t = delete $self->{Dot}{ '.' . $key };
449 44 100       88 if ( defined $t ) {
450 15         65 $self->{$key} = {};
451             ## no critic (BuiltinFunctions::RequireBlockMap)
452 15         32 foreach my $dep ( map @{ $_->prereqs }, @{ $t->rules } ) {
  15         38  
  15         40  
453             ## use critic
454 70         278 $self->{$key}{$dep} = 1;
455             }
456             }
457             }
458 11         20 return;
459             }
460              
461             sub find_makefile {
462 12     12 0 43 my ( $self, $file, $dir ) = @_;
463             ## no critic ( BuiltinFunctions::RequireBlockGrep )
464 12         58 my @dirs = grep defined, $self->{InDir}, $dir;
465 12 100       61 $dir = join '/', @dirs if @dirs;
466             ## use critic
467 12         30 my $fsmap = $self->fsmap;
468 12 100       46 return in_dir $fsmap, $dir, $file if defined $file;
469 11         45 my @search = qw(makefile Makefile);
470 11 100       40 unshift @search, 'GNUmakefile' if $self->{GNU};
471             ## no critic (BuiltinFunctions::RequireBlockMap)
472 11         36 @search = map in_dir( $fsmap, $dir, $_ ), @search;
473             ## use critic
474 11         24 for (@search) {
475 20 100       74 return $_ if $fsmap->{file_readable}->($_);
476             }
477 0         0 return;
478             }
479              
480             sub parse {
481 11     11 1 95 my ( $self, $file ) = @_;
482 11         16 my $fh;
483 11 100       30 if ( ref $file eq 'SCALAR' ) {
484 3         58 open my $tfh, "+<", $file;
485 3         12 $fh = $tfh;
486             }
487             else {
488 8         28 $file = $self->find_makefile($file);
489 8         53 $fh = $self->fsmap->{fh_open}->( '<', $file );
490             }
491 11         346 my $ast = parse_makefile($fh);
492 11         46 $self->process_ast_bit(@$_) for @$ast;
493 11         61 undef $fh;
494              
495             # Next bits should really be done 'lazy' on need.
496              
497 11         38 $self->pseudos; # Pull out .SUFFIXES etc.
498 11         51 $self->dotrules; # Convert .c.o into %.o : %.c
499 11         58 return $self;
500             }
501              
502             sub PrintVars {
503 0     0 0 0 my $self = shift;
504 0         0 local $_;
505 0         0 my $vars = $self->vars;
506 0         0 foreach ( sort keys %$vars ) {
507 0         0 print "$_ = ", $vars->{$_}, "\n";
508             }
509 0         0 print "\n";
510 0         0 return;
511             }
512              
513             sub parse_cmdline {
514 13     13 0 5483 my ($line) = @_;
515 13         277 $line =~ s/^([\@\s-]*)//;
516 13         96 my $prefix = $1;
517 13         49 my %parsed = ( line => $line );
518 13 100       148 $parsed{silent} = 1 if $prefix =~ /\@/;
519 13 100       43 $parsed{can_fail} = 1 if $prefix =~ /-/;
520 13         46 return \%parsed;
521             }
522              
523             ## no critic (BuiltinFunctions::RequireBlockMap)
524             my %NAME_QUOTING = map +( $_ => sprintf "%%%02x", ord $_ ), qw(% :);
525             my $NAME_QUOTE_CHARS = join '', '[', ( map quotemeta, sort keys %NAME_QUOTING ), ']';
526              
527             sub name_encode {
528             join ':', map {
529 93         133 my $s = $_;
530 93         261 $s =~ s/($NAME_QUOTE_CHARS)/$NAME_QUOTING{$1}/gs;
531 93         327 $s
532 42     42 1 1812 } @{ $_[0] };
  42         88  
533             }
534              
535             sub name_decode {
536 13     13 1 1062 my ($s) = @_;
537             [
538             map {
539 13         37 my $s = $_;
  27         35  
540 27         46 $s =~ s/%(..)/chr hex $1/ges;
  2         11  
541 27         108 $s
542             } split ':',
543             $_[0]
544             ];
545             }
546             ## use critic
547              
548             ## no critic (Subroutines::ProhibitBuiltinHomonyms)
549             sub exec {
550 8     8 0 35 my ( $self, $line ) = @_;
551 8         46 undef %date;
552 8         45 my $parsed = parse_cmdline($line);
553 8 50       44 print "$parsed->{line}\n" unless $parsed->{silent};
554 8         51225 my $code = system $parsed->{line};
555 8 50 33     223 if ( $code && !$parsed->{can_fail} ) {
556 0         0 $code >>= 8;
557 0         0 die "Code $code from $parsed->{line}";
558             }
559 8         779 return;
560             }
561             ## use critic
562              
563             ## no critic (Subroutines::RequireFinalReturn)
564 5     5 0 11 sub NextPass { shift->{Pass}++ }
565 20     20 0 35 sub pass { shift->{Pass} }
566             ## use critic
567              
568             ## no critic (RequireArgUnpacking)
569             sub parse_args {
570 11     11 0 40 my ( @vars, @targets );
571 11         26 foreach (@_) {
572 6 100       40 if (/^(\w+)=(.*)$/) {
573 1         32 push @vars, [ $1, $2 ];
574             }
575             else {
576 5         23 push @targets, $_;
577             }
578             }
579 11         61 return \@vars, \@targets;
580             }
581             ## use critic
582              
583             sub _rmf_search_rule {
584 10     10   26 my ( $rule, $target_obj, $target, $rule_no, $rmfs ) = @_;
585 10         15 my @found;
586 10         15 my $line = -1;
587 10         32 for my $cmd ( $rule->exp_recipe($target_obj) ) {
588 10         21 $line++;
589 10         14 my @rec_vars;
590 10         24 for my $rf (@$rmfs) {
591 10 100       24 last if @rec_vars = $rf->($cmd);
592             }
593 10 100       25 next unless @rec_vars;
594 5         18 push @found, [ $target, $rule_no, $line, @rec_vars ];
595             }
596 10         36 return @found;
597             }
598              
599             sub find_recursive_makes {
600 1     1 1 3474 my ($self) = @_;
601 1         2 my @found;
602 1         4 my $rmfs = $self->{RecursiveMakeFinders};
603 1         4 for my $target ( sort $self->targets ) {
604 3         8 my $target_obj = $self->target($target);
605 3         5 my $rule_no = 0;
606             ## no critic (BuiltinFunctions::RequireBlockMap)
607 3         7 push @found, map _rmf_search_rule( $_, $target_obj, $target, $rule_no++, $rmfs ), @{ $target_obj->rules };
  3         9  
608             ## use critic
609             }
610 1         5 return @found;
611             }
612              
613             sub as_graph {
614 8     8 1 13534 my ( $self, %options ) = @_;
615 8         27 my ( $no_rules, $recursive_make ) = @options{qw(no_rules recursive_make)};
616 8         1208 require Graph;
617 8 100       36016 my $g = Graph->new( $no_rules ? ( multiedged => 1 ) : () );
618 8         9574 my ( %recipe_cache, %seen );
619 8         16 my $rmfs = $self->{RecursiveMakeFinders};
620 8         24 my $fsmap = $self->fsmap;
621 8         15 my $fr = $fsmap->{file_readable};
622 8         27 my %make_args = (
623             FunctionPackages => $self->function_packages,
624             FSFunctionMap => $fsmap,
625             );
626 8         16 my $InDir = $self->{InDir};
627              
628 8         22 for my $target ( sort $self->targets ) {
629 22 100       885 my $node_name = $no_rules ? $target : name_encode( [ 'target', $target ] );
630 22         76 $g->add_vertex($node_name);
631 22         955 my $rule_no = -1;
632 22         50 my $target_obj = $self->target($target);
633 22         29 for my $rule ( @{ $target_obj->rules } ) {
  22         50  
634 12         16 $rule_no++;
635 12         25 my $recipe = $rule->recipe;
636 12         27 my $recipe_hash = { recipe => $recipe, recipe_raw => $rule->recipe_raw };
637 12         23 my $from_id;
638 12 100       30 if ($no_rules) {
639 6         9 $from_id = $node_name;
640             }
641             else {
642             $from_id = $recipe_cache{$recipe}
643 6   33     37 || ( $recipe_cache{$recipe} = name_encode( [ 'rule', $target, $rule_no ] ) );
644 6         27 $g->set_vertex_attributes( $from_id, $recipe_hash );
645 6         915 $g->add_edge( $node_name, $from_id );
646             }
647 12         950 my $prereqs = $rule->prereqs;
648 12 100 100     57 my @to_nodes = ( $no_rules && !@$prereqs ) ? $node_name : @$prereqs;
649 12         24 for my $dep (@to_nodes) {
650 18 100       1665 my $dep_node = $no_rules ? $dep : name_encode( [ 'target', $dep ] );
651 18         52 $g->add_vertex($dep_node);
652 18 100       806 if ($no_rules) {
653 10         23 my @edge = ( $from_id, $dep_node, $rule_no );
654 10         28 $g->set_edge_attributes_by_id( @edge, $recipe_hash );
655             }
656             else {
657 8         21 $g->add_edge( $from_id, $dep_node );
658             }
659             }
660 12 100       2040 next if !$recursive_make;
661 8         31 for my $t ( _rmf_search_rule( $rule, $target_obj, $target, $rule_no, $rmfs ) ) {
662 4         21 my ( undef, $rule_index, $line, $dir, $makefile, $vars, $targets ) = @$t;
663 4 100       16 my $from = $no_rules ? $target : name_encode( [ 'rule', $target, $rule_index ] );
664 4         23 my $indir_makefile = $self->find_makefile( $makefile, $dir );
665 4 50 33     41 next unless $indir_makefile && $fr->($indir_makefile);
666             ## no critic (BuiltinFunctions::RequireBlockMap)
667 4         26 my $cache_key = join ' ', $indir_makefile, sort map join( '=', @$_ ), @$vars;
668             ## use critic
669 4 50       18 if ( !$seen{$cache_key}++ ) {
670 4         16 my $make2 = ref($self)->new( %make_args, InDir => in_dir( $fsmap, $InDir, $dir ) );
671 4         17 $make2->parse($makefile);
672 4         10 $make2->set_var(@$_) for @$vars;
673 4 50       15 $targets = [ $make2->{Vars}{'.DEFAULT_GOAL'} ] unless @$targets;
674 4         102 my $g2 = $make2->as_graph(%options);
675             $g2->rename_vertices(
676             sub {
677 19 100   19   779 return in_dir( $fsmap, $dir, $_[0] ) if $no_rules;
678 11         13 my ( $type, $name, @other ) = @{ name_decode( $_[0] ) };
  11         31  
679 11         31 name_encode( [ $type, in_dir( $fsmap, $dir, $name ), @other ] );
680             }
681 4         38 );
682 4         173 $g->ingest($g2);
683             }
684 4 100       22718 if ($no_rules) {
685             ## no critic (BuiltinFunctions::RequireBlockMap)
686 2         17 $g->add_edge( $from, $_ ) for map "$dir/$_", @$targets;
687             ## use critic
688             }
689             else {
690             ## no critic (BuiltinFunctions::RequireBlockMap)
691             $g->set_edge_attribute( $from, $_, fromline => $line )
692 2         27 for map name_encode( [ 'target', "$dir/$_" ] ), @$targets;
693             ## use critic
694             }
695             }
696             }
697             }
698 8         837 return $g;
699             }
700              
701             sub apply {
702 5     5 0 46 my ( $self, $method, @args ) = @_;
703 5         23 $self->NextPass;
704 5         23 my ( $vars, $targets ) = parse_args(@args);
705 5         14 $self->set_var(@$_) for @$vars;
706 5 100       16 $targets = [ $self->{Vars}{'.DEFAULT_GOAL'} ] unless @$targets;
707             ## no critic (BuiltinFunctions::RequireBlockGrep BuiltinFunctions::RequireBlockMap)
708 5         25 my @bad_targets = grep !$self->{Depend}{$_}, @$targets;
709 5 50       13 die "Cannot '$method' (@args) - no target @bad_targets" if @bad_targets;
710 5         17 return map $self->target($_)->recurse($method), @$targets;
711             ## use critic
712             }
713              
714             # Spew a shell script to perfom the 'make' e.g. make -n
715             sub Script {
716 0     0 1 0 my ( $self, @args ) = @_;
717 0 0       0 my $com = ( $^O eq 'MSWin32' ) ? 'rem ' : '# ';
718 0         0 my @results;
719 0         0 for ( $self->apply( Make => @args ) ) {
720 0         0 my ( $name, @cmd ) = @$_;
721 0         0 push @results, $com . $name . "\n";
722             ## no critic (BuiltinFunctions::RequireBlockMap)
723 0         0 push @results, map parse_cmdline($_)->{line} . "\n", @cmd;
724             ## use critic
725             }
726 0         0 return @results;
727             }
728              
729             sub Print {
730 0     0 1 0 my ( $self, @args ) = @_;
731 0         0 return $self->apply( Print => @args );
732             }
733              
734             sub Make {
735 5     5 1 1903 my ( $self, @args ) = @_;
736 5         20 for ( $self->apply( Make => @args ) ) {
737 12         112 my ( $name, @cmd ) = @$_;
738 12         61 $self->exec($_) for @cmd;
739             }
740 5         254 return;
741             }
742              
743             sub new {
744 11     11 1 20019 my ( $class, %args ) = @_;
745 11         350 my $self = bless {
746             Pattern => {}, # GNU style %.o : %.c
747             Dot => {}, # Trad style .c.o
748             Vpath => {}, # vpath %.c info
749             Vars => {}, # Variables defined in makefile
750             Depend => {}, # hash of targets
751             Pass => 0, # incremented each sweep
752             Done => {},
753             FunctionPackages => [qw(Make::Functions)],
754             FSFunctionMap => \%fs_function_map,
755             RecursiveMakeFinders => \@RECMAKE_FINDS,
756             %args,
757             }, $class;
758 11         217 $self->set_var( 'CC', $Config{cc} );
759 11         52 $self->set_var( 'AR', $Config{ar} );
760 11         51 $self->set_var( 'CFLAGS', $Config{optimize} );
761 11         22 load_modules( @{ $self->function_packages } );
  11         28  
762 11   66     62 $DEFAULTS_AST ||= parse_makefile( \*DATA );
763 11         47 $self->process_ast_bit(@$_) for @$DEFAULTS_AST;
764 11         46 return $self;
765             }
766              
767             =head1 NAME
768              
769             Make - Pure-Perl implementation of a somewhat GNU-like make.
770              
771             =head1 SYNOPSIS
772              
773             require Make;
774             my $make = Make->new;
775             $make->parse($file)->Make(@ARGV);
776              
777             # to see what it would have done
778             print $make->Script(@ARGV);
779              
780             # to see an expanded version of the makefile
781             $make->Print(@ARGV);
782              
783             my $targ = $make->target($name);
784             my $rule = Make::Rule->new(':', \@prereqs, \@recipe, \@recipe_raw);
785             $targ->add_rule($rule);
786             my @rules = @{ $targ->rules };
787              
788             my @prereqs = @{ $rule->prereqs };
789             my @commands = @{ $rule->recipe };
790              
791             =head1 DESCRIPTION
792              
793             Implements in pure Perl a somewhat GNU-like make, intended to be highly
794             customisable.
795              
796             Via pure-perl-make Make has built perl/Tk from the C generated
797             Makefiles...
798              
799             =head1 MAKEFILE SYNTAX
800              
801             Broadly, there are macros, directives, and rules (including recipes).
802              
803             Macros:
804              
805             varname = value
806              
807             Directives:
808              
809             vpath %.c src/%.c
810             [-]include otherfile.mk # - means no warn on failure to include
811              
812             Please note the C does not have the GNU-make behaviour of
813             discarding the found path if an inferred target must be rebuilt, since
814             this is too non-deterministic / confusing behaviour for this author.
815              
816             Rules:
817              
818             target : prerequisite1 prerequisite2[; immediate recipe]
819             (tab character)follow-on recipe...
820              
821             Recipe lines can start with C<@> (do not echo), C<-> (continue on failure).
822              
823             In addition to traditional
824              
825             .c.o :
826             $(CC) -c ...
827              
828             GNU make's 'pattern' rules e.g.
829              
830             %.o : %.c
831             $(CC) -c ...
832              
833             The former gets internally translated to the latter.
834              
835             =head1 METHODS
836              
837             There are other methods (used by parse) which can be used to add and
838             manipulate targets and their prerequites.
839              
840             =head2 new
841              
842             Class method, takes pairs of arguments in name/value form. Arguments:
843              
844             =head3 Vars
845              
846             A hash-ref of values that sets variables, overridable by the makefile.
847              
848             =head3 Jobs
849              
850             Number of concurrent jobs to run while building. Not implemented.
851              
852             =head3 GNU
853              
854             If true, then F is looked for first.
855              
856             =head3 FunctionPackages
857              
858             Array-ref of package names to search for GNU-make style
859             functions. Defaults to L.
860              
861             =head3 FSFunctionMap
862              
863             Hash-ref of file-system functions by which to access the
864             file-system. Created to help testing, but might be more widely useful.
865             Defaults to code accessing the actual local filesystem. The various
866             functions are expected to return real Perl filehandles. Relevant keys:
867             C, C, C, C, C,
868             C.
869              
870             =head3 InDir
871              
872             Optional. If supplied, will be treated as the current directory instead
873             of the default which is the real current directory.
874              
875             =head3 RecursiveMakeFinders
876              
877             Array-ref of functions to be called in order, searching an expanded
878             recipe line for a recursive make invocation (cf
879             L)
880             that would run a C in a subdirectory. Each returns either an empty
881             list, or
882              
883             ($dir, $makefile, $vars, $targets)
884              
885             The C<$makefile> might be , in which case the default will be
886             searched for. C<$vars> and C<$targets> are array-refs of pairs and
887             strings, respectively. The C<$targets> can be empty.
888              
889             Defaults to a single, somewhat-suitable, function.
890              
891             =head2 parse
892              
893             Parses the given makefile. If none or C, these files will be tried,
894             in order: F if L, F, F.
895              
896             If a scalar-ref, will be makefile text.
897              
898             Returns the make object for chaining.
899              
900             =head2 Make
901              
902             Given a target-name, builds the target(s) specified, or the first 'real'
903             target in the makefile.
904              
905             =head2 Print
906              
907             Print to current C
908             variables expanded.
909              
910             =head2 Script
911              
912             Print to current C
913             that a make would perform i.e. the output of C.
914              
915             =head2 set_var
916              
917             Given a name and value, sets the variable to that.
918              
919             May gain a "type" parameter to distinguish immediately-expanded from
920             recursively-expanded (the default).
921              
922             =head2 expand
923              
924             Uses L to return its only arg with any macros expanded.
925              
926             =head2 target
927              
928             Find or create L for given target-name.
929              
930             =head2 has_target
931              
932             Returns boolean on whether the given target-name is known to this object.
933              
934             =head2 targets
935              
936             List all "real" (non-dot, non-inference) target-names known to this object
937             at the time called, unsorted. Note this might change when C is
938             called, as targets will be added as part of the dependency-search process.
939              
940             =head2 patrule
941              
942             Search registered pattern-rules for one matching given
943             target-name. Returns a L for that of the given kind, or false.
944              
945             Uses GNU make's "exists or can be made" algorithm on each rule's proposed
946             requisite to see if that rule matches.
947              
948             =head2 find_recursive_makes
949              
950             my @found = $make->find_recursive_makes;
951              
952             Iterate over all the rules, expanding them for their targets, and find
953             any recursive make invocations using the L.
954              
955             Returns a list of array-refs with:
956              
957             [ $from_target, $rule_index, $line_index, $dir, $makefile, $vars, $targets ]
958              
959             =head1 ATTRIBUTES
960              
961             These are read-only.
962              
963             =head2 vars
964              
965             Returns a hash-ref of the current set of variables.
966              
967             =head2 function_packages
968              
969             Returns an array-ref of the packages to search for macro functions.
970              
971             =head2 fsmap
972              
973             Returns a hash-ref of the L.
974              
975             =head2 as_graph
976              
977             Returns a L object representing the makefile.
978             Takes options as a hash:
979              
980             =head3 recursive_make
981              
982             If true (default false), uses L to find recursive
983             make invocations in the current makefile, parses those, then includes
984             them, with an edge created to the relevant target.
985              
986             =head3 no_rules
987              
988             If true, the graph will only have target vertices, but will be
989             "multiedged". The edges will have an ID of the zero-based index of the
990             rule on the predecessor target, and will have attributes C
991             and C. Rules with no prerequisites will be indicated with
992             an edge back to the same target.
993              
994             If false (the default), the vertices are named either C
995             (representing Ls) or C (representing
996             Ls). The names encoded with L. Rules are named
997             according to the first (alphabetically) target they are attached to.
998              
999             The rule vertices have attributes with the same values as the
1000             L attributes:
1001              
1002             =over
1003              
1004             =item recipe
1005              
1006             =item recipe_raw
1007              
1008             =back
1009              
1010             =head1 FUNCTIONS
1011              
1012             =head2 name_encode
1013              
1014             =head2 name_decode
1015              
1016             my $encoded = Make::name_encode([ 'target', 'all' ]);
1017             my $tuple = Make::name_decode($encoded); # [ 'target', 'all' ]
1018              
1019             Uses C<%>-encoding and -decoding to allow C<%> and C<:> characters in
1020             components without problems.
1021              
1022             =head2 parse_makefile
1023              
1024             Given a file-handle, returns array-ref of Abstract Syntax-Tree (AST)
1025             fragments, representing the contents of that file. Each is an array-ref
1026             whose first element is the node-type (C, C, C,
1027             C, C), followed by relevant data.
1028              
1029             =head2 tokenize
1030              
1031             Given a line, returns array-ref of the space-separated "tokens". Also
1032             splits on any further args.
1033              
1034             =head2 subsvars
1035              
1036             my $expanded = Make::subsvars(
1037             'hi $(shell echo there)',
1038             \@function_packages,
1039             [ \%vars ],
1040             $fsmap,
1041             );
1042             # "hi there"
1043              
1044             Given a piece of text, will substitute any macros in it, either a
1045             single-character macro, or surrounded by either C<{}> or C<()>. These
1046             can be nested. Uses the array-ref as a list of hashes to search
1047             for values.
1048              
1049             If the macro is of form C<$(varname:a=b)>, then this will be a GNU
1050             (and others) make-style "substitution reference". First "varname" will
1051             be expanded. Then all occurrences of "a" at the end of words within
1052             the expanded text will be replaced with "b". This is intended for file
1053             suffixes.
1054              
1055             For GNU-make style functions, see L.
1056              
1057             =head1 DEBUGGING
1058              
1059             To see debugging messages on C, set environment variable
1060             C to a true value;
1061              
1062             =head1 BUGS
1063              
1064             More attention needs to be given to using the package to I makefiles.
1065              
1066             The rules for matching 'dot rules' e.g. .c.o and/or pattern rules e.g. %.o : %.c
1067             are suspect. For example give a choice of .xs.o vs .xs.c + .c.o behaviour
1068             seems a little odd.
1069              
1070             =head1 SEE ALSO
1071              
1072             L
1073              
1074             L POSIX standard for make
1075              
1076             L GNU make docs
1077              
1078             =head1 AUTHOR
1079              
1080             Nick Ing-Simmons
1081              
1082             =head1 COPYRIGHT AND LICENSE
1083              
1084             Copyright (c) 1996-1999 Nick Ing-Simmons.
1085              
1086             This program is free software; you can redistribute it and/or
1087             modify it under the same terms as Perl itself.
1088              
1089             =cut
1090              
1091             1;
1092             #
1093             # Remainder of file is in makefile syntax and constitutes
1094             # the built in rules
1095             #
1096             __DATA__