File Coverage

blib/lib/Make.pm
Criterion Covered Total %
statement 441 464 95.0
branch 148 172 86.0
condition 22 35 62.8
subroutine 54 57 94.7
pod 21 41 51.2
total 686 769 89.2


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