| Panotools-Script documentation | Contained in the Panotools-Script distribution. |
Panotools::Makefile::Rule - Assemble Makefile rules
Simple interface for generating Makefile syntax
Writing Makefiles directly from perl scripts with print and "\t" etc... is prone to error, this library provides a simple perl interface for assembling Makefile rules.
my $rule = new Panotools::Makefile::Rule;
..or additionally specify targets at creation time
my $rule = new Panotools::Makefile::Rule ('all');
A Makefile rule always has one or more 'targets', these are typically filenames, but can be 'phony' non-files.
(phony targets should be listed as perequisites of the special .PHONY target)
$rule->Targets ('output1.txt', 'output2.txt');
..or equivalently:
$rule->Targets ('output1.txt');
$rule->Targets ('output2.txt');
Rules can have zero or more 'prerequisites', again these are typically filenames, but can be 'phony' non-files.
$rule->Prerequisites ('input1.txt', 'input2.txt');
..or equivalently:
$rule->Prerequisites ('input1.txt');
$rule->Prerequisites ('input2.txt');
Rules zero or more 'commands':
$rule->Command ('cp', 'input1.txt', 'output1.txt');
$rule->Command ('cp', 'input2.txt', 'output2.txt');
Assemble all this into string that can be written to a Makefile:
my $string = $rule->Assemble;
| Panotools-Script documentation | Contained in the Panotools-Script distribution. |
package Panotools::Makefile::Rule;
use strict; use warnings; use Panotools::Makefile::Utils qw/quotetarget quoteprerequisite quoteshell/;
sub new { my $class = shift; $class = ref $class || $class; my $self = bless {targets => [@_], prerequisites => [], command => []}, $class; return $self; }
sub Targets { my $self = shift; push @{$self->{targets}}, @_; #warn 'Error: unescapable =;:% in targets: '. join (' ', @_) if grep /[=;:%]/, @_; #warn 'Warning: non-portable target name: '. join (' ', @_) if grep /[?<>:*|"^]/, @_; }
sub Prerequisites { my $self = shift; push @{$self->{prerequisites}}, @_; #warn 'Error: unescapable =;:% in prerequisites: '. join (' ', @_) if grep /[=;:%]/, @_; #warn 'Warning: non-portable target name: '. join (' ', @_) if grep /[?<>:*|"^]/, @_; }
sub Command { my $self = shift; push @{$self->{command}}, [@_]; }
sub Assemble { my $self = shift; my $opts = shift || {}; return '' unless scalar @{$self->{targets}}; my $text; $text .= join ' ', (map { quotetarget ($_)} @{$self->{targets}}); $text .= ' : '; $text .= join ' ', (map { quoteprerequisite ($_)} @{$self->{prerequisites}}); for my $command (@{$self->{command}}) { $text .= "\n\t"; $text .= join ' ', (map { quoteshell ($_)} @{$command}); next unless defined $opts->{warnings}; for my $token (@{$command}) { my @vars = $token =~ /\$\([[:alnum:]_]+\)/g; for my $var (@vars) { warn "underquoted \"$token\"" unless $var =~ /\$\([[:alnum:]_]+_SHELL\)/; } } } $text .= "\n\n"; return $text; } 1;