5 use File
::Temp
'tempfile';
12 my $x = join '', map { sprintf "%04s", $_ } split /\./, $a;
13 my $y = join '', map { sprintf "%04s", $_ } split /\./, $b;
19 my ($source, $pkgs) = @_;
23 foreach my $pkg (@
$pkgs) {
24 my (@pkgissues, %abi_versions);
26 next if !defined($pkg->{'libs'}) || @
{$pkg->{'libs'}} == 0;
28 foreach my $lib (@
{$pkg->{'libs'}}) {
29 next unless defined $lib->{'soname'};
31 if ($lib->{'soname'} =~ m!^.+\.so\.(.+?)$!) {
36 if (keys(%abi_versions) > 1) {
37 push @pkgissues, "bundles multiple libraries with different SONAME versions,\n".
38 " consider splitting into multiple packages:";
40 foreach my $lib (@
{$pkg->{'libs'}}) {
41 next unless defined $lib->{'soname'};
43 $pkgissues[-1] .= sprintf "\n - define Package/lib%s (%s)",
44 $lib->{'name'}, $lib->{'soname'};
48 my ($highest_version) = sort version_cmp
keys %abi_versions;
50 if (defined($highest_version) && !defined($pkg->{'abiversion'})) {
51 push @pkgissues, sprintf "should specify ABI_VERSION:=%s", $highest_version;
53 elsif (defined($highest_version) && defined($pkg->{'abiversion'}) &&
54 !exists($abi_versions{$pkg->{'abiversion'}})) {
56 sprintf "specifies ABI_VERSION:=%s but none of the libary sonames matches, " .
57 "consider changing to ABI_VERSION:=%s",
58 $pkg->{'abiversion'}, $highest_version;
61 foreach my $lib (@
{$pkg->{'libs'}}) {
62 next unless defined $lib->{'soname'};
64 if ($lib->{'soname'} =~ m!\.so(?:\.[0-9a-zA-Z]+)+$! && $lib->{'unversioned_symlink'}) {
66 sprintf "should not package unversioned %s symlink",
67 $lib->{'unversioned_symlink'};
73 sprintf " Package %s (define Package/%s)\n",
74 $pkg->{'name'}, $pkg->{'name'};
76 foreach my $issue (@pkgissues) {
78 sprintf " [-] %s\n", $issue;
81 $issues += @pkgissues;
86 printf "Source %s/Makefile\n", $source;
97 if (open my $control, '-|', "tar -Ozxf '$ipk' ./control.tar.gz | tar -Ozx ./control") {
98 while (defined(my $line = readline $control)) {
101 if ($line =~ m!^Package: *(\S+)$!) {
104 elsif ($line =~ m!^Source: *(\S+)$!) {
105 $info{'source'} = $1;
107 elsif ($line =~ m!^SourceName: *(\S+)$!) {
108 my $abiv = substr $info{'name'}, length $1;
112 $info{'abiversion'} = $abiv if length $abiv;
119 if (open my $listing, '-|', "tar -Ozxf '$ipk' ./data.tar.gz | tar -tz | sort") {
120 while (defined(my $entry = readline $listing)) {
121 chomp $entry; $entry =~ s/'/'"'"'/g;
123 if ($entry =~ m!.+/lib/lib(\S+)\.so((?:\.[0-9a-zA-Z]+)+)?$!) {
124 my ($fd, $fname) = tempfile
('/tmp/libfile.so.XXXXXXX', 'UNLINK' => 1);
125 my ($libname, $libversion) = ($1, $2);
127 if (!$lib || $lib->{'name'} ne $libname) {
128 $lib = { 'name' => $libname };
129 push @
{$info{'libs'}}, $lib;
132 if (open my $extract, '-|', "tar -Ozxf '$ipk' ./data.tar.gz | tar -Ozx '$entry'") {
133 while (read $extract, my $buf, 1024) {
141 if (open my $readelf, '-|', 'readelf', '-d', $fname) {
142 while (defined(my $line = readline $readelf)) {
145 if ($line =~ m!^ 0x[0-9a-f]{8,16} \(SONAME\) +Library soname: \[(.+)\]$!) {
146 $lib->{'soname'} = $1;
154 warn "Failed to execute readelf: $!\n";
157 elsif ($libversion) {
158 $lib->{'versioned_symlink'} = $entry;
161 $lib->{'unversioned_symlink'} = $entry;
175 @ARGV >= 1 || die "Usage: $0 <.ipk directory> [<.ipk directory>...]\n";
179 foreach my $dir (@ARGV) {
180 if (open my $find, '-|', 'find', $dir, '-type', 'f', '-name', 'lib*.ipk') {
181 while (defined(my $ipk = readline $find)) {
183 my $pkg = analyze_ipk
($ipk);
184 if (defined($pkg) && defined($pkg->{'source'})) {
185 push @
{$sources{$pkg->{'source'}}}, $pkg;
193 foreach my $source (sort keys %sources) {
194 print_diag
($source, $sources{$source});