]> git.pld-linux.org Git - projects/cleanbuild.git/blame - findbr
- preffer python-setuptools over python-distribute
[projects/cleanbuild.git] / findbr
CommitLineData
c494424e 1#!/usr/bin/perl
2
3use strict;
4use warnings;
5use IPC::Open2;
c728428f 6use Cwd;
c494424e 7
c728428f 8my $pwd = getcwd();
c494424e 9# how to run poldek
10my @ignore = qw(vserver-packages python-devel-src);
c728428f 11my @poldek = (qw(sudo poldek -n th-x86_64-ready), "--cachedir=$pwd/poldekcache",
12 "--skip-installed", "--conf=$pwd/poldekconf/poldek.conf",
c494424e 13 "-O", "ignore=" . (join " ", @ignore)
14);
15
16# if multiple packages provide some funcionality those will be selected:
17my %preferred = (
18 "automake" => +1,
19 "autoconf" => +1,
20 "pkgconfig" => +1,
21
22 "python" => +1,
23 "python-modules" => +1,
9ac658a4 24 "python-setuptools" => +1,
c494424e 25
26 "perl-modules" => +1,
27 "perl-Encode" => +2,
28
29 "zlib-devel" => +1,
30 "libstdc++-devel" => +1,
a75e2ecf 31 "libusb-compat-devel" => +1,
022b6e5b 32 "libjpeg-devel" => +1,
c728428f 33 "libpng-devel" => +1,
022b6e5b 34 "libsamplerate-devel" => +1,
35 "pulseaudio-devel" => +1,
36 "xorg-lib-libXrandr-devel" => +1,
c728428f 37 "sqlite-devel" => +1,
c494424e 38);
39
44dfaf2a 40# translate package name to provides name
c494424e 41my %translate = (
42 "rarian-compat" => "scrollkeeper",
022b6e5b 43 "Mesa-libGL" => "OpenGL",
44 "Mesa-libGL-devel" => "OpenGL-devel",
c494424e 45 "Mesa-libGLU-devel" => "OpenGL-GLU-devel",
46);
47
a6c4aafb 48my @skip = qw(hostname git svn svnversion);
49my %skip;
50@skip{ @skip } = (1) x scalar @skip;
51
c494424e 52# for m4 in *.m4; do R=$(rpm -qf $m4); R=${R%-*-*}; \
53# awk -vr=$R '/^\s*(AC_DEFUN|AU_ALIAS)/ { gsub(/\].*/,""); gsub(/.*\[/,""); print r " " $0}' $m4; \
54# done | sort | awk '{print "\t\"" $2 "\" => \"" $1 "\","}'
55my %ac2br = do "findbr-ac2br";
56
57my %cmake2br = (
58 "findkde4:44" => "kde4-kdelibs",
59 "findmsgfmt" => "gettext-devel",
60 "findpythoninterp" => "python",
61);
62
63BEGIN {
64 $SIG{__WARN__} = sub
65 {
66 local $_ = shift;
67 chomp;
68 print STDERR "\033[31;1m" . $_ . "\033[0m\n"
69 };
70}
71
72my $builddir = shift @ARGV;
73my @lines = <ARGV>;
74
75my $reason;
76
77my %out;
78sub add_br
79{
80 my $pkg = shift;
81 my $msg = shift || $reason;
82 if ( ref $pkg ) {
83 foreach my $p ( @$pkg ) {
84 add_br( $p, $msg );
85 }
86 return;
87 }
88
89 $msg =~ s/\n/ # /sg;
90
91 $pkg = $translate{ $pkg } || $pkg;
92
93 return if exists $out{ $pkg };
94 $out{ $pkg } = $msg;
95 print STDERR "\033[33;1madding: $pkg => $msg\033[0m\n";
96}
97
98sub poldek_cmd
99{
100 my $cmd = shift;
101 warn "Poldek: $cmd\n";
102 my $pid = open( READ, "-|", @poldek, "--shcmd=".$cmd );
103
104 my @read = <READ>;
105 close READ;
106
107 return @read if wantarray;
108 return \@read;
109}
110
111my $check_ac = 0;
c728428f 112my $check_config_log = undef;
c494424e 113
114my %checked_files;
115sub poldek_file
116{
117 my @files;
118 foreach ( @_ ) {
119 next if $checked_files{ $_ };
120 $checked_files{ $_ } = 1;
121 push @files, $_;
122 }
123 return unless @files;
124
125 my $search = join "; ", map "search -f $_", @files;
126 warn "Reason: $reason\n";
127 my @read = poldek_cmd( $search );
128
129 local $_;
130 my @found;
131 while ( $_ = shift @read ) {
132 if ( /(\d+) package\(s\) found:$/ ) {
133 foreach my $i ( 1..$1 ) {
134 $_ = shift @read;
135 chomp;
136 $_ =~ /^(.*)-.*?-.*?$/;
137 push @found, $1;
138 }
139 }
140 }
141
142 return unless @found;
143
144 my $found = $found[0];
145 if ( @found > 1 ) {
146 my $i = 0.0;
147 my %pts = map { ( $_ => ( ($i += 0.001) + ( $preferred{ $_ } || 0 ) ) ) }
148 reverse @found;
149 my @pref = sort { $pts{$b} <=> $pts{$a} } @found;
150 my $pref = join ", ", map "$_ => $pts{$_}", @pref;
151 warn "Multiple found: $pref\n";
152 $found = $pref[0];
153 }
154
155 $found = $translate{ $found } if $translate{ $found };
156
157 add_br( $found );
158}
159
160my $pkglist;
161sub get_pkglist
162{
163 my %pkglist;
164 my $read = poldek_cmd( "ls" );
165 foreach ( @$read ) {
166 chomp;
167 next unless /(\S+)-.*?-.*?\.[a-z0-9_]+$/;
168 my $pkg = $1;
169 $pkglist{ lc $pkg } = $pkg;
170 }
171 $pkglist = \%pkglist;
172}
173
174sub guess_package
175{
176 my $origname = shift;
177 get_pkglist() unless $pkglist;
178 return unless defined $origname;
179 my $name = lc $origname;
180 my @try = (
181 "lib$name-devel",
182 "$name-devel",
183 "$name",
184 "lib$name-.*-devel",
185 "$name-.*-devel",
186 ".*-lib$name-devel",
187 ".*-$name-devel",
188 ".*-lib$name-.*-devel",
189 ".*-$name-.*-devel",
190 );
191 my @select;
192 for my $k ( keys %$pkglist ) {
193 if ( $k =~ /$name/ ) {
194 push @select, $k;
195 }
196 }
197 @select = sort @select;
198
199 foreach my $try ( @try ) {
200 foreach my $pkg ( @select ) {
201 if ( $pkg =~ /^$try$/ ) {
202 warn "guessed: $origname => $pkglist->{ $pkg }\n";
203 return $pkglist->{ $pkg };
204 }
205 }
206 }
207 warn "$origname not guessed\n";
208 return undef;
209}
210
022b6e5b 211start_check:
212
c494424e 213my %checked;
214my $cmake_get_call = 0;
215my $cmake_pkg_list = 0;
216while ( $_ = shift @lines ) {
217 chomp;
218 #next if $checked{ $_ };
219 #$checked{ $_ } = 1;
220
221 $reason = $_;
222 if ( /^\S+: (\S+): (?:Command )?not found$/ or /.*configure\[\d+\]: (\S+): not found$/
223 or m{which: no (\S+) in \(.*/bin.*\)}
224 or m{\S+: (\S+): command not found$}
4dc40081 225 or m{/usr/bin/env: (\S+): No such file or directory}
c494424e 226 or m{Can't exec "(\S+)": No such file or directory} ) {
227 my $exec = $1;
c728428f 228 $exec = $1 if $exec =~ m{^"(.*)"$};
a6c4aafb 229 next if $skip{ $exec };
c494424e 230 warn "Looking for executable $exec\n";
231 if ( $exec =~ m#^/# ) {
232 poldek_file( $exec );
233 }
234 poldek_file( "/usr/bin/$exec", "/bin/$exec" );
235 }
236
237
bfe0e7d5 238 if ( /\S+\.[ch](?:pp|xx|c)?:\d+:\d+: error: (\S+): No such file or directory$/ or
239 /\S+\.[ch](?:pp|xx|c)?:\d+:\d+: fatal error: (\S+): No such file or directory$/ ) {
c494424e 240 my $h = $1;
241 warn "Looking for C(++) header $h\n";
242 poldek_file( "/usr/include*/$h" );
243 }
244 if ( m{^ImportError: No module named (\S+)$} ) {
245 my $mod = $1;
246 $mod =~ s#\.#/#g;
247 warn "Looking for python module $mod\n";
248 poldek_file( "/usr/share/python2*/$mod/__init__.py*",
249 "/usr/share/python2*/$mod.py*",
250 "/usr/lib*/python2*/$mod.py*",
9ac658a4 251 "/usr/lib*/python2*/_$mod.so",
252 "/usr/lib*/python2*/$mod.so" );
c494424e 253 }
254 if ( /configure(?:\.in|\.ac)?:\d+: error: possibly undefined macro: (\S+)/
e6da4d63 255 or m{configure(?:\.in|\.ac)?:\d+: error: m4 macro `(\S+)' is not defined}
256 or m{warning: macro `(\S+)' not found in library} ) {
c494424e 257 my $macro = $1;
258 warn "Looking for autotools macro $macro\n";
259 if ( my $br = $ac2br{ $macro } ) {
260 add_br( $br );
261 next;
c728428f 262 } else {
263 $check_ac = 1;
c494424e 264 }
265 }
266 if ( /^No package '(\S+)' found$/ or
267 /Package (\S+) was not found in the pkg-config search path/
268 or m{None of the required '(\S+?)(?:[<>=].*)?' found}
269 or m{--\s+package '(\S+?)(?:[<>=].*)?' not found}
270 ) {
271 my $pkg = $1;
272 warn "Looking for package $pkg\n";
273 poldek_file( "/usr/lib*/pkgconfig/$pkg.pc" );
274 }
275 if ( m{^cp: cannot stat `(/.*)': No such file or directory$} ) {
276 my $f = $1;
277 warn "Looking for file $f\n";
278 poldek_file( $f );
279 }
280 if ( m{^find-lang.sh: Error: international files not found for '}
281 or m{ gettext tools not found}
282 ) {
283 add_br( "gettext-devel" );
284 #exit;
285 next;
286 }
287 if ( m{ pkg-config .*not .*found}
288 or m{^checking for pkg-config\.\.\. no} ) {
289 add_br( "pkgconfig" );
290 #exit;
291 next;
292 }
293 if ( m{^Can't locate (.*?\.pm) in \@INC} ) {
294 my $mod = $1;
295 warn "Looking for perl module $mod\n";
296 poldek_file( "/usr/lib*/perl*/$mod", "/usr/share/perl*/$mod" );
297 }
c728428f 298 if ( m{^(?:/usr/bin/ld: )?cannot find -l(.*?)$} ) {
c494424e 299 my $lib = $1;
300 warn "Looking for library $lib\n";
c728428f 301 poldek_file( "/usr/lib64/lib$lib.so", "/usr/lib/lib$lib.so",
302 "/usr/lib*/lib$lib.so" );
c494424e 303 }
304 if ( m{^error: Couldn't exec (/\S+): No such file or directory$}
305 or m{^Can't open perl script "(/\S+)": No such file or directory$}
306 or m{unable to open (/\S+) \(No such file or directory\)$}
307 or m{GConf-CRITICAL \*\*: No such file `(/.\S+?)'$}
308 or m{make.*: \*\*\* No rule to make target `(/\S+)'}
309 or m{g(?:cc|\+\+): (/\S+): No such file or directory$}
c728428f 310 or m{env: (/\S+): No such file or directory$}
c494424e 311 ) {
312 my $file = $1;
313 warn "Looking for file $file\n";
314 poldek_file( $file );
315 }
c728428f 316 if ( m{^ValueError: Couldn't find include '(.*\.gir)'} ) {
317 my $file = $1;
318 warn "Looking for gir file $file\n";
319 poldek_file( "/usr/share/gir-1.0/" . $file );
320 }
c494424e 321 if ( m{failed.*http://www\.oasis-open\.org/docbook/xml/([\d\.]+/\S+\.dtd)} ) {
322 my $dtd = $1;
323 warn "Looking for docbook file $dtd\n";
324 poldek_file( "/usr/share/sgml/docbook/xml-dtd-$dtd" );
325 }
326 if ( m{http://docbook.sourceforge.net/release/xsl/current/(\S+\.xsl)} ) {
327 my $db = $1;
328 next if m{^\s*(/usr/bin/)?xsltproc };
329 warn "Looking for docbook file $db\n";
330 poldek_file( "/usr/share/sgml/*/$db" );
331 }
a755261c 332
333 if ( m{LaTeX Error: File `(\S+)' not found} ) {
334 my $tex = $1;
335 warn "Looking for tex file $tex\n";
336 poldek_file( "/usr/share/tex*/$tex" );
337 }
338 if ( m{mv: cannot move `\S+' to `(/var/lib/texmf.*?)':} ) {
339 my $tex = $1;
340 warn "Looking for tex file $tex\n";
341 poldek_file( $tex );
342 }
343
c494424e 344 if ( m{configure: error: C\+\+ preprocessor "/lib/cpp" fails sanity check} ) {
345 add_br( "gcc-c++", "try: %undefine\t__cxx" );
346 }
347 if ( m{configure: error: C\+\+ compiler cannot create executables} ) {
348 add_br( "libstdc++-devel", "maybe try: %undefine\t__cxx" );
349 }
350 if ( m{configure: error: XML::Parser perl module is required for intltool} ) {
351 add_br( "perl-XML-Parser" );
352 }
9ffdd22c 353 if ( m{iconv: conversion from `\S+' is not supported} ) {
354 add_br( "iconv" );
355 }
c494424e 356
bfe0e7d5 357 if ( m{ (\S+) does not appear in AM_CONDITIONAL$} ) {
358 my $macro = $1;
359 warn "Looking for autotools macro $macro\n";
360 if ( my $br = $ac2br{ $macro } ) {
361 add_br( $br );
362 next;
363 } else {
364 $check_ac = 1;
365 }
366 }
367
c494424e 368 if ( m{configure\[\d+\]: syntax error: }
a75e2ecf 369 or m{\./configure\[\d+\]: \S+_\S+: not found}
370 or m{./configure\[\d+\]: .*unexpected}
371 or m{does not appear in AM_CONDITIONAL$}
372 ) {
c494424e 373 warn "Need to check configure source: $reason\n";
374 $check_ac = 1;
375 }
022b6e5b 376 if ( m{^configure: error:} ) {
377 $check_config_log = 1 unless defined $check_config_log;
378 }
c494424e 379
380 if ( m{^CMake Error at (?:\S+/)?(\S+?)\.cmake:(\d+) } ) {
381 my ( $module, $line ) = ( lc $1, $2 );
382 my $br;
383 if ( $module eq "findqt4" ) {
384 my $l = $lines[0];
385 chomp $l;
386 if ( $l =~ /qmake/ ) {
387 add_br( "qt4-qmake", $l );
388 } elsif ( $l =~ /rcc/ ) {
389 add_br( "qt4-build", $l );
390 } elsif ( $l =~ /Could NOT find (Qt\S+) header/ ) {
391 add_br( "$1-devel", $l );
392 } else {
393 warn "unrecognized Qt requirement: $l\n";
394 }
395 } elsif ( $module eq "cmakedeterminecxxcompiler" ) {
396 add_br( "libstdc++-devel",
397 '"try: -DCMAKE_CXX_COMPILER_WORKS=1 -DCMAKE_CXX_COMPILER="%{__cc}"' );
398 } elsif ( $br = $cmake2br{ $module . ":" . $line } ) {
399 add_br( $br );
400 } elsif ( $br = $cmake2br{ $module } ) {
401 add_br( $br );
402 } elsif ( $br = guess_package( $module =~ /find(.+)/ ) ) {
403 add_br( $br );
404 } else {
405 $cmake_get_call = 1;
406 warn "Unrecognized cmake error: $reason\n";
407 }
408 }
409 if ( m{^\s*ERROR: (?:\S+/)?(\S+?\.cmake) not found} ) {
410 my $cmake = $1;
411 warn "Looking for cmake file: $cmake\n";
412 poldek_file( "/usr/*/cmake/*/$cmake" )
413 }
414 if ( $cmake_get_call ) {
415 if ( m{^\s*/\S+/(\S+)\.cmake:(\d+) } ) {
416 my ( $module, $line ) = ( lc $1, $2 );
417 my $br;
418 if ( $br = $cmake2br{ $module . ":" . $line } ) {
419 add_br( $br );
420 $cmake_get_call = 0;
421 } elsif ( $br = $cmake2br{ $module } ) {
422 add_br( $br );
423 $cmake_get_call = 0;
424 } elsif ( $br = guess_package( $module =~ /find(.+)/ ) ) {
425 add_br( $br );
426 $cmake_get_call = 0;
427 }
428 }
429 }
430 if ( m{^-- WARNING: you are using the obsolete 'PKGCONFIG' macro} ) {
431 add_br( "pkgconfig" );
432 }
433 if ( m{QT_(QT\S+)_LIBRARY \(ADVANCED\)}
434 or m{X11_(\S+)_LIB \(ADVANCED\)}
435 or m{Qt (\S+) library not found} ) {
436 my $find = $1;
437 my $pkg = guess_package( $find );
438 if ( $pkg ) {
439 add_br( $pkg );
440 } else {
441 warn "Cannot quess qt package: $find\n";
442 }
443 }
444
e6da4d63 445 if ( m{Unable to find a javac compiler;$} ) {
446 add_br( "jdk" );
447 }
9ffdd22c 448 if ( m{Could not find (\S+) Java extension for this JVM$} ) {
449 my $jar = $1;
450 warn "Looking for jar file: $jar\n";
451 poldek_file( "/usr/share/java/$jar.jar", "*/$jar.jar" )
452 }
e6da4d63 453
454
c494424e 455 if ( m{^-- The following OPTIONAL packages could NOT be located on your system} ) {
456 $cmake_pkg_list = 1;
457 }
458 if ( $cmake_pkg_list ) {
459 if ( /\s+\* (\S+) / ) {
460 my $find = $1;
461 my $pkg = guess_package( $find );
462 if ( $pkg ) {
463 add_br( $pkg );
464 } else {
465 warn "Cannot quess optional package: $find\n";
466 }
467 } elsif ( /^\s*$/ ) {
468 $cmake_pkg_list = 0;
469 }
470 }
c728428f 471
472 if ( m{^configure:\d+: checking for (?:"(\S+)"|(\S+))$} ) {
473 my $exec = $1 || $2;
474 if ( @lines and $lines[0] =~ m{^configure:\d+: result: no$} ) {
a6c4aafb 475 next if $skip{ $exec };
c728428f 476 warn "Looking for executable $exec\n";
477 poldek_file( $exec ) if $exec =~ m#^/#;
478 poldek_file( "/usr/bin/$exec", "/bin/$exec" );
479 }
480 }
c494424e 481}
482
483
484
485sub wanted
486{
487 return unless /^configure(\.(?:ac|in|in\.in))?$/;
488 return unless -r;
489
490 warn "$File::Find::name\n";
491 open F_IN, "<", $_;
492 my $file = $_;
493 while ( <F_IN> ) {
494 chomp;
495 if ( m{^\s*([A-Za-z0-9_]+)\s*(\(.*)?$} ) {
496 my $def = $1;
497 if ( my $br = $ac2br{ $def } ) {
498 add_br( $br, "$file: $_" );
499 } elsif ( $def !~ /^A[CM]_/ and $def =~ /^_?[A-Z]+_[A-Z_0-9a-z]+$/ ) {
500 #warn "Possible macro unrecognized: $def [[[$_]]]\n";
501 }
502 }
503 }
504 close F_IN;
505}
506
507use File::Find;
508if ( $check_ac ) {
509 find( \&wanted, $builddir );
510}
511
022b6e5b 512sub wanted2
513{
514 return unless /^config\.log$/;
515 return unless -r;
516
517 warn "$File::Find::name\n";
518 open F_IN, "<", $_;
519 push @lines, <F_IN>;
520 close F_IN;
521}
522
523if ( $check_config_log ) {
524 $check_config_log = 0;
525 find( \&wanted2, $builddir );
526 goto start_check if @lines;
527}
528
c494424e 529foreach my $pkg ( sort keys %out ) {
530 print "$pkg -- $out{$pkg}\n";
531}
532# vim: ts=4 sw=4
This page took 0.358236 seconds and 4 git commands to generate.