1# $Id: Signature.pm,v 1.14 2012/03/04 13:56:35 pfeiffer Exp $ 2package Mpp::Signature; 3 4=head1 NAME 5 6Mpp::Signature -- Interface definition for various signature classes 7 8=head1 USAGE 9 10Derive a package from this package. 11 12=head1 DESCRIPTION 13 14Makepp is quite flexible in the algorithm it uses for deciding whether 15a target is out of date with respect to its dependencies. Most of this 16flexibility is due to various different implementations of the Mpp::Signature 17class. 18 19Each rule can have a different signature class associated with it, 20if necessary. In the makefile, the signature class is specified by 21using the :signature modifier, like this: 22 23 %.o : %.c 24 : signature special_build 25 $(CC) $(CFLAGS) -c $(FIRST_DEPENDENCY) -o $(TARGET) 26 27This causes the signature class C<Mpp::Signature::special_build> to be used for 28this particular rule. 29 30Only one object from each different signature class is actually created; the 31object has no data, and its only purpose is to contain a blessed reference to 32the package that actually implements the functions. Each rule contains a 33reference to the Mpp::Signature object that is appropriate for it. The object is 34found by the name of the Mpp::Signature class. For example, the above rule uses 35the object referenced by C<$Mpp::Signature::special_build::special_build>. (The 36purpose of this naming scheme is to make it impossible to inherit accidentally a 37singleton object, which would cause the wrong Mpp::Signature class to be used.) 38 39 40=head2 signature 41 42 $signature = $sigobj->signature($objinfo); 43 44This function returns a signature for the given object (usually a 45Mpp::File class, but possibly some other kind of object). A signature is 46simply an ASCII string that will change if the object is modified. 47 48$sigobj is the dummy Mpp::Signature class object. 49 50$objinfo is the a reference to B<makepp>'s internal description of that object 51and how it is to be built. See L<makepp_extending> for details. 52 53The default signature function simply calls $objinfo->signature, i.e., it uses 54the default signature function for objects of that class. For files, this is 55the file date concatenated with the file size. 56 57=cut 58 59our $signature = bless []; # Make the singleton object. 60 61sub get { 62 my( $fullname, $mkfile_line ) = @_; 63 my( $name, $sep, $re ) = split /(\.\(?|\()/, $fullname, 2; 64 $name =~ tr/-/_/; 65 $name = 'c_compilation_md5' if $name eq 'C'; # Alias 66 my $sig = eval "use Mpp::Signature::$name; \$Mpp::Signature::${name}::$name" || 67 eval "use Signature::$name; warn qq!$mkfile_line: name Signature::$name is deprecated, rename to Mpp::Signature::$name\n!; \$Signature::${name}::$name"; 68 if( defined $re ) { 69 die "$mkfile_line: Can't add suffixes to inexistent signature $name\n" unless $sig; 70 die "$mkfile_line: Signature $name doesn't support adding suffixes\n" unless UNIVERSAL::can( $sig, 'recognizes_file' ); 71 72 my $class = ref( $sig ) . '::_'; # Make an unlikely-to-exist subclass name. 73 unless( keys %{$class.'::'} ) { 74 my $super = $sig; 75 @{$class.'::ISA'} = ref $sig; 76 *{$class.'::recognizes_file'} = sub { 77 ($_[0][1] ? Mpp::File::absolute_filename $_[1] : $_[1]{NAME}) =~ $_[0][0] or 78 $super->recognizes_file( $_[1] ); 79 }; 80 } 81 82 if( $sep eq '.' ) { 83 my $orig = $re; 84 $re = quotemeta $re; 85 $re =~ s/\\,/|/g and $re = "(?:$re)"; 86 $sig = ${$class."::$orig"} ||= bless [qr/\.$re$/], $class; 87 } else { 88 $re =~ s/\)$// or die "$mkfile_line: No final parenthesis in $fullname\n"; 89 $sep eq '.(' && $re =~ /\|/ and $re = "(?:$re)"; 90 $sig = ${$class."::$re"} ||= 91 bless $sep eq '.(' ? [qr/\.$re$/] : [qr/$re/, $re =~ /\//], $class; 92 } 93 } 94 $sig; 95} 96 97 98sub signature { 99 return $_[1]->signature; 100} 101 102# This is used to determine whether the signature is file content based, as 103# opposed to timestamp based. This is used to determine whether the signature 104# can be used in a build cache key, because we never want to use 105# timestamp-based signatures for that. 106sub is_content_based { 107 # A heuristic that works for all the current Mpp::Signature subclasses, but 108 # not necessarily for all possible subclasses. 109 return $_[0] =~ m|^[+/A-Za-z\d]{22}$|; 110} 111 112=head1 BUGS 113 114A signature must not contain 22 consecutive characters that are alphanumeric 115or '+' or '/', unless the signature is dependent only on file content and 116expected to be alias-free. 117Otherwise, aliases can cause corruption when you use build caches. 118There probably ought to be a more robust way to determine whether a signature 119was generated by a method that is prone to aliasing. 120 121=cut 122 1231; 124