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