File Coverage

blib/lib/Make/Rule.pm
Criterion Covered Total %
statement 51 65 78.4
branch 8 20 40.0
condition 6 9 66.6
subroutine 14 15 93.3
pod 0 10 0.0
total 79 119 66.3


line stmt bran cond sub pod time code
1             package Make::Rule;
2              
3 1     1   7 use strict;
  1         1  
  1         30  
4 1     1   5 use warnings;
  1         3  
  1         22  
5 1     1   4 use Carp;
  1         2  
  1         71  
6 1     1   386 use Make::Rule::Vars;
  1         2  
  1         35  
7             ## no critic (ValuesAndExpressions::ProhibitConstantPragma)
8 1     1   6 use constant DEBUG => $ENV{MAKE_DEBUG};
  1         2  
  1         780  
9             ## use critic
10              
11             our $VERSION = '2.009';
12              
13             sub prereqs {
14 158     158 0 489 return shift->{PREREQS};
15             }
16              
17             sub recipe {
18 178     178 0 645 return shift->{RECIPE};
19             }
20              
21             sub recipe_raw {
22 59     59 0 868 return shift->{RECIPE_RAW};
23             }
24              
25             # The key make test - is target out-of-date as far as this rule is concerned
26             # In scalar context - boolean value of 'do we need to apply the rule'
27             # In list context the things we are out-of-date with e.g. magic $? variable
28             sub out_of_date {
29 12     12 0 22 my ( $self, $target ) = @_;
30 12         33 my $info = $target->Info;
31 12         21 my @dep = ();
32 12         53 my $tdate = $target->date;
33 12         19 my $count = 0;
34 12         15 foreach my $dep ( @{ $self->prereqs } ) {
  12         30  
35 11         39 my $date = $info->date($dep);
36 11         17 $count++;
37 11 50 100     77 if ( !defined($date) || !defined($tdate) || $date > $tdate ) {
      66        
38 11         16 DEBUG and print STDERR $target->Name . " outdated by " . $dep . "\n";
39 11 50       44 return 1 unless wantarray;
40 0         0 push( @dep, $dep );
41             }
42             }
43 1 50       6 return @dep if wantarray;
44              
45             # Note special case of no prerequisites means it is always out-of-date!
46 1         5 return !$count;
47             }
48              
49             sub auto_vars {
50 23     23 0 563 my ( $self, $target ) = @_;
51 23         30 my %var;
52 23         140 tie %var, 'Make::Rule::Vars', $self, $target;
53 23         123 return \%var;
54             }
55              
56             # - May need vpath processing
57             sub exp_recipe {
58 22     22 0 33 my ( $self, $target ) = @_;
59 22         48 my $info = $target->Info;
60 22         96 my @subs_args = ( $info->function_packages, [ $self->auto_vars($target), $info->vars, \%ENV ] );
61             ## no critic (BuiltinFunctions::RequireBlockMap)
62 22         80 my @cmd = map Make::subsvars( $_, @subs_args ), @{ $self->recipe };
  22         40  
63             ## use critic
64 22 50       136 return (wantarray) ? @cmd : \@cmd;
65             }
66              
67             sub new {
68 125     125 0 278 my ( $class, $kind, $prereqs, $recipe, $recipe_raw ) = @_;
69 125 50       316 confess "prereqs $prereqs are not an array reference"
70             if 'ARRAY' ne ref $prereqs;
71 125 50       249 confess "recipe $recipe not an array reference"
72             if 'ARRAY' ne ref $recipe;
73 125 50 33     444 confess "recipe but no recipe_raw"
74             if $recipe and not $recipe_raw;
75 125         758 return bless {
76             KIND => $kind, # : or ::
77             PREREQS => $prereqs, # right hand args
78             RECIPE => $recipe, # recipe
79             RECIPE_RAW => $recipe_raw,
80             }, $class;
81             }
82              
83             sub kind {
84 125     125 0 339 return shift->{KIND};
85             }
86              
87             sub Make {
88 12     12 0 28 my ( $self, $target ) = @_;
89 12 50       29 return unless ( $self->out_of_date($target) );
90 12         34 return [ $target->Name, $self->exp_recipe($target) ];
91             }
92              
93             #
94             # Print rule out in makefile syntax
95             # - currently has variables expanded as debugging aid.
96             # - will eventually become make -p
97             # - may be useful for writing makefiles from MakeMaker too...
98             #
99             sub Print {
100 0     0 0   my ( $self, $target ) = @_;
101 0           my $file;
102 0           print $target->Name, ' ', $self->{KIND}, ' ';
103 0           foreach my $file ( $self->prereqs ) {
104 0           print " \\\n $file";
105             }
106 0           print "\n";
107 0           my @cmd = $self->exp_recipe($target);
108 0 0         if (@cmd) {
109 0           foreach my $file (@cmd) {
110 0           print "\t", $file, "\n";
111             }
112             }
113             else {
114 0 0         print STDERR "No recipe for ", $target->Name, "\n" unless ( $self->target->phony );
115             }
116 0           print "\n";
117 0           return;
118             }
119              
120             =head1 NAME
121              
122             Make::Rule - a rule with prerequisites and recipe
123              
124             =head1 SYNOPSIS
125              
126             my $rule = Make::Rule->new( $kind, \@prereqs, \@recipe, \@recipe_raw );
127             my @name_commands = $rule->Make($target);
128             my @deps = @{ $rule->prereqs };
129             my @cmds = @{ $rule->recipe };
130             my @expanded_cmds = @{ $rule->exp_recipe($target) }; # vars expanded
131             my @raw_cmds = @{ $rule->recipe_raw }; # with any \ still on line-ends
132             my @ood = $rule->out_of_date($target);
133             my $vars = $rule->auto_vars($target); # tied hash-ref
134              
135             =head1 DESCRIPTION
136              
137             Represents a rule. An instance exists for each ':' or '::' rule in
138             the makefile. The recipe and prerequisites are kept here.
139              
140             =cut
141              
142             1;