—# $Id: shared_object.pm,v 1.13 2012/03/25 18:34:48 pfeiffer Exp $
use
strict;
package
Mpp::Signature::shared_object;
our
@ISA
=
'Mpp::Signature::c_compilation_md5'
;
=head1 NAME
Mpp::Signature::shared_object -- a signature class that ignores changes to shared objects
=head1 DESCRIPTION
Normally, if you build a shared object, you do not have to relink anything
that depends on that shared object. This class sets the signature of a shared
object to the same value, regardless of its contents.
For files which are not shared objects, the signature is the same as for C<c_compilation_md5>.
=cut
our
$shared_object
=
bless
\
@ISA
;
# Make the singleton object.
# Things that can be overridden by a derived class:
sub
build_info_key() {
'SHARED_OBJECT'
}
#
# The only subroutine we need to override is the signature method; we use
# exact matching of MD5 signatures.
#
sub
signature {
my
(
$self
,
$finfo
) =
@_
;
# Name the arguments.
if
(
$finfo
->{NAME} =~ /\.s[oal]$/) {
my
$sig
=
&signature_shared_lib
;
defined
(
$sig
) and
return
$sig
;
}
&Mpp::Signature::c_compilation_md5::signature
;
}
#
# This function calculates the MD5 sum of the interface of a shared library.
# Normally, when a shared library changes, one does not need to relink;
# it's only if the externally visible variables change that a relink might
# be necessary. This function computes an MD5 checksum on the externally
# visible symbols.
#
# This will only work with GNU binutils.
#
# This function may trigger rebuilds too often, because not every change that
# affects a shared library's external symbol table requires a rebuild. But
# it's probably impossible to figure out which changes don't require a rebuild
# without actually doing full symbol resolution.
#
# Arguments:
# a) The singleton object.
# b) The file info for the shared library.
#
sub
signature_shared_lib {
my
(
$self
,
$finfo
) =
@_
;
my
$cksum
= Mpp::File::build_info_string(
$finfo
, build_info_key );
return
$cksum
if
$cksum
;
# Don't bother redigesting if the
# file hasn't changed. (The build info is
# discarded if the file date changes, so this
# flushes our cached signature.)
open
my
$nm
,
'nm -P '
. Mpp::File::absolute_filename(
$finfo
) .
' 2>/dev/null |'
or
return
undef
;
local
$_
;
my
@symbols
;
my
$n_symbols
= 0;
while
( <
$nm
> ) {
# Keep reading lines.
if
( s/\s+([A-Z]) .*/$1\01/s ) {
# Uppercase seems to more or less cover the
# non-portable GNU -D opt. Someone who
# understands this might fine tune the types
# that should really go into the sig --
# portably!
++
$n_symbols
if
ord
( $1 ) !=
ord
'U'
;
push
@symbols
,
$_
;
}
}
return
undef
unless
$n_symbols
;
# If that didn't work, then fall back to the
# regular signature.
$cksum
= Digest::MD5::md5_base64(
sort
@symbols
);
Mpp::File::set_build_info_string(
$finfo
, build_info_key,
$cksum
);
$cksum
;
}
1;