Upgrading libs with many dependent ports

Stephen Montgomery-Smith stephen at missouri.edu
Wed Jan 18 04:51:12 UTC 2012


On 01/17/2012 07:51 PM, Kevin Oberman wrote:
> I have just been cleaning up the mess caused by the upgrade of xcb-utils.
> On my systmes I have hundreds of ports that will be re-built by the methods
> listed in UPDATING, even though the vast majority of them are only
> dependent on other ports that are dependent on xcb-utils, but don't
> actually load any of the libraries in xcb-utils. It is a huge waste of time
> and CPU cycles.
>
> I think that I can see two ways of eliminating the rebuilding of ports that
> don't need it. One is rather manual but can be done now while the other
> wou;d be automatic, but would need to be written by someone who is far
> better at writing shell scripts than I.
>
> The manual method would be to install sysutils/bsdadminscripts and use a
> command like `pkg_libchk | grep -E "xcb-.+.so" | sort>  tmpfile` to provide
> a list of ports that actually are linked to the libraries in question. This
> would be fed into portmaster to rebuild just these ports. (I guess I could
> use awk and uniq to remove repeats.)
>
> Should this become a preferred method of handling this problem?


You mean something like the attached script?

Type

perl pkg_libchk xcb-util-0.3.6,1

and it tells you all the ports that have xcb-util-0.3.6,1 as a lib-depends.

On my system I get 38 ports that require upgrading.  All the other 248 
dependencies installed on my system are only run-depends, and so don't 
need to be upgraded.

I wrote it using perl, because I think a shell script would be quite a 
bit slower.  And it is already quite slow as it is.

It looks worth implementing, because it looks like it could save 
considerable compilation time.  If other people think this tool is 
useful, someone could clean up the script (e.g. it isn't PREFIX 
friendly, and assumes the port database is /var/db/pkg, etc).  It could 
also be written as a C program without too much trouble.
-------------- next part --------------
#!/usr/bin/perl -w

use strict;

my %lib_found;
my %ldd;
 
sub pkg_libchk {
  my $req="/var/db/pkg/$_[0]/+REQUIRED_BY";
  return if ! -e $req;

  my @libs;
  open(my $C,"/var/db/pkg/$_[0]/+CONTENTS") || die;
  while (<$C>) {
    if (!/^\@/ && /\/(lib[^\/]+\.so)$/) {
      push @libs,$1;
    }
  }
  close $C;
  return if $#libs==-1;

  open(my $R,$req) || die;
  while (my $r=<$R>) {
    next if defined($lib_found{$r});
    chomp $r;
    open(my $C,"/var/db/pkg/$r/+CONTENTS") || die;
    while (my $f=<$C>) {
      chomp $f;
      if ($f !~ /^@/) {
        if (!defined($ldd{$f})) {
          $ldd{$f} = `ldd "/usr/local/$f" 2>/dev/null`;
        }
        foreach my $l (@libs) {
          if ($ldd{$f} =~/$l/) {
            if (!defined($lib_found{$r})) {
              print "$r\n";
              $lib_found{$r}=1;
              pkg_libchk($r);
              goto DONE;
            }
          }
        }
      }
    }
DONE:
    close($C);
  }
  close($R);
}

die if ! -e "/var/db/pkg/$ARGV[0]";
pkg_libchk($ARGV[0]);


More information about the freebsd-ports mailing list