Re: limitation in build-depends
Matt Zimmerman wrote:
> On Fri, Jan 12, 2001 at 09:39:02AM +0100, Wichert Akkerman wrote:
> > Previously Paul Slootman wrote:
> > > Why doesn't dpkg-buildpackage check the Build-Depends line?
> > Patches are welcome.
>
> Here is a script I put together recently that does part of what is needed. It
> takes a list of packages, and checks whether they are installed or provided by
> another package. What is missing is handling for boolean expressions.
The attached program includes a fairly general subroutine for checking
build-dependancies, and your status parser, and a little bit of code to
call the subroutine and output a list of unmet build deps. It also
returns false if there are unmet build deps. Sample run:
joey@kite:~>perl check_build_deps
Enter build-dependancy line: libc6 (>= 9999.99) | bar [sparc]
Unmet: libc6 (>= 9999.99)
joey@kite:~>perl check_build_deps
Enter build-dependancy line: dpkg (>= 1.7.0), flex, bison, bsdmainutils, groff, libz-dev, libncurses5-dev, libpam-dev, libfreetype6-dev, libpaperg, tetex-bin, debhelper (>= 2.1.8), lynx, libglide2-dev [i386], libglide3-dev [i386]
Unmet: libpam-dev
Unmet: libfreetype6-dev
Unmet: libglide2-dev
Unmet: libglide3-dev
+ exit 1
It handles version number compares and architecture-sepecific
build-dependances, as you can see.
Handling of build-conflicts is left as an exercise for the reader.
Sadly, it's not a straightforeard inversion of the return code of
unmet_build_depends...
--
see shy jo
#!/usr/bin/perl -w
use strict;
$|=1;
print "Enter build-dependancy line: ";
my $line=<>;
chomp $line;
# This part could be replaced. Silly little status file parser.
# thanks to Matt Zimmerman.
my %providers;
my %version;
$/ = '';
my $status = "/var/lib/dpkg/status";
open(STATUS, "<$status") || die "$status: $!\n";
while (<STATUS>) {
next unless /^Status: .*ok installed$/m;
my ($package) = /^Package: (.*)$/m;
push @{$providers{$package}}, $package;
($version{$package}) = /^Version: (.*)$/m;
if (/^Provides: (.*)$/m) {
foreach (split(/,\s+/, $1)) {
push @{$providers{$_}}, $package;
}
}
}
close STATUS;
my @unmet=unmet_build_depends($line, \%version, \%providers);
foreach (@unmet) {
print STDERR "Unmet: $_\n";
}
exit 1 if @unmet;
# This function checks the build dependancies passed in as the first
# parameter. If they are satisfied, returns false. If they are unsatisfied,
# an list of the unsatisfied depends is returned.
#
# Additional parameters that must be passed:
# * A reference to a hash of all "ok installed" the packages on the system,
# with the hash key being the package name, and the value being the
# installed version.
# * A reference to a hash, where the keys are package names, and the
# value is a true value iff some package installed on the system provides
# that package (all installed packages provide themselves)
#
# Optionally, the architecture the package is to be built for can be passed
# in as the 4th parameter. If not set, dpkg will be queried for the build
# architecture.
sub unmet_build_depends {
my $line=shift;
my %version=%{shift()};
my %providers=%{shift()};
my $build_arch=shift || `dpkg --print-architecture`;
chomp $build_arch;
my @unmet=();
foreach my $dep (split(/,\s+/, $line)) {
my $ok=0;
my @possibles=();
ALTERNATE: foreach my $alternate (split(/\s*\|\s*/, $dep)) {
my ($package, $rest)=split(/\s+/, $alternate, 2);
# Check arch specifications.
if (defined $rest && $rest=~m/\[(.*?)\]/) {
my $arches=lc($1);
my $seen_arch='';
foreach my $arch (split(' ', $arches)) {
if ($arch eq $build_arch) {
$seen_arch=1;
next;
}
elsif ($arch eq "!$build_arch") {
next ALTERNATE;
}
elsif ($arch =~ /!/) {
# This is equivilant to
# having seen the current arch,
# unless the current arch
# is also listed..
$seen_arch=1;
}
}
if (! $seen_arch) {
next;
}
}
# This is a possibile way to meet the dependancy.
# Remove the arch stuff from $alternate.
$alternate=~s/\s+\[.*?\]//;
push @possibles, $alternate;
# Check version.
if (defined $rest && $rest=~m/\((..)\s+(.*?)\)/) {
my $relation=$1;
my $version=$2;
if (! exists $version{$package}) {
# Not installed at all, so fail.
next;
}
else {
# Compare installed and needed
# version number.
system("dpkg", "--compare-versions",
$version{$package}, $relation,
$version);
if (($? >> 8) != 0) {
next; # fail
}
}
}
elsif (! defined $providers{$package}) {
# It's not a versioned dependancy, and
# nothing provides it, so fail.
next;
}
# If we get to here, the dependancy was met.
$ok=1;
}
# If there were no possibilities of meeting this
# dependancy, it means it is a dep that only applies to
# other arches.
if (! $ok && @possibles) {
# TODO: this could return a more complex
# data structure instead to save re-parsing.
push @unmet, join (" | ", @possibles);
}
}
return @unmet;
}
Reply to: