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