2014-08-13 12:08:26 +01:00
|
|
|
#!/usr/bin/perl -w
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
dh_makeclilibs - automatically create clilibs file
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use Debian::Debhelper::Dh_Lib;
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
B<dh_makeclilibs> [S<I<debhelper options>>] [B<-r>] [B<-V>I<[dependancies]>] [B<-m>I<minversion>] [B<-l>I<nextincompatible>] [B<-X>I<item>]
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
dh_makeclilibs is a debhelper program that automatically scans for
|
|
|
|
versioned CIL (.NET) assemblies, and generates a clilibs file for the
|
|
|
|
libraries it finds.
|
|
|
|
|
|
|
|
By default, dh_makeclilibs scans the .dll files in the package
|
|
|
|
directories and writes the discovered compatibility data (major/minor,
|
|
|
|
build, token) to "clilibs" files in the appropriate packages.
|
|
|
|
|
|
|
|
However, if a file like debian/package.clilibs is found, this one will
|
|
|
|
be installed and no scanning is performed.
|
|
|
|
|
|
|
|
=head1 OPTIONS
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item B<-V>, B<-V>I<dependancies>
|
|
|
|
|
|
|
|
=item B<--version-info>, B<--version-info=>I<dependancies>
|
|
|
|
|
|
|
|
By default, the clilibs file generated by this program does not make packages
|
|
|
|
depend on any particular version of the package containing the assembly.
|
|
|
|
It may be necessary for you to add some version dependency
|
|
|
|
information to the clilibs file. If -V is specified with no dependency
|
|
|
|
information, the current version of the package is plugged into a
|
|
|
|
dependency that looks like "packagename (>= packageversion)". If -V is
|
|
|
|
specified with parameters, the parameters can be used to specify the exact
|
|
|
|
dependency information needed (be sure to include the package name).
|
|
|
|
|
|
|
|
Beware of using -V without any parameters; this is a conservative setting
|
|
|
|
that always ensures that other packages' shared library dependencies are at
|
|
|
|
least as tight as they need to be, so that if the maintainer screws up then
|
|
|
|
they won't break. The flip side is that packages might end up with
|
|
|
|
dependencies that are too tight and so find it harder to be upgraded.
|
|
|
|
|
|
|
|
=item B<-m>I<minversion>
|
|
|
|
|
|
|
|
Like -V, but specifies only the version string, the package name comes
|
|
|
|
from the package that is actually processed. This option is more
|
|
|
|
flexible if you try to set a range of valid versions for different
|
|
|
|
assembly packages coming from one source package.
|
|
|
|
|
|
|
|
=item B<-l>I<nextincompatible>
|
|
|
|
|
|
|
|
Specifies the (expected) version of this package when the compatibility
|
|
|
|
to the current assemblies will break.
|
|
|
|
|
|
|
|
=item B<-r>
|
|
|
|
|
|
|
|
An experimental option to automaticaly guess the next incompatible
|
|
|
|
upstream version and insert them (like working with -l and -m options,
|
|
|
|
see above). Do not expect the guessed values to be always correct -
|
|
|
|
normally, the usualy assumed version string has the form
|
|
|
|
generation.major.minor where versions with changes in "minor" are
|
|
|
|
compatible and "major" versions break with compatibility.
|
|
|
|
|
|
|
|
=item B<-X>I<item>, B<--exclude=>I<item>
|
|
|
|
|
|
|
|
Exclude files that contain "item" anywhere in their filename or directory
|
|
|
|
from being treated as shared libraries.
|
|
|
|
|
|
|
|
=item B<--internal-mono>
|
|
|
|
|
|
|
|
Uses the Mono runtime in . (used for bootstrapping Mono packages)
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 EXAMPLES
|
|
|
|
|
|
|
|
dh_makeclilibs
|
|
|
|
|
|
|
|
Assuming this is a package named libfoobar0.9x-cil, generates a clilibs file that
|
|
|
|
looks something like:
|
|
|
|
libfoobar 1.0.2345.0_23a12f34 libfoobar0.9x-cil
|
|
|
|
|
|
|
|
dh_makeclilibs -V
|
|
|
|
|
|
|
|
Assuming the current version of the package is 0.93-3, generates a clilibs
|
|
|
|
file that looks something like:
|
|
|
|
libfoobar 1.0.2345.0_23a12f34 libfoobar0.9x-cil (>= 0.93-3)
|
|
|
|
|
|
|
|
dh_makeclilibs -V 'libfoobar0.9x-cil (>= 0.92)'
|
|
|
|
|
|
|
|
Generates a clilibs file that looks something like:
|
|
|
|
libfoobar 1.0.2345.0_23a12f34 libfoobar0.9x-cil (>= 0.92)
|
|
|
|
|
|
|
|
Assuming that your package creates libfoobar-cil and liblafasel-cil,
|
|
|
|
which are compatible to 0.92 versions but the upstream is going to break
|
|
|
|
compatibility in the next version, 0.94:
|
|
|
|
|
|
|
|
dh_makeclilibs -m 0.92 -l 0.94
|
|
|
|
|
|
|
|
Generates clilibs file that looks something like:
|
|
|
|
|
|
|
|
libfoobar 1.0.2345.0_23a12f34 libfoobar-cil (>= 0.92), libfoobar-cil (<< 0.94)
|
|
|
|
|
|
|
|
and
|
|
|
|
|
|
|
|
liblafasel 1.0.2345.0_23a12f34 liblafasel-cil (>= 0.92), liblafasel-cil (<< 0.94)
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
|
|
|
# gar, debhelper 7.1 defines -V for all scripts already :(
|
|
|
|
init(options => {
|
|
|
|
# "V", => \$dh{V_FLAG},
|
|
|
|
"r" => \$dh{R_FLAG},
|
|
|
|
"m=s" => \$dh{M_PARAMS},
|
|
|
|
"l=s" => \$dh{L_PARAMS},
|
|
|
|
"internal-mono" => \$dh{INTERNAL_MONO_FLAG},
|
|
|
|
});
|
|
|
|
|
|
|
|
my $clr;
|
|
|
|
my $cli = '/usr/bin/cli';
|
|
|
|
my $cli_version = `$cli --version 2>&1`;
|
|
|
|
my $cli_parser;
|
|
|
|
my $sn = 'sn';
|
|
|
|
|
|
|
|
if (defined($dh{INTERNAL_MONO_FLAG}) ||
|
|
|
|
(defined($ARGV[0]) && $ARGV[0] eq "internal-mono")) {
|
|
|
|
$clr = "mono";
|
2015-04-07 10:56:59 +01:00
|
|
|
my $mono_path = "LD_LIBRARY_PATH=debian/tmp/usr/lib MONO_PATH=debian/tmp/usr/lib/mono/4.5 MONO_CFG_DIR=debian/tmp/etc";
|
2017-03-15 11:26:37 +00:00
|
|
|
$cli_parser = "$mono_path debian/tmp/usr/bin/mono debian/tmp/usr/lib/mono/4.5/ikdasm.exe";
|
2014-08-13 12:08:26 +01:00
|
|
|
$sn = "$mono_path debian/tmp/usr/bin/mono debian/tmp/usr/lib/mono/4.5/sn.exe";
|
2017-03-13 17:19:47 +00:00
|
|
|
verbose_print("Will use build Mono (debian/tmp/usr/bin/ikdasm) for CIL parsing.");
|
|
|
|
} elsif (-x "/usr/bin/ikdasm") {
|
2014-08-13 12:08:26 +01:00
|
|
|
$clr = "mono";
|
2017-03-13 17:19:47 +00:00
|
|
|
$cli_parser = "/usr/bin/ikdasm";
|
|
|
|
verbose_print("Will use Mono (/usr/bin/ikdasm) for CIL parsing.");
|
2014-08-13 12:08:26 +01:00
|
|
|
} elsif (-x "/usr/bin/ildasm") {
|
|
|
|
$clr = "pnet";
|
|
|
|
$cli_parser = "/usr/share/cli-common/ildasm-monodis";
|
|
|
|
verbose_print("Will use Portable.NET (/usr/bin/ildasm) for CIL parsing.");
|
|
|
|
} else {
|
|
|
|
error("Could not find a CIL disassembler, aborting.");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
local $/="";
|
|
|
|
open(FILE, 'debian/control');
|
|
|
|
my $srcblock = <FILE>;
|
|
|
|
close(FILE);
|
|
|
|
if ($srcblock =~ m/Build-Depends(?:\-Indep)?\:(?:.*\n\s+)*.*cli\-common\-dev\s*\(>=\s*([^\)]+)\)/ &&
|
|
|
|
system("dpkg", "--compare-versions", $1, ">=", "0.8~") != 0) {
|
|
|
|
warning("Warning! No Build-Depends(-Indep) on cli-common-dev (>= 0.8~)!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
my $fh;
|
|
|
|
my %shlibdata;
|
|
|
|
|
|
|
|
foreach my $package (@{$dh{DOPACKAGES}}) {
|
|
|
|
next if is_udeb($package);
|
|
|
|
|
|
|
|
my $tmp = tmpdir($package);
|
|
|
|
|
|
|
|
my %seen;
|
|
|
|
my $need_ldconfig = 0;
|
|
|
|
|
|
|
|
doit("rm", "-f", "$tmp/DEBIAN/clilibs");
|
|
|
|
if (-e "debian/$package.clilibs" ) {
|
|
|
|
complex_doit("cat debian/$package.clilibs > $tmp/DEBIAN/clilibs");
|
|
|
|
} else {
|
|
|
|
# So, we look for files or links to existing files with names that
|
|
|
|
# match "*.so*". Matching *.so.* is not good enough because of
|
|
|
|
# broken crap like db3. And we only look at real files not
|
|
|
|
# symlinks, so we don't accidentually add clilibs data to -dev
|
|
|
|
# packages. This may have a few false positives, which is ok,
|
|
|
|
# because only if we can get a library name and a major number from
|
|
|
|
# objdump is anything actually added.
|
|
|
|
my $exclude = '';
|
|
|
|
if (defined($dh{EXCLUDE_FIND}) && $dh{EXCLUDE_FIND} ne '') {
|
|
|
|
$exclude = "! \\( $dh{EXCLUDE_FIND} \\) ";
|
|
|
|
}
|
|
|
|
open(FIND, "find $tmp -type f \\( -name '*.dll' \\) $exclude |");
|
|
|
|
|
|
|
|
dll:
|
|
|
|
while (<FIND>) {
|
|
|
|
chomp;
|
|
|
|
my ($library, $ver, $libfile);
|
|
|
|
$libfile = $_;
|
|
|
|
|
|
|
|
my $sig;
|
|
|
|
my $command = "$sn -T $libfile 2>&1";
|
|
|
|
verbose_print("running signature reader command: $command");
|
|
|
|
my $output = `$command`;
|
|
|
|
if ($? == 0) {
|
|
|
|
$sig = $output;
|
|
|
|
if ($sig !~ s/.*key token: (\w+).*/$1/is) {
|
|
|
|
warning "$libfile has no signature, ignoring";
|
|
|
|
next dll;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
error("signature reader call failed: '$command' rc: $? output:\n$output");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
$command = "$sn -v $libfile 2>&1";
|
|
|
|
verbose_print("running signature verifier command: $command");
|
|
|
|
$output = `$command`;
|
|
|
|
if ($? != 0) {
|
|
|
|
verbose_print("signature verifier call failed: '$command' rc: $? output:\n$output");
|
|
|
|
warning("$libfile has no valid signature, ignoring");
|
|
|
|
next dll;
|
|
|
|
}
|
|
|
|
|
|
|
|
$command = "LANG=C MONO_GAC_PREFIX=\$MONO_GAC_PREFIX:$tmp/usr $cli_parser --assembly $libfile 2>&1";
|
|
|
|
verbose_print("running CLI parser command: $command");
|
|
|
|
|
|
|
|
$output = `$command`;
|
|
|
|
if ($? == 0) {
|
|
|
|
$output =~ m/Name:\s+(\S+)/;
|
|
|
|
$library = $1;
|
|
|
|
$output =~ m/Version:\s+(\S+)/;
|
|
|
|
$ver = $1;
|
|
|
|
} else {
|
|
|
|
error("cli_parser call failed: '$command' rc: $? output:\n$output");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!-d "$tmp/DEBIAN") {
|
|
|
|
doit("install", "-d", "$tmp/DEBIAN");
|
|
|
|
}
|
|
|
|
my $deps = $package;
|
|
|
|
|
|
|
|
# Call isnative becuase it sets $dh{VERSION}
|
|
|
|
# as a side effect.
|
|
|
|
isnative($package);
|
|
|
|
my $version = $dh{VERSION};
|
|
|
|
|
|
|
|
# Old compatibility levels include the
|
|
|
|
# debian revision, while new do not.
|
|
|
|
if (!compat(3)) {
|
|
|
|
# Remove debian version, if any.
|
|
|
|
$version =~ s/-[^-]+$//;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (defined($dh{M_PARAMS}) && $dh{M_PARAMS} ne '') {
|
|
|
|
$version = $dh{M_PARAMS};
|
|
|
|
}
|
|
|
|
if ($dh{V_FLAG_SET}) {
|
|
|
|
if ($dh{V_FLAG} ne '' ) {
|
|
|
|
$deps = $dh{V_FLAG};
|
|
|
|
} else {
|
|
|
|
$deps = "$package (>= $version)";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (defined($dh{R_FLAG})) {
|
|
|
|
$version =~ s/-[^-]+$//;
|
|
|
|
my @uvers = split ( /\./, $version );
|
|
|
|
$uvers[1]++;
|
|
|
|
$deps = "$package (>= $version), $package (<< ".join(".", @uvers).")";
|
|
|
|
}
|
|
|
|
if (defined($dh{M_PARAMS})) {
|
|
|
|
$deps = "$package (>= ".$dh{M_PARAMS}.")";
|
|
|
|
}
|
|
|
|
if (defined($dh{L_PARAMS})) {
|
|
|
|
$deps .= ", $package (<< ".$dh{L_PARAMS}.")";
|
|
|
|
}
|
|
|
|
if (defined($library) &&
|
|
|
|
defined($ver) &&
|
|
|
|
defined($deps) &&
|
|
|
|
$library ne '' &&
|
|
|
|
$ver ne '' &&
|
|
|
|
$deps ne '') {
|
|
|
|
# Prevent duplicate lines from entering the file.
|
|
|
|
my $line = "$library $ver" . "__$sig $deps";
|
|
|
|
|
|
|
|
# extra dependencies are to be resolved by dh_clideps,
|
|
|
|
# don't forward the dependency libs to the apps where it
|
|
|
|
# does not belong to
|
|
|
|
# if ( my $extra = extraDeps ($libfile) ) { $line .= ", $extra"; }
|
|
|
|
if (!$seen{$line}) {
|
|
|
|
$seen{$line} = 1;
|
|
|
|
complex_doit("echo '$line' >> $tmp/DEBIAN/clilibs");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close FIND;
|
|
|
|
|
|
|
|
if (-e "$tmp/DEBIAN/clilibs") {
|
|
|
|
doit("chmod", 644, "$tmp/DEBIAN/clilibs");
|
|
|
|
doit("chown", "0:0", "$tmp/DEBIAN/clilibs");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
|
|
|
|
L<debhelper(7)>
|
|
|
|
|
|
|
|
This program is a part of cli-common-dev.
|
|
|
|
|
|
|
|
=head1 KNOWN BUGS
|
|
|
|
|
|
|
|
Will possibly not work correctly with DH_COMPAT levels 1 and 2.
|
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
|
|
Mirco Bauer <meebey@meebey.net>, Eduard Bloch <blade@debian.org>,
|
|
|
|
inspired by dh_makeshlibs by Joey Hess <joeyh@debian.org>
|
|
|
|
|
|
|
|
=cut
|