7 use constant DOCKER => -e '/.dockerenv';
11 my @ignore = qw(vserver-packages python-devel-src);
14 push(@poldek, qw[poldek]);
16 push(@poldek, qw[sudo poldek -n th-x86_64-ready],
17 "--cachedir=$pwd/poldekcache",
18 "--conf=$pwd/poldekconf/poldek.conf",
23 "-O", "ignore=" . (join " ", @ignore)
26 # if multiple packages provide some funcionality those will be selected:
33 "python-modules" => +1,
34 "python-setuptools" => +1,
40 "libstdc++-devel" => +1,
41 "libusb-compat-devel" => +1,
42 "libjpeg-devel" => +1,
44 "libsamplerate-devel" => +1,
45 "pulseaudio-devel" => +1,
46 "xorg-lib-libXrandr-devel" => +1,
52 # translate package name to provides name
54 "gcc-c++" => "libstdc++-devel",
55 "rarian-compat" => "scrollkeeper",
56 "Mesa-libGL" => "OpenGL",
57 "Mesa-libGL-devel" => "OpenGL-devel",
58 "Mesa-libGLU-devel" => "OpenGL-GLU-devel",
61 my @skip = qw(hostname git svn svnversion mt gawk);
63 @skip{ @skip } = (1) x scalar @skip;
65 # for m4 in *.m4; do R=$(rpm -qf $m4); R=${R%-*-*}; \
66 # awk -vr=$R '/^\s*(AC_DEFUN|AU_ALIAS)/ { gsub(/\].*/,""); gsub(/.*\[/,""); print r " " $0}' $m4; \
67 # done | sort | awk '{print "\t\"" $2 "\" => \"" $1 "\","}'
68 my %ac2br = do (DOCKER ? './cleanbuild/bin/findbr-ac2br' : './bin/findbr-ac2br');
71 "findkde4:44" => "kde4-kdelibs",
72 "findmsgfmt" => "gettext-tools",
73 "findpythoninterp" => "python",
81 print STDERR "\033[31;1m" . $_ . "\033[0m\n"
85 my $builddir = shift @ARGV;
94 my $msg = shift || $reason;
96 foreach my $p ( @$pkg ) {
104 $pkg = $translate{ $pkg } || $pkg;
106 return if exists $out{ $pkg };
108 print STDERR "\033[33;1madding: $pkg => $msg\033[0m\n";
115 warn "Poldek: $cmd\n";
117 my @cmd = (@poldek, "--shcmd=".$cmd);
118 open my $fh, '-|', @cmd or die "$!: @cmd";
122 return wantarray ? @read : \@read;
126 my $check_config_log = undef;
127 my $check_mkmf_log = undef;
134 next if $checked_files{ $_ };
135 $checked_files{ $_ } = 1;
138 return unless @files;
140 my $search = join "; ", map "search -f $_", @files;
141 warn "Reason: $reason\n";
142 my @read = poldek_cmd( $search );
146 while ( $_ = shift @read ) {
147 if ( /(\d+) package\(s\) found:$/ ) {
148 foreach my $i ( 1..$1 ) {
151 $_ =~ /^(.*)-.*?-.*?$/;
157 return unless @found;
159 my $found = $found[0];
162 my %pts = map { ( $_ => ( ($i += 0.001) + ( $preferred{ $_ } || 0 ) ) ) }
164 my @pref = sort { $pts{$b} <=> $pts{$a} } @found;
165 my $pref = join ", ", map "$_ => $pts{$_}", @pref;
166 warn "Multiple found: $pref\n";
170 $found = $translate{ $found } if $translate{ $found };
179 my $read = poldek_cmd( "ls" );
182 next unless /(\S+)-.*?-.*?\.[a-z0-9_]+$/;
184 $pkglist{ lc $pkg } = $pkg;
186 $pkglist = \%pkglist;
191 my $origname = shift;
192 get_pkglist() unless $pkglist;
193 return unless defined $origname;
194 my $name = lc $origname;
203 ".*-lib$name-.*-devel",
207 for my $k ( keys %$pkglist ) {
208 if ( $k =~ /$name/ ) {
212 @select = sort @select;
214 foreach my $try ( @try ) {
215 foreach my $pkg ( @select ) {
216 if ( $pkg =~ /^$try$/ ) {
217 warn "guessed: $origname => $pkglist->{ $pkg }\n";
218 return $pkglist->{ $pkg };
222 warn "$origname not guessed\n";
229 my $cmake_get_call = 0;
230 my $cmake_pkg_list = 0;
232 while ( $_ = shift @lines ) {
234 #next if $checked{ $_ };
237 # try to extract current python version from setup.py run
238 if (m{^copying .+ -> build-(\d+)/lib/}) {
240 warn "py_ver set to '$py_ver'\n";
244 if ( /^\S+: (\S+): (?:Command )?not found$/ or /.*configure\[\d+\]: (\S+): not found$/
245 or m{which: no (\S+) in \(.*/bin.*\)}
246 or m{\S+: (\S+): command not found$}
247 or m{(?:/usr/bin/)?env: (\S+): No such file or directory}
248 or m{flock: (\S+): No such file or directory}
249 or m{Can't exec "(\S+)": No such file or directory} ) {
251 $exec = $1 if $exec =~ m{^"(.*)"$};
252 next if $skip{ $exec };
253 warn "Looking for executable $exec\n";
254 if ( $exec =~ m#^/# ) {
255 poldek_file( $exec );
257 poldek_file( "/usr/bin/$exec", "/bin/$exec" );
260 if ( /\S+\.[ch](?:pp|xx|c)?:\d+:\d+: error: (\S+): No such file or directory$/ or
261 /\S+\.[ch](?:pp|xx|c)?:\d+:\d+: fatal error: (\S+): No such file or directory$/ or
262 /Can't find the '(\S+\.h)'? header/
265 warn "Looking for C(++) header $h\n";
266 poldek_file( "/usr/include*/$h" );
269 if (m{^ImportError: No module named (\S+)$}
270 or m{^ERROR: Cannot find .+: No module named (\S+)$}
271 or m{^ERROR: Failed to import the ".+" module: No module named (\S+)$}
272 or m{^distutils.errors.DistutilsError: Could not find suitable distribution for Requirement.parse\('([^'>=]+).*'\)}
273 or m{^error: Could not find suitable distribution for Requirement.parse\('([^'>=]+).*'\)}
274 or m{^Couldn't find index page for '(\S+)'}
278 warn "Looking for Python$py_ver module $mod\n";
280 "/usr/share/python$py_ver*/site-packages/$mod/__init__.py*",
281 "/usr/share/python$py_ver*/$mod/__init__.py*",
282 "/usr/share/python$py_ver*/site-packages/$mod.py*",
283 "/usr/share/python$py_ver*/$mod.py*",
284 "/usr/lib*/python$py_ver*/site-packages/$mod/__init__.py*",
285 "/usr/lib*/python$py_ver*/$mod/__init__.py*",
286 "/usr/lib*/python$py_ver*/site-packages/$mod.py*",
287 "/usr/lib*/python$py_ver*/$mod.py*",
288 "/usr/lib*/python$py_ver*/site-packages/_$mod.so",
289 "/usr/lib*/python$py_ver*/_$mod.so",
290 "/usr/lib*/python$py_ver*/site-packages/$mod.so",
291 "/usr/lib*/python$py_ver*/$mod.so",
296 m{^-- Could NOT find Sphinx \(missing: SPHINX_EXECUTABLE\)}
298 add_br("sphinx-pdg");
303 m{^You need to install the (\S+) module} or
304 m{\*\*\*Error\*\*\*: You must have (\S+) >= (\S+) installed}
311 m{^cannot load such file -- (\S+)} or
312 m{in `require': cannot load such file -- (\S+) \(LoadError\)}
315 warn "Looking for ruby module $mod\n";
317 "/usr/share/ruby/*/$mod.rb",
318 "/usr/share/ruby/vendor_ruby/*/$mod.rb",
319 "/usr/lib64/ruby/vendor_ruby/*/$mod.so",
323 if ( /configure(?:\.in|\.ac)?:\d+: error: possibly undefined macro: (\S+)/
324 or m{configure(?:\.in|\.ac)?:\d+: error: m4 macro `(\S+)' is not defined}
325 or m{warning: macro `(\S+)' not found in library} ) {
327 warn "Looking for autotools macro $macro\n";
328 if ( my $br = $ac2br{ $macro } ) {
335 if ( /^No package '(\S+)' found$/ or
336 /Package (\S+) was not found in the pkg-config search path/
337 or m{None of the required '(\S+?)(?:[<>=].*)?' found}
338 or m{--\s+package '(\S+?)(?:[<>=].*)?' not found}
339 or m{ERROR: cannot find a valid pkg-config package for \['(\S+?)(?:[<>=].*)?'\]}
342 warn "Looking for package $pkg\n";
343 poldek_file( "/usr/lib*/pkgconfig/$pkg.pc", "/usr/share/pkgconfig/$pkg.pc" );
346 if (/^ocamlfind: Package `(\S+)' not found - required by/
347 or m{Camlp4: Uncaught exception: DynLoader.Error \("(\S+)", "file not found in path"\)}
350 warn "Looking for ocaml package $pkg\n";
351 poldek_file( "/usr/lib*/ocaml/*/$pkg.a", "/usr/lib*/ocaml/*/$pkg");
354 if ( m{^cp: cannot stat `(/.*)': No such file or directory$} ) {
356 warn "Looking for file $f\n";
360 if ( m{ERROR: Could not find KDE4 (kde4-config)}) {
361 my $f = "/usr/bin/$1";
362 warn "Looking for file $f\n";
366 if (m{Ragel State Machine Compiler not found}) {
371 if (m{ERROR: CMake is required to build}) {
377 if (m{'yum install (\S+)'}) {
382 if ( m{^find-lang.sh: Error: international files not found for '}
383 or m{ gettext tools not found}
385 add_br( "gettext-tools" );
389 if ( m{ pkg-config .*not .*found}
390 or m{^checking for pkg-config\.\.\. no}
391 or m{^pkg-config unavailable, build terminated}
392 or m{^\*\*\*Error\*\*\*: You must have pkg-config >= .* installed}
393 or m{^-- Could NOT find PkgConfig \(missing: PKG_CONFIG_EXECUTABLE\)}
394 or m{exec: "pkg-config": executable file not found in \$PATH}
396 add_br( "pkgconfig" );
400 if ( m{Can't locate (.*?\.pm) in \@INC} ) {
402 warn "Looking for perl module $mod\n";
403 poldek_file( "/usr/lib*/perl*/$mod", "/usr/share/perl*/$mod" );
407 m{^(?:/usr/bin/ld: )?cannot find -l(.*?)$}
410 warn "Looking for library $lib\n";
411 poldek_file( "/usr/lib64/lib$lib.so", "/usr/lib/lib$lib.so",
412 "/usr/lib*/lib$lib.so" );
415 # full path to ldd files
417 m{^WARNING; can.*t resolve .* dependency: (.*?)$}
420 warn "Looking for library '$lib'\n";
421 poldek_file( "/usr/lib64/$lib", "/usr/lib/$lib", "/lib64/$lib", "/lib/$lib");
424 if ( m{^error: Couldn't exec (/\S+): No such file or directory$}
425 or m{^Can't open perl script "(/\S+)": No such file or directory$}
426 or m{unable to open (/\S+) \(No such file or directory\)$}
427 or m{GConf-CRITICAL \*\*: No such file `(/.\S+?)'$}
428 or m{make.*: \*\*\* No rule to make target `(/\S+)'}
429 or m{g(?:cc|\+\+): (/\S+): No such file or directory$}
430 or m{env: (/\S+): No such file or directory$}
433 warn "Looking for file $file\n";
434 poldek_file( $file );
437 if ( m{^ValueError: Couldn't find include '(.*\.gir)'} ) {
439 warn "Looking for gir file $file\n";
440 poldek_file( "/usr/share/gir-1.0/" . $file );
443 if ( m{^error: Package `(\S+)' not found in specified Vala API directories or GObject-Introspection GIR directories}
446 warn "Looking for gir file $file\n";
447 poldek_file( "/usr/share/vala/vapi/$file.vapi");
450 if ( m{failed.*http://www\.oasis-open\.org/docbook/xml/([\d\.]+/\S+\.dtd)} ) {
452 warn "Looking for docbook file $dtd\n";
453 poldek_file( "/usr/share/sgml/docbook/xml-dtd-$dtd" );
455 if ( m{http://docbook.sourceforge.net/release/xsl/current/(\S+\.xsl)} ) {
457 next if m{^\s*(/usr/bin/)?xsltproc };
458 warn "Looking for docbook file $db\n";
459 poldek_file( "/usr/share/sgml/*/$db" );
461 if (m{Could not find HTML docbook.xsl}) {
462 add_br("docbook-style-xsl");
465 if ( m{LaTeX Error: File `(\S+)' not found} ) {
467 warn "Looking for tex file $tex\n";
468 poldek_file( "/usr/share/tex*/$tex" );
470 if ( m{mv: cannot move `\S+' to `(/var/lib/texmf.*?)':} ) {
472 warn "Looking for tex file $tex\n";
476 if ( m{configure: error: C\+\+ preprocessor "/lib/cpp" fails sanity check} ) {
477 add_br( "gcc-c++", "try: %undefine\t__cxx" );
479 if ( m{configure: error: C\+\+ compiler cannot create executables} ) {
480 add_br( "libstdc++-devel", "maybe try: %undefine\t__cxx" );
482 if ( m{ccache: error: Could not find compiler ".+-g\+\+" in PATH}) {
483 add_br("libstdc++-devel");
485 if ( m{configure: error: XML::Parser perl module is required for intltool} ) {
486 add_br( "perl-XML-Parser" );
488 if ( m{iconv: conversion from `\S+' is not supported} ) {
492 if (m{rst2man \(python-docutils\) is required to build man pages}) {
496 if ( m{ (\S+) does not appear in AM_CONDITIONAL$} ) {
498 warn "Looking for autotools macro $macro\n";
499 if ( my $br = $ac2br{ $macro } ) {
507 if ( m{configure\[\d+\]: syntax error: }
508 or m{\./configure\[\d+\]: \S+_\S+: not found}
509 or m{./configure\[\d+\]: .*unexpected}
510 or m{does not appear in AM_CONDITIONAL$}
512 warn "Need to check configure source: $reason\n";
515 if ( m{^configure: error:} ) {
516 $check_config_log = 1 unless defined $check_config_log;
519 if ( m{Check the mkmf.log file for more details} ) {
520 $check_mkmf_log = 1 unless defined $check_mkmf_log;
523 if ( m{^CMake (?:Error|Warning) at (?:\S+/)?(\S+?)\.cmake:(\d+) } ) {
524 my ( $module, $line ) = ( lc $1, $2 );
526 if ( $module eq "findqt4" ) {
529 if ( $l =~ /qmake/ ) {
530 add_br( "qt4-qmake", $l );
531 } elsif ( $l =~ /rcc/ ) {
532 add_br( "qt4-build", $l );
533 } elsif ( $l =~ /Could NOT find (Qt\S+) header/ ) {
534 add_br( "$1-devel", $l );
536 warn "unrecognized Qt requirement: $l\n";
538 } elsif ( $module eq "qt5coreconfig" ) {
541 if ( $l =~ /qmake/ ) {
542 add_br( "qt5-qmake", $l );
543 } elsif ( $l =~ /moc/) {
544 add_br( "qt5-build", $l );
546 warn "Unrecognized Qt requirement: $l\n";
548 } elsif ( $module eq "cmakedeterminecxxcompiler" ) {
549 add_br( "libstdc++-devel",
550 '"try: -DCMAKE_CXX_COMPILER_WORKS=1 -DCMAKE_CXX_COMPILER="%{__cc}"' );
551 } elsif ( $br = $cmake2br{ $module . ":" . $line } ) {
553 } elsif ( $br = $cmake2br{ $module } ) {
555 } elsif ( $br = guess_package( $module =~ /find(.+)/ ) ) {
559 warn "Unrecognized cmake error: $reason\n";
563 if ( m{^CMake Error at (?:\S+/)?(\S+?):(\d+) \(find_package\):} ) {
564 my ($file, $line) = (lc $1, $2);
566 #CMake Error at CMakeLists.txt:29 (find_package):
567 # Could not find a package configuration file provided by "LLVM" with any of the following names:
571 my @files = grep { /\.cmake$/ } @lines;
572 my @find = map { chomp; s/^\s+//; "/usr/*/cmake/*/$_" } @files;
576 if ( m{^\s*ERROR: (?:\S+/)?(\S+?\.cmake) not found} ) {
578 warn "Looking for cmake file: $cmake\n";
579 poldek_file( "/usr/*/cmake/*/$cmake" )
581 if ( $cmake_get_call ) {
582 if ( m{^\s*/\S+/(\S+)\.cmake:(\d+) } ) {
583 my ( $module, $line ) = ( lc $1, $2 );
585 if ( $br = $cmake2br{ $module . ":" . $line } ) {
588 } elsif ( $br = $cmake2br{ $module } ) {
591 } elsif ( $br = guess_package( $module =~ /find(.+)/ ) ) {
595 } elsif (m{Can not use "(.+)" module which has not yet been found}
596 or m{Could not find a package configuration file provided by "(.+)"}) {
599 warn "Looking for cmake file: $cmake\n";
601 "/usr/*/cmake/*/$cmake.cmake",
602 "/usr/*/cmake/*/${cmake}Config.cmake",
603 "/usr/*/cmake/*/${cmake}-config.cmake",
608 if ( m{^-- WARNING: you are using the obsolete 'PKGCONFIG' macro} ) {
609 add_br( "pkgconfig" );
611 if ( m{QT_(QT\S+)_LIBRARY \(ADVANCED\)}
612 or m{X11_(\S+)_LIB \(ADVANCED\)}
613 or m{Qt (\S+) library not found} ) {
615 my $pkg = guess_package( $find );
619 warn "Cannot quess qt package: $find\n";
623 if ( m{Unable to find a javac compiler;$} ) {
626 if ( m{Could not find (\S+) Java extension for this JVM$} ) {
628 warn "Looking for jar file: $jar\n";
629 poldek_file( "/usr/share/java/$jar.jar", "*/$jar.jar" )
633 if ( m{^-- The following OPTIONAL packages could NOT be located on your system} ) {
636 if ( $cmake_pkg_list ) {
637 if ( /\s+\* (\S+) / ) {
639 my $pkg = guess_package( $find );
643 warn "Cannot quess optional package: $find\n";
645 } elsif ( /^\s*$/ ) {
650 if (m{By not providing "Find(.+)\.cmake" in CMAKE_MODULE_PATH}
651 or m{Could not find a package configuration file provided by "(.+)"
654 my $lcmake = lc $cmake;
656 warn "Looking for cmake file: $cmake\n";
658 "/usr/*/cmake/*/$cmake.cmake",
659 "/usr/*/cmake/*/${cmake}Config.cmake",
660 "/usr/*/cmake/*/${cmake}-config.cmake",
661 "/usr/*/cmake/*/${lcmake}Config.cmake",
662 "/usr/*/cmake/*/${lcmake}-config.cmake",
666 if ( m{^configure:\d+: checking for (?:"(\S+)"|(\S+))$} ) {
668 if ( @lines and $lines[0] =~ m{^configure:\d+: result: no$} ) {
669 next if $skip{ $exec };
670 warn "Looking for executable $exec\n";
671 poldek_file( $exec ) if $exec =~ m#^/#;
672 poldek_file( "/usr/bin/$exec", "/bin/$exec" );
678 m{Could not find (\S+)}
681 poldek_file("/usr/bin/$exec", "/bin/$exec" );
689 return unless /^configure(\.(?:ac|in|in\.in))?$/;
692 warn "$File::Find::name\n";
697 if ( m{^\s*([A-Za-z0-9_]+)\s*(\(.*)?$} ) {
699 if ( my $br = $ac2br{ $def } ) {
700 add_br( $br, "$file: $_" );
701 } elsif ( $def !~ /^A[CM]_/ and $def =~ /^_?[A-Z]+_[A-Z_0-9a-z]+$/ ) {
702 #warn "Possible macro unrecognized: $def [[[$_]]]\n";
711 find( \&find_configure, $builddir );
716 return unless /^config\.log$/;
719 warn "$File::Find::name\n";
725 if ( $check_config_log ) {
726 $check_config_log = 0;
727 find( \&find_config_log, $builddir );
728 goto start_check if @lines;
731 if ($check_mkmf_log) {
734 return unless /^mkmf\.log$/;
737 warn "$File::Find::name\n";
742 goto start_check if @lines;
745 foreach my $pkg ( sort keys %out ) {
746 print "$pkg -- $out{$pkg}\n";