summaryrefslogtreecommitdiffstats
path: root/scripts/create-recipe
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/create-recipe')
-rwxr-xr-xscripts/create-recipe2071
1 files changed, 2071 insertions, 0 deletions
diff --git a/scripts/create-recipe b/scripts/create-recipe
new file mode 100755
index 0000000000..e4bc4c322b
--- /dev/null
+++ b/scripts/create-recipe
@@ -0,0 +1,2071 @@
1#!/usr/bin/perl -w
2
3# Copyright (C) 2012 Wind River Systems, Inc.
4#
5# Copyright (C) 2010 Intel Corporation
6#
7#
8# This program is free software: you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation, either version 3 of the License.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20# As a special exception, you may create a larger work that contains
21# part or all of the autospectacle output and distribute that work
22# under terms of your choice.
23# Alternatively, if you modify or redistribute autospectacle itself,
24# you may (at your option) remove this special exception.
25#
26# This special exception was modeled after the bison exception
27# (as done by the Free Software Foundation in version 2.2 of Bison)
28#
29
30
31use File::Temp qw(tempdir);
32use File::Path qw(mkpath rmtree);
33use File::Spec ();
34use File::Basename qw(basename dirname);
35
36
37my $name = "";
38my $predef_version = "TO BE FILLED IN";
39my $version = $predef_version;
40my $pversion = $predef_version;
41my $description = "";
42my $summary = "";
43my $url = "";
44my $homepage = "";
45my @depends;
46my @rdepends;
47my @rawpythondeps;
48my $configure = "";
49my $localename = "";
50my @sources;
51my @mainfiles;
52my @patches;
53
54my $md5sum = "";
55my $sh256sum = "";
56my @inherits;
57
58my $printed_subpackages = 0;
59my $fulldir = "";
60
61my $builder = "";
62
63
64my $oscmode = 0;
65my $python = 0;
66
67my @banned_pkgconfig;
68my %failed_commands;
69my %failed_libs;
70my %failed_headers;
71
72
73
74######################################################################
75#
76# License management
77#
78# We store the sha1sum of common COPYING files in an associative array
79# %licenses.
80#
81# For all matching sha1's in the tarball, we then push the result
82# in the @license array (which we'll dedupe at the time of printing).
83#
84
85my %licenses;
86my @license;
87my %lic_files;
88
89sub setup_licenses
90{
91 $licenses{"06877624ea5c77efe3b7e39b0f909eda6e25a4ec"} = "GPLv2";
92 $licenses{"075d599585584bb0e4b526f5c40cb6b17e0da35a"} = "GPLv2";
93 $licenses{"10782dd732f42f49918c839e8a5e2894c508b079"} = "GPLv2";
94 $licenses{"2d29c273fda30310211bbf6a24127d589be09b6c"} = "GPLv2";
95 $licenses{"4df5d4b947cf4e63e675729dd3f168ba844483c7"} = "LGPLv2.1";
96 $licenses{"503df7650052cf38efde55e85f0fe363e59b9739"} = "GPLv2";
97 $licenses{"5405311284eab5ab51113f87c9bfac435c695bb9"} = "GPLv2";
98 $licenses{"5fb362ef1680e635fe5fb212b55eef4db9ead48f"} = "LGPLv2";
99 $licenses{"68c94ffc34f8ad2d7bfae3f5a6b996409211c1b1"} = "GPLv2";
100 $licenses{"66c77efd1cf9c70d4f982ea59487b2eeb6338e26"} = "LGPLv2.1";
101 $licenses{"74a8a6531a42e124df07ab5599aad63870fa0bd4"} = "GPLv2";
102 $licenses{"8088b44375ef05202c0fca4e9e82d47591563609"} = "LGPLv2.1";
103 $licenses{"8624bcdae55baeef00cd11d5dfcfa60f68710a02"} = "GPLv3";
104 $licenses{"8e57ffebd0ed4417edc22e3f404ea3664d7fed27"} = "MIT";
105 $licenses{"99b5245b4714b9b89e7584bfc88da64e2d315b81"} = "BSD";
106 $licenses{"aba8d76d0af67d57da3c3c321caa59f3d242386b"} = "MPLv1.1";
107 $licenses{"bf50bac24e7ec325dbb09c6b6c4dcc88a7d79e8f"} = "LGPLv2";
108 $licenses{"caeb68c46fa36651acf592771d09de7937926bb3"} = "LGPLv2.1";
109 $licenses{"dfac199a7539a404407098a2541b9482279f690d"} = "GPLv2";
110 $licenses{"e60c2e780886f95df9c9ee36992b8edabec00bcc"} = "LGPLv2.1";
111 $licenses{"c931aad3017d975b7f20666cde0953234a9efde3"} = "GPLv2";
112}
113
114sub guess_license_from_file {
115 my ($copying) = @_;
116
117 if (!-e $copying) {
118 return;
119 }
120
121 my $sha1output = `sha1sum $copying`;
122 $sha1output =~ /^([a-zA-Z0-9]*) /;
123 my $sha1 = $1;
124
125 chomp($sha1);
126
127 #
128 # if sha1 matches.. push there result
129 #
130 if (defined($licenses{$sha1})) {
131 my $lic = $licenses{$sha1};
132 push(@license, $lic);
133
134 my $md5output = `md5sum $copying`;
135 $md5output =~ /^([a-zA-Z0-9]*) /;
136 my $md5 = $1;
137 chomp($md5);
138 $lic_files{$copying} = $md5
139 }
140
141 #
142 # if file is found, and licence of python
143 # package is already aquired, add file.
144 #
145 if ($python == 1 && @license != 0) {
146 my $md5output = `md5sum $copying`;
147 $md5output =~ /^([a-zA-Z0-9]*) /;
148 my $md5 = $1;
149 chomp($md5);
150 $lic_files{$copying} = $md5
151 }
152
153 #
154 # We also must make sure that the COPYING/etc files
155 # end up in the main package as %doc..
156 #
157 $copying =~ s/$fulldir//g;
158 $copying =~ s/^\///g;
159 $copying = "\"\%doc " . $copying ."\"";
160
161 push(@mainfiles, $copying);
162}
163
164sub print_license
165{
166 my $count = @license;
167 if ($count == 0) {
168 print OUTFILE "License: TO BE FILLED IN\n";
169 return;
170 }
171
172 # remove dupes
173 undef %saw;
174 @saw{@license} = ();
175 @out = sort keys %saw;
176
177 print OUTFILE "License : ";
178 foreach (@out) {
179 print OUTFILE "$_ ";
180 }
181 print OUTFILE "\n";
182}
183
184# end of license section
185#
186#######################################################################
187
188######################################################################
189#
190# Package group management
191#
192# We set up an associative array of regexp patterns, where the content
193# of the array is the name of the group.
194#
195# These are "strings of regexps", which means one needs to escape
196# everything, and if you want the actual regexp to have a \,
197# it needs to be a \\ in this string.
198
199my %group_patterns;
200my @groups;
201my $group = "TO_BE/FILLED_IN";
202
203sub setup_group_rules
204{
205 $group_patterns{"^\\/usr\\/lib\\/.*so"} = "System/Libraries";
206 $group_patterns{"^\\/lib\\/.*so"} = "System/Libraries";
207 $group_patterns{"^\\/bin\\/.*"} = "Applications/System";
208 $group_patterns{"^\\/sbin\\/.*"} = "Applications/System";
209 $group_patterns{"^\\/usr\\/sbin\\/.*"} = "Applications/System";
210}
211
212sub guess_group_from_file
213{
214 my ($filename) = @_;
215 while (($key,$value) = each %group_patterns) {
216 if ($filename =~ /$key/) {
217 push(@groups, $value);
218 }
219 }
220
221}
222
223# end of group section
224#
225######################################################################
226
227
228######################################################################
229#
230# Files and package section
231#
232# This section creates the %files section, but also decides which
233# subpackages (devel and/or doc) we need to have.
234#
235# We start out with the @allfiles array, which will contain all the
236# files installed by the %build phase of the package. The task is
237# to sort these into @mainfiles, @develfiles and @docfiles.
238# In addition, an attempt is made to compress the files list by
239# replacing full filenames with "*" patterns.
240#
241# For this we use a set of regexps from the @files_match array,
242# which are then used as index to three associative arrays:
243# %files_target : numerical index for which package the regexp
244# would place the file at hand.
245# 0 - main package
246# 1 - devel package
247# 2 - doc package
248# 99 - don't package this at all
249#
250# %files_from: regexp to match the file against for filename-wildcarding
251# %files_to : pattern to append to the ()'d part of %files_from to end up
252# with the filename-wildcard.
253
254my @allfiles;
255my @develfiles;
256my @docfiles;
257
258
259my @files_match;
260my %files_target;
261my %files_from;
262my %files_to;
263
264my $totaldocs = 0;
265
266
267sub add_files_rule
268{
269 my ($match, $target, $from, $to) =@_;
270 push(@files_match, $match);
271 $files_target{"$match"} = $target;
272
273 if (length($from) > 0) {
274 $files_from{"$match"} = $from;
275 }
276
277 if (length($to) > 0) {
278 $files_to{"$match"} = $to;
279 }
280}
281
282sub setup_files_rules
283{
284
285#
286# Files for the Main package
287#
288
289 add_files_rule("^\\/usr\\/lib\\/[a-z0-9A-Z\\_\\-\\.]+\\.so\\.", 0,
290 "(\\/usr\\/lib\\/.*\\.so\\.).*", "\*");
291
292
293 add_files_rule("^\\/usr\\/share\\/omf\\/", 0,
294 "(\\/usr\\/share\\/omf\\/.*?\\/).*", "\*");
295
296#
297# Files for the Devel subpackage
298#
299 add_files_rule("^\\/usr\\/share\\/gir-1\\.0\\/[a-z0-9A-Z\\_\\-\\.]+\\.gir\$", 1,
300 "(\\/usr\\/share\\/gir-1\\.0\/).*", "\*\.gir");
301 add_files_rule("^\\/usr\\/lib\\/girepository-1\\.0\\/[a-z0-9A-Z\\_\\-\\.]+\\.typelib\$", 1,
302 "(\\/usr\\/lib\\/girepository-1\\.0\/).*", "\*\.typelib");
303 add_files_rule("^\\/usr\\/include\\/[a-z0-9A-Z\\_\\-\\.]+\\.h\$", 1,
304 "(\\/usr\\/include\/).*", "\*\.h");
305 add_files_rule("^\\/usr\\/include\\/[a-z0-9A-Z\\_\\-\\.]+\\/.*?\\.h\$", 1,
306 "(\\/usr\\/include\\/[a-z0-9A-Z\\_\\-\\.]+\\/.*?)[a-z0-9A-Z\\_\\-\\.]+\\.h", "\*\.h");
307 add_files_rule("^\\/usr\\/lib\\/[a-z0-9A-Z\\_\\-\\.]+\\.so\$", 1,
308 "(\\/usr\\/lib\\/).*\\.so\$", "\*.so");
309 add_files_rule("^\\/usr\\/lib\\/pkgconfig\\/[a-z0-9A-Z\\_\\-\\.\+]+\\.pc\$", 1,
310 "(\\/usr\\/lib\\/pkgconfig\\/).*\\.pc\$", "\*.pc");
311 add_files_rule("^\\/usr\\/share\\/aclocal", 1, "", "");
312 add_files_rule("^\\/usr\\/lib\\/qt4\\/mkspecs/", 1, "", "");
313
314
315
316
317#
318# Files for the documentation subpackage
319#
320 add_files_rule("^\\/usr\\/share\\/gtk\-doc\\/html\\/[a-z0-9A-Z\\_\\-\\.]+\\/.\*", 2,
321 "(\\/usr\\/share\\/gtk\-doc\\/html\\/[a-z0-9A-Z\\_\\-\\.]+\\/).\*", "\*");
322 add_files_rule("^\\/usr\\/share\\/doc\\/[a-zA-Z0-9\-]*", 2,
323 "(\\/usr\\/share\\/doc\\/[a-zA-Z0-9\-]+\\/).*", "\*");
324 add_files_rule("^\\/usr\\/share\\/man\\/man[0-9]\\/[a-zA-Z0-9\-]*", 2,
325 "(\\/usr\\/share\\/man\\/man[0-9]\\/[a-zA-Z0-9\-]+\\/).*", "\*");
326 add_files_rule("^\\/usr\\/share\\/gnome\\/help\\/", 2,
327 "(\\/usr\\/share\\/gnome\\/help\\/.*?\\/.*?\\/).*", "\*");
328
329
330#
331# Files to just not package at all (picked up by other things)
332#
333 add_files_rule("^\\/usr\\/share\\/locale", 99, "", "");
334 # compiled python things will get auto cleaned by rpm
335# add_files_rule("\.pyo\$", 99, "", "");
336# add_files_rule("\.pyc\$", 99, "", "");
337
338}
339
340sub apply_files_rules
341{
342 my $filenumber = @allfiles;
343
344 if ($filenumber == 0) {
345 return;
346 }
347
348 while (@allfiles > 0) {
349 my $filename = $allfiles[0];
350 my $destname = $filename;
351 my $handled = 0;
352
353#
354# while we're here, try to guess what group our package is
355#
356 guess_group_from_file($filename);
357
358 foreach (@files_match) {
359 my $match = $_;
360
361 if ($filename =~ /$match/) {
362#
363# First try to see if we can turn the full filename into a
364# wildcard based filename
365#
366 if (defined($files_from{$match}) && defined($files_to{$match})) {
367 $from = $files_from{$match};
368 $to = $files_to{$match};
369 $destname =~ s/$from/$1$to/;
370# print "changing $filename to $destname\n";
371 }
372
373# devel package
374 if ($files_target{$match} == 1) {
375 $handled = 1;
376 push(@develfiles, $destname);
377 }
378# doc rules.. also prepend %doc
379 if ($files_target{$match} == 2) {
380 $handled = 1;
381 $destname = "\"%doc " . $destname . "\"";
382 push(@docfiles, $destname);
383 $totaldocs = $totaldocs + 1;
384 }
385# don't package
386 if ($files_target{$match} == 99) {
387 $handled = 1;
388 if ($filename =~ /\/usr\/share\/locale\/.*?\/LC_MESSAGES\/(.*)\.mo/) {
389 $localename = $1;
390 }
391 }
392 }
393 }
394
395
396#
397# if the destination name contains our package version,
398# use %version instead for future maintenance
399#
400 $destname =~ s/$version/\%\{version\}/g;
401 if ($handled == 0) {
402 push(@mainfiles, $destname);
403 }
404 shift(@allfiles);
405 }
406
407#
408# Now.. if we have less than 5 documentation files, just stick them in the main package
409#
410
411 $filenumber = @docfiles;
412
413 if ($filenumber <= 5) {
414 while (@docfiles > 0) {
415 my $filename = $docfiles[0];
416
417 push(@mainfiles, $filename);
418 shift(@docfiles);
419 }
420 }
421
422}
423
424sub print_files
425{
426 my $count = @mainfiles;
427 if ($count == 0) {
428 return;
429 }
430
431 # remove dupes
432 undef %saw;
433 @saw{@mainfiles} = ();
434 @out = sort keys %saw;
435
436 print OUTFILE "Files:\n";
437 foreach (@out) {
438 print OUTFILE " - $_\n";
439 }
440}
441
442sub print_devel
443{
444 my $count = @develfiles;
445 if ($count == 0) {
446 return;
447 }
448 print OUTFILE "SubPackages:\n";
449 $printed_subpackages = 1;
450 print OUTFILE " - Name: devel\n";
451 print OUTFILE " Summary: Development components for the $name package\n";
452 print OUTFILE " Group: Development/Libraries\n";
453 print OUTFILE " Description:\n";
454 print OUTFILE " - Development files for the $name package\n";
455
456 # remove dupes
457 undef %saw;
458 @saw{@develfiles} = ();
459 @out = sort keys %saw;
460
461 print OUTFILE " Files:\n";
462 foreach (@out) {
463 print OUTFILE " - $_\n";
464 }
465}
466
467sub print_doc
468{
469 my $count = @docfiles;
470 if ($count == 0) {
471 return;
472 }
473 if ($printed_subpackages == 0) {
474 print OUTFILE "SubPackages:\n";
475 $printed_subpackages = 1;
476 }
477 print OUTFILE " - Name: docs\n";
478 print OUTFILE " Summary: Documentation components for the $name package\n";
479 print OUTFILE " Group: Documentation\n";
480
481 # remove dupes
482 undef %saw;
483 @saw{@docfiles} = ();
484 @out = sort keys %saw;
485
486 print OUTFILE " Files:\n";
487 foreach (@out) {
488 print OUTFILE " - $_\n";
489 }
490}
491
492
493# end of %files section
494#
495######################################################################
496
497
498######################################################################
499#
500# What we can learn from configure.ac/configure
501#
502# - pkgconfig requirements
503# - regular build requirements
504# - package name / version
505
506
507sub setup_pkgconfig_ban
508{
509 push(@banned_pkgconfig, "^dnl\$");
510 push(@banned_pkgconfig, "^hal\$"); # we don't have nor want HAL
511 push(@banned_pkgconfig, "tslib-0.0"); # we don't want tslib-0.0 (legacy touchscreen interface)
512 push(@banned_pkgconfig, "intel-gen4asm");
513 push(@banned_pkgconfig, "^xp\$"); # xprint - deprecated and not in meego
514 push(@banned_pkgconfig, "^directfb\$"); # we use X, not directfb
515 push(@banned_pkgconfig, "^gtkmm-2.4\$"); # we use X, not directfb
516 push(@banned_pkgconfig, "^evil\$");
517 push(@banned_pkgconfig, "^directfb");
518 push(@banned_pkgconfig, "^sdl ");
519
520
521}
522
523sub setup_failed_commands
524{
525 $failed_commands{"doxygen"} = "doxygen";
526 $failed_commands{"scrollkeeper-config"} = "rarian-compat";
527 $failed_commands{"dot"} = "graphviz";
528 $failed_commands{"flex"} = "flex";
529 $failed_commands{"lex"} = "flex";
530 $failed_commands{"freetype-config"} = "freetype-devel";
531 $failed_commands{"makeinfo"} = "texinfo";
532 $failed_commands{"desktop-file-install"} = "desktop-file-utils";
533 $failed_commands{"deflateBound in -lz"} = "zlib-devel";
534 $failed_commands{"gconftool-2"} = "GConf-dbus";
535 $failed_commands{"jpeglib.h"} = "libjpeg-devel";
536 $failed_commands{"expat.h"} = "expat-devel";
537 $failed_commands{"bison"} = "bison";
538 $failed_commands{"msgfmt"} = "gettext";
539 $failed_commands{"curl-config"} = "libcurl-devel";
540 $failed_commands{"doxygen"} = "doxygen";
541 $failed_commands{"X"} = "pkgconfig(x11)";
542
543 $failed_commands{"gawk"} = "gawk";
544 $failed_commands{"xbkcomp"} = "xkbcomp";
545 $failed_commands{"Vorbis"} = "libvorbis-devel";
546 # checking Expat 1.95.x... no
547 $failed_commands{"Expat 1.95.x"} = "expat-devel";
548 $failed_commands{"xml2-config path"} = "libxml2-devel";
549
550 $failed_libs{"-lz"} = "zlib-devel";
551 $failed_libs{"-lncursesw"} = "ncurses-devel";
552 $failed_libs{"-ltiff"} = "libtiff-devel";
553 $failed_libs{"-lasound"} = "alsa-lib-devel";
554 $failed_libs{"Curses"} = "ncurses-devel";
555
556 $failed_headers{"X11/extensions/randr.h"} = "xrandr";
557 $failed_headers{"X11/Xlib.h"} = "x11";
558 $failed_headers{"X11/extensions/XShm.h"} = "xext";
559 $failed_headers{"X11/extensions/shape.h"} = "xext";
560 $failed_headers{"ncurses.h"} = "ncursesw";
561 $failed_headers{"curses.h"} = "ncursesw";
562 $failed_headers{"pci/pci.h"} = "libpci";
563 $failed_headers{"xf86.h"} = "xorg-server";
564 $failed_headers{"sqlite.h"} = "sqlite3";
565
566 $failed_headers{"X11/extensions/XIproto.h"} = "xi";
567 $failed_headers{"QElapsedTimer"} = "";
568}
569
570
571
572my @package_configs;
573my @buildreqs;
574my $uses_configure = 0;
575
576
577sub push_pkgconfig_buildreq
578{
579 my ($pr) = @_;
580
581 $pr =~ s/\s+//g;
582
583 # remove collateral ] ) etc damage in the string
584 $pr =~ s/\"//g;
585 $pr =~ s/\)//g;
586 $pr =~ s/\]//g;
587 $pr =~ s/\[//g;
588
589
590 # first, undo the space packing
591
592 $pr =~ s/\>\=/ \>\= /g;
593 $pr =~ s/\<\=/ \<\= /g;
594
595 $pr =~ s/\<1.1.1/ /g;
596
597 # don't show configure variables, we can't deal with them
598 if ($pr =~ /^\$/) {
599 return;
600 }
601 if ($pr =~ /AC_SUBST/) {
602 return;
603 }
604
605
606
607
608 # process banned pkgconfig options for things that we don't
609 # have or don't want.
610
611
612 # remore versions that are macros or strings, not numbers
613 $pr =~ s/\s\>\= \$.*//g;
614
615 $pr =~ s/\s\>\= [a-zA-Z]+.*//g;
616
617 # don't show configure variables, we can't deal with them
618 if ($pr =~ /\$/) {
619 return;
620 }
621
622 foreach (@banned_pkgconfig) {
623 my $ban = $_;
624 if ($pr =~ /$ban/) {
625 return;
626 }
627 }
628
629 push(@package_configs, $pr);
630}
631
632#
633# detect cases where we require both a generic pkgconfig, and a version specific
634# case
635#
636sub uniquify_pkgconfig
637{
638 # first remove real dupes
639 undef %saw;
640 @saw{@package_configs} = ();
641 @out = sort keys %saw;
642
643 my $count = 0;
644
645 while ($count < @out) {
646
647 my $entry = $out[$count];
648
649 foreach(@out) {
650 my $compare = $_;
651 if ($entry eq $compare) {
652 next;
653 }
654
655 $compare =~ s/ \>\=.*//g;
656 if ($entry eq $compare) {
657 $out[$count] = "";
658 }
659 }
660 $count = $count + 1;
661 }
662 @package_configs = @out;
663}
664
665
666sub process_configure_ac
667{
668 my ($filename) = @_;
669 my $line = "";
670 my $depth = 0;
671 my $keepgoing = 1;
672 my $buffer = "";
673
674 if (!-e $filename) {
675 return;
676 }
677
678 $uses_configure = 1;
679
680
681
682 open(CONFIGURE, "$filename") || die "Couldn't open $filename\n";
683 seek(CONFIGURE, 0,0) or die "seek : $!";
684 while ($keepgoing && !eof(CONFIGURE)) {
685 $buffer = getc(CONFIGURE);
686
687 if ($buffer eq "(") {
688 $depth = $depth + 1;
689 }
690 if ($buffer eq ")" && $depth > 0) {
691 $depth = $depth - 1;
692 }
693
694 if (!($buffer eq "\n")) {
695 $line = $line . $buffer;
696 }
697
698 if (!($buffer eq "\n") || $depth > 0) {
699 redo unless eof(CONFIGURE);
700 }
701
702 if ($line =~ /PKG_CHECK_MODULES\((.*)\)/) {
703 my $match = $1;
704 $match =~ s/\s+/ /g;
705 $match =~ s/, /,/g;
706 my @pkgs = split(/,/, $match);
707 my $pkg;
708 if (defined($pkgs[1])) {
709 $pkg = $pkgs[1];
710 } else {
711 next;
712 }
713 if ($pkg =~ /\[(.*)\]/) {
714 $pkg = $1;
715 }
716
717 $pkg =~ s/\s+/ /g;
718 # deal with versioned pkgconfig's by removing the spaces around >= 's
719 $pkg =~ s/\>\=\s/\>\=/g;
720 $pkg =~ s/\s\>\=/\>\=/g;
721 $pkg =~ s/\=\s/\=/g;
722 $pkg =~ s/\s\=/\=/g;
723 $pkg =~ s/\<\=\s/\<\=/g;
724 $pkg =~ s/\<\s/\</g;
725 $pkg =~ s/\s\<\=/\<\=/g;
726 $pkg =~ s/\s\</\</g;
727
728 @words = split(/ /, $pkg);
729 foreach(@words) {
730 push_pkgconfig_buildreq($_);
731 }
732 }
733
734 if ($line =~ /PKG_CHECK_EXISTS\((.*)\)/) {
735 my $match = $1;
736 $match =~ s/\s+/ /g;
737 $match =~ s/, /,/g;
738 my @pkgs = split(/,/, $match);
739 my $pkg = $pkgs[0];
740 if ($pkg =~ /\[(.*)\]/) {
741 $pkg = $1;
742 }
743
744 $pkg =~ s/\s+/ /g;
745 # deal with versioned pkgconfig's by removing the spaces around >= 's
746 $pkg =~ s/\>\=\s/\>\=/g;
747 $pkg =~ s/\s\>\=/\>\=/g;
748 $pkg =~ s/\<\=\s/\<\=/g;
749 $pkg =~ s/\<\s/\</g;
750 $pkg =~ s/\s\<\=/\<\=/g;
751 $pkg =~ s/\s\</\</g;
752 $pkg =~ s/\=\s/\=/g;
753 $pkg =~ s/\s\=/\=/g;
754
755 @words = split(/ /, $pkg);
756 foreach(@words) {
757 push_pkgconfig_buildreq($_);
758 }
759 }
760
761 if ($line =~ /XDT_CHECK_PACKAGE\(.*?,.*?\[(.*?)\].*\)/) {
762 my $pkg = $1;
763
764 $pkg =~ s/\s+/ /g;
765 # deal with versioned pkgconfig's by removing the spaces around >= 's
766 $pkg =~ s/\>\=\s/\>\=/g;
767 $pkg =~ s/\s\>\=/\>\=/g;
768 $pkg =~ s/\=\s/\=/g;
769 $pkg =~ s/\s\=/\=/g;
770
771 @words = split(/ /, $pkg);
772 foreach(@words) {
773 push_pkgconfig_buildreq($_);
774 }
775 }
776
777 if ($line =~ /XDT_CHECK_OPTIONAL_PACKAGE\(.*?,.*?\[(.*?)\].*\)/) {
778 my $pkg = $1;
779
780 $pkg =~ s/\s+/ /g;
781 # deal with versioned pkgconfig's by removing the spaces around >= 's
782 $pkg =~ s/\>\=\s/\>\=/g;
783 $pkg =~ s/\s\>\=/\>\=/g;
784 $pkg =~ s/\=\s/\=/g;
785 $pkg =~ s/\s\=/\=/g;
786
787 @words = split(/ /, $pkg);
788 foreach(@words) {
789 push_pkgconfig_buildreq($_);
790 }
791 }
792
793 if ($line =~ /AC_CHECK_LIB\(\[expat\]/) {
794 push(@buildreqs, "expat-devel");
795 }
796 if ($line =~ /AC_CHECK_FUNC\(\[tgetent\]/) {
797 push(@buildreqs, "ncurses-devel");
798 }
799 if ($line =~ /_PROG_INTLTOOL/) {
800 push(@buildreqs, "intltool");
801 }
802 if ($line =~ /GETTEXT_PACKAGE/) {
803 push(@buildreqs, "gettext");
804 }
805 if ($line =~ /GTK_DOC_CHECK/) {
806 push_pkgconfig_buildreq("gtk-doc");
807 }
808 if ($line =~ /GNOME_DOC_INIT/) {
809 push(@buildreqs, "gnome-doc-utils");
810 }
811 if ($line =~ /AM_GLIB_GNU_GETTEXT/) {
812 push(@buildreqs, "gettext");
813 }
814
815 if ($line =~ /AC_INIT\((.*)\)/) {
816 my $match = $1;
817 $match =~ s/\s+/ /g;
818 @acinit = split(/,/, $match);
819# $name = $acinit[0];
820
821 if ($name =~ /\[(.*)\]/) {
822# $name = $1;
823 }
824
825 if (defined($acinit[3])) {
826# $name = $acinit[3];
827 if ($name =~ /\[(.*)\]/) {
828# $name = $1;
829 }
830 }
831 if (defined($acinit[1]) and $version eq $predef_version) {
832 my $ver = $acinit[1];
833 $ver =~ s/\[//g;
834 $ver =~ s/\]//g;
835 if ($ver =~ /\$/){} else {
836 $version = $ver;
837 $version =~ s/\s+//g;
838 }
839 }
840 }
841 if ($line =~ /AM_INIT_AUTOMAKE\((.*)\)/) {
842 my $match = $1;
843 $match =~ s/\s+/ /g;
844 @acinit = split(/,/, $match);
845# $name = $acinit[0];
846
847 if ($name =~ /\[(.*)\]/) {
848# $name = $1;
849 }
850
851 if (defined($acinit[3])) {
852# $name = $acinit[3];
853 if ($name =~ /\[(.*)\]/) {
854# $name = $1;
855 }
856 }
857 if (defined($acinit[1]) and $version eq $predef_version) {
858 my $ver = $acinit[1];
859 $ver =~ s/\[//g;
860 $ver =~ s/\]//g;
861 if ($ver =~ /\$/){} else {
862 $version = $ver;
863 $version =~ s/\s+//g;
864 }
865 }
866 }
867
868 $line = "";
869 }
870 close(CONFIGURE);
871}
872
873sub process_qmake_pro
874{
875 my ($filename) = @_;
876 my $line = "";
877 my $depth = 0;
878 my $keepgoing = 1;
879 my $buffer = "";
880 my $prev_char = "";
881
882 if (!-e $filename) {
883 return;
884 }
885
886
887 open(CONFIGURE, "$filename") || die "Couldn't open $filename\n";
888 seek(CONFIGURE, 0,0) or die "seek : $!";
889 while ($keepgoing && !eof(CONFIGURE)) {
890 $buffer = getc(CONFIGURE);
891
892 if ($buffer eq "(") {
893 $depth = $depth + 1;
894 }
895 if ($buffer eq ")" && $depth > 0) {
896 $depth = $depth - 1;
897 }
898
899 if (!($buffer eq "\n")) {
900 $line = $line . $buffer;
901 }
902
903 if (!($buffer eq "\n") || ($prev_char eq "\\") ) {
904 $prev_char = $buffer;
905 redo unless eof(CONFIGURE);
906 }
907 $prev_char = " ";
908
909 if ($line =~ /PKGCONFIG.*?\=(.*)/) {
910 my $l = $1;
911 my @pkgs;
912
913 $l =~ s/\\//g;
914 $l =~ s/\s/ /g;
915 @pkgs = split(/ /, $l);
916 foreach (@pkgs) {
917 if (length($_)>1) {
918 push_pkgconfig_buildreq($_);
919 }
920 }
921 }
922
923 $line = "";
924 }
925 close(CONFIGURE);
926}
927
928#
929# We also check configure if it exists, it's nice for some things
930# because various configure.ac macros have been expanded for us already.
931#
932sub process_configure
933{
934 my ($filename) = @_;
935 my $line = "";
936 my $depth = 0;
937 my $keepgoing = 1;
938
939 if (!-e $filename) {
940 return;
941 }
942
943 $uses_configure = 1;
944
945 open(CONFIGURE, "$filename") || die "Couldn't open $filename\n";
946 seek(CONFIGURE, 0,0) or die "seek : $!";
947 while ($keepgoing && !eof(CONFIGURE)) {
948 $buffer = getc(CONFIGURE);
949
950 if ($buffer eq "(") {
951 $depth = $depth + 1;
952 }
953 if ($buffer eq ")" && $depth > 0) {
954 $depth = $depth - 1;
955 }
956
957 if (!($buffer eq "\n")) {
958 $line = $line . $buffer;
959 }
960
961 if (!($buffer eq "\n") || $depth > 0) {
962 redo unless eof(CONFIGURE);
963 }
964
965
966
967 if ($line =~ /^PACKAGE_NAME=\'(.*?)\'/) {
968 $name = $1;
969 }
970 if ($line =~ /^PACKAGE_TARNAME=\'(.*?)\'/) {
971 $name = $1;
972 }
973 if ($line =~ /^PACKAGE_VERSION=\'(.*?)\'/) {
974 $version = $1;
975 $version =~ s/\s+//g;
976 }
977 if ($line =~ /^PACKAGE_URL=\'(.*?)\'/) {
978 if (length($1) > 2) {
979 $url = $1;
980 }
981 }
982
983
984 $line = "";
985 }
986 close(CONFIGURE);
987}
988
989sub print_pkgconfig
990{
991 my $count = @package_configs;
992 if ($count == 0) {
993 return;
994 }
995
996 uniquify_pkgconfig();
997
998 print OUTFILE "PkgConfigBR:\n";
999 foreach (@out) {
1000 $line = $_;
1001 $line =~ s/^\s+//g;
1002 if (length($line) > 1) {
1003 print OUTFILE " - $line\n";
1004 }
1005 }
1006}
1007
1008sub print_buildreq
1009{
1010 my $count = @buildreqs;
1011 if ($count == 0) {
1012 return;
1013 }
1014
1015 # remove dupes
1016 undef %saw;
1017 @saw{@buildreqs} = ();
1018 @out = sort keys %saw;
1019
1020 print OUTFILE "PkgBR:\n";
1021 foreach (@out) {
1022 print OUTFILE " - $_\n";
1023 }
1024}
1025
1026
1027# end of configure section
1028#
1029######################################################################
1030
1031
1032######################################################################
1033#
1034# Guessing the Description and Summary for a package
1035#
1036# We'll look at various sources of information for this:
1037# - spec files in the package
1038# - debain files in the package
1039# - DOAP files in the package
1040# - pkgconfig files in the package
1041# - the README file in the package
1042# - freshmeat.net online
1043#
1044
1045sub guess_description_from_spec {
1046 my ($specfile) = @_;
1047
1048 my $state = 0;
1049 my $cummul = "";
1050
1051 open(SPEC, $specfile);
1052 while (<SPEC>) {
1053 my $line = $_;
1054 if ($state == 1 && $line =~ /^\%/) {
1055 $state = 2;
1056 }
1057 if ($state == 1) {
1058 $cummul = $cummul . $line;
1059 }
1060 if ($state==0 && $line =~ /\%description/) {
1061 $state = 1;
1062 }
1063
1064 if ($line =~ /Summary:\s*(.*)/ && length($summary) < 2) {
1065 $summary = $1;
1066 }
1067 if ($line =~ /URL:\s*(.*)/ && length($url) < 2) {
1068 $url = $1;
1069 }
1070 }
1071 close(SPEC);
1072 if (length($cummul) > 4) {
1073 $description = $cummul;
1074 }
1075}
1076
1077#
1078# DOAP is a project to create an XML/RDF vocabulary to describe software projects, and in particular open source.
1079# so if someone ships a .doap file... we can learn from it.
1080#
1081sub guess_description_from_doap {
1082 my ($doapfile) = @_;
1083
1084 open(DOAP, $doapfile);
1085 while (<DOAP>) {
1086 my $line = $_;
1087 # <shortdesc xml:lang="en">Virtual filesystem implementation for gio</shortdesc>
1088 if ($line =~ /\<shortdesc .*?\>(.*)\<\/shortdesc\>/) {
1089 $summary = $1;
1090 }
1091 if ($line =~ /\<homepage .*?resource=\"(.*)\"\s*\/>/) {
1092 $url = $1;
1093 }
1094 }
1095 close(DOAP);
1096}
1097
1098#
1099# Debian control files have some interesting fields we can glean information
1100# from as well.
1101#
1102sub guess_description_from_debian_control {
1103 my ($file) = @_;
1104
1105 my $state = 0;
1106 my $cummul = "";
1107
1108 $file = $file . "/debian/control";
1109
1110 open(FILE, $file) || return;
1111 while (<FILE>) {
1112 my $line = $_;
1113 if ($state == 1 && length($line) < 2) {
1114 $state = 2;
1115 }
1116 if ($state == 1) {
1117 $cummul = $cummul . $line;
1118 }
1119 if ($state==0 && $line =~ /\Description: (.*)/) {
1120 $state = 1;
1121 $cummul = $1;
1122 }
1123
1124 }
1125 close(FILE);
1126 if (length($cummul) > 4) {
1127 $description = $cummul;
1128 }
1129}
1130
1131#
1132# the pkgconfig files have often a one line description
1133# of the software... good for Summary
1134#
1135sub guess_description_from_pkgconfig {
1136 my ($file) = @_;
1137
1138 open(FILE, $file);
1139 while (<FILE>) {
1140 my $line = $_;
1141
1142 if ($line =~ /Description:\s*(.*)/ && length($summary) < 2) {
1143 $summary = $1;
1144 }
1145 }
1146 close(FILE);
1147}
1148
1149#
1150# Freshmeat can provide us with a good one paragraph description
1151# of the software..
1152#
1153sub guess_description_from_freshmeat {
1154 my ($tarname) = @_;
1155 my $cummul = "";
1156 my $state = 0;
1157 open(HTML, "curl -s http://freshmeat.net/projects/$tarname |");
1158 while (<HTML>) {
1159 my $line = $_;
1160
1161 if ($state == 1) {
1162 $cummul = $cummul . $line;
1163 }
1164 if ($state == 0 && $line =~ /\<div class\=\"project-detail\"\>/) {
1165 $state = 1;
1166 }
1167 if ($state == 1 && $line =~/\<\/p\>/) {
1168 $state = 2;
1169 }
1170 }
1171 close(HTML);
1172 $cummul =~ s/\<p\>//g;
1173 $cummul =~ s/\r//g;
1174 $cummul =~ s/\<\/p\>//g;
1175 $cummul =~ s/^\s*//g;
1176 if (length($cummul)>10) {
1177 $description = $cummul;
1178 }
1179}
1180#
1181# If all else fails, just take the first paragraph of the
1182# readme file
1183#
1184sub guess_description_from_readme {
1185 my ($file) = @_;
1186
1187 my $state = 0;
1188 my $cummul = "";
1189
1190 open(FILE, $file);
1191 while (<FILE>) {
1192 my $line = $_;
1193 if ($state == 1 && $line =~ /^\n/ && length($cummul) > 80) {
1194 $state = 2;
1195 }
1196 if ($state == 0 && length($line)>1) {
1197 $state = 1;
1198 }
1199 if ($state == 1) {
1200 $cummul = $cummul . $line;
1201 }
1202 if ($line =~ /(http\:\/\/.*$name.*\.org)/) {
1203 my $u = $1;
1204 if ($u =~ /bug/ || length($url) > 1) {
1205 } else {
1206 $url = $u;
1207 }
1208 }
1209 }
1210 close(FILE);
1211 if (length($cummul) > 4 && length($description)<3) {
1212 $description = $cummul;
1213 }
1214}
1215
1216#
1217# Glue all the guesses together
1218#
1219sub guess_description {
1220 my ($directory) = @_;
1221
1222
1223 @files = <$directory/README*>;
1224 foreach (@files) {
1225 guess_description_from_readme($_);
1226 }
1227
1228 if (length($name)>2) {
1229 guess_description_from_freshmeat($name);
1230 }
1231
1232 @files = <$directory/*.spec*>;
1233 foreach (@files) {
1234 guess_description_from_spec($_);
1235 }
1236
1237 guess_description_from_debian_control($directory);
1238
1239 $name =~ s/ //g;
1240 @files = <$directory/$name.pc*>;
1241 foreach (@files) {
1242 guess_description_from_pkgconfig($_);
1243 }
1244 @files = <$directory/*.pc.*>;
1245 foreach (@files) {
1246 guess_description_from_pkgconfig($_);
1247 }
1248 @files = <$directory/*.pc>;
1249 foreach (@files) {
1250 guess_description_from_pkgconfig($_);
1251 }
1252 @files = <$directory/*.doap>;
1253 foreach (@files) {
1254 guess_description_from_doap($_);
1255 }
1256
1257 if (length($summary) < 2) {
1258 $summary = $description;
1259 $summary =~ s/\n/ /g;
1260 $summary =~ s/\s+/ /g;
1261 if ($summary =~ /(.*?)\./) {
1262 $summary = $1;
1263 }
1264 }
1265
1266}
1267
1268# end of Description / Summary section
1269#
1270######################################################################
1271
1272
1273
1274#
1275# Build the package, and wait for rpm to complain about unpackaged
1276# files.... which we then use as basis for our %files section
1277#
1278sub guess_files_from_rpmbuild {
1279 my $infiles = 0;
1280 open(OUTPUTF, "rpmbuild --nodeps --define \"\%_sourcedir $orgdir \" -ba $name.spec 2>&1 |");
1281 while (<OUTPUTF>) {
1282 my $line2 = $_;
1283
1284 if ($infiles == 1 && $line2 =~ /RPM build errors/) {
1285 $infiles = 2;
1286 }
1287 if ($infiles == 1 && $line2 =~ /^Building/) {
1288 $infiles = 2;
1289 }
1290
1291 if ($infiles == 1) {
1292 $line2 =~ s/\s*//g;
1293 push(@allfiles, $line2);
1294 }
1295 if ($line2 =~ / Installed \(but unpackaged\) file\(s\) found\:/) {
1296 $infiles = 1;
1297 }
1298 }
1299 close(OUTPUTF);
1300 if (@allfiles == 0) {
1301 print "Build failed ... stopping here.\n";
1302 exit(0);
1303 }
1304
1305}
1306
1307sub guess_files_from_oscbuild {
1308 my $infiles = 0;
1309 my $restart = 0;
1310 my $mustrestart = 0;
1311 my $rcount = 0;
1312 my $done_python = 0;
1313
1314 system("osc addremove &> /dev/null");
1315 system("osc ci -m \"Initial import by autospectacle\" &> /dev/null");
1316
1317retry:
1318 if ($restart > 0) {
1319 write_yaml();
1320 print "Restarting the build\n";
1321 }
1322 $restart = 0;
1323 $infiles = 0;
1324 $mustrestart = 0;
1325 open(OUTPUTF, "osc build --no-verify $name.spec 2>&1 |");
1326 while (<OUTPUTF>) {
1327 my $line2 = $_;
1328
1329# print "line is $line2\n";
1330 if ($infiles == 1 && $line2 =~ /RPM build errors/) {
1331 $infiles = 2;
1332 }
1333 if ($infiles == 1 && $line2 =~ /^Building/) {
1334 $infiles = 2;
1335 }
1336 if ($infiles == 1) {
1337 $line2 =~ s/\s*//g;
1338 push(@allfiles, $line2);
1339 }
1340 if ($line2 =~ /No package \'(.*)\' found/) {
1341 push_pkgconfig_buildreq("$1");
1342 $restart = $restart + 1;
1343 print " Adding pkgconfig($1) requirement\n";
1344 }
1345 if ($line2 =~ /Package requirements \((.*?)\) were not met/) {
1346 $pkg = $1;
1347 # deal with versioned pkgconfig's by removing the spaces around >= 's
1348 $pkg =~ s/\>\=\s/\>\=/g;
1349 $pkg =~ s/\s\>\=/\>\=/g;
1350 $pkg =~ s/\=\s/\=/g;
1351 $pkg =~ s/\s\=/\=/g;
1352 my @req = split(/ /,$pkg);
1353 foreach (@req) {
1354 push_pkgconfig_buildreq("$_");
1355
1356 $restart = $restart + 1;
1357 print " Adding pkgconfig($_) requirement\n";
1358 }
1359 }
1360 if ($line2 =~ /which: no qmake/) {
1361 $restart += 1;
1362 push_pkgconfig_buildreq("Qt");
1363 print " Adding Qt requirement\n";
1364 }
1365 if ($line2 =~ /Cannot find development files for any supported version of libnl/) {
1366 $restart += 1;
1367 push_pkgconfig_buildreq("libnl-1");
1368 print " Adding libnl requirement\n";
1369 }
1370 if ($line2 =~ /<http:\/\/www.cmake.org>/) {
1371 $restart += 1;
1372 push(@buildreqs, "cmake");
1373 print " Adding cmake requirement\n";
1374 }
1375 if ($line2 =~ /checking for (.*?)\.\.\. not_found/ || $line2 =~ /checking for (.*?)\.\.\. no/ || $line2 =~ /checking (.*?)\.\.\. no/) {
1376 $pkg = $1;
1377 while (($key,$value) = each %failed_commands) {
1378 if ($pkg eq $key) {
1379 push(@buildreqs, $value);
1380 print " Adding $value requirement\n";
1381 $restart += $restart + 1;
1382 $mustrestart = 1;
1383 }
1384 }
1385
1386 }
1387
1388 if ($line2 =~ /checking for [a-zA-Z0-9\_]+ in (.*?)\.\.\. no/) {
1389 $pkg = $1;
1390 while (($key,$value) = each %failed_libs) {
1391 if ($pkg eq $key) {
1392 push(@buildreqs, $value);
1393 print " Adding $value requirement\n";
1394 $restart += $restart + 1;
1395 $mustrestart = 1;
1396 }
1397 }
1398
1399 }
1400
1401 if ($line2 =~ /-- Could NOT find ([a-zA-Z0-9]+)/) {
1402 $pkg = $1;
1403 while (($key,$value) = each %failed_libs) {
1404 if ($pkg eq $key) {
1405 push(@buildreqs, $value);
1406 print " Adding $value requirement\n";
1407 $restart += $restart + 1;
1408 $mustrestart = 1;
1409 }
1410 }
1411
1412 }
1413
1414 if ($line2 =~ /fatal error\: (.*)\: No such file or directory/) {
1415 $pkg = $1;
1416 while (($key,$value) = each %failed_headers) {
1417 if ($pkg eq $key) {
1418 push_pkgconfig_buildreq($value);
1419 print " Adding $value requirement\n";
1420 $restart += $restart + 1;
1421 }
1422 }
1423
1424 }
1425 if ($line2 =~ /checking for UDEV\.\.\. no/) {
1426 print " Adding pkgconfig(udev) requirement\n";
1427 push_pkgconfig_buildreq("udev");
1428 }
1429 if ($line2 =~ /checking for Apache .* module support/) {
1430 print " Adding pkgconfig(httpd-devel) requirement\n";
1431 push(@buildreqs, "httpd-devel");
1432 if ($rcount < 3) {
1433 $restart = $restart + 1;
1434 }
1435 }
1436 if ($line2 =~ /([a-zA-Z0-9\-\_]*)\: command not found/i) {
1437 my $cmd = $1;
1438 my $found = 0;
1439
1440 while (($key,$value) = each %failed_commands) {
1441 if ($cmd eq $key) {
1442 push(@buildreqs, $value);
1443 print " Adding $value requirement\n";
1444 $restart += $restart + 1;
1445 $mustrestart = 1;
1446 $found = 1;
1447 }
1448 }
1449
1450 if ($found < 1) {
1451 print " Command $cmd not found!\n";
1452 }
1453 }
1454 if ($line2 =~ /checking for.*in -ljpeg... no/) {
1455 push(@buildreqs, "libjpeg-devel");
1456 print " Adding libjpeg-devel requirement\n";
1457 $restart = $restart + 1;
1458 }
1459 if ($line2 =~ /fatal error\: zlib\.h\: No such file or directory/) {
1460 push(@buildreqs, "zlib-devel");
1461 print " Adding zlib-devel requirement\n";
1462 $restart = $restart + 1;
1463 }
1464 if ($line2 =~ /error\: xml2-config not found/) {
1465 push_pkgconfig_buildreq("libxml-2.0");
1466 print " Adding libxml2-devel requirement\n";
1467 $restart = $restart + 1;
1468 }
1469 if ($line2 =~ /checking \"location of ncurses\.h file\"/) {
1470 push(@buildreqs, "ncurses-devel");
1471 print " Adding ncurses-devel requirement\n";
1472 $restart = $restart + 1;
1473 }
1474 if (($line2 =~ / \/usr\/include\/python2\.6$/ || $line2 =~ / to compile python extensions/) && $done_python == 0) {
1475 push(@buildreqs, "python-devel");
1476 print " Adding python-devel requirement\n";
1477 $restart = $restart + 1;
1478 $done_python = 1;
1479 }
1480 if ($line2 =~ /error: must install xorg-macros 1.6/) {
1481 push_pkgconfig_buildreq("xorg-macros");
1482 print " Adding xorg-macros requirement\n";
1483 $restart = $restart + 1;
1484 }
1485 if ($line2 =~ /installing .*?.gmo as [a-zA-Z0-9\-\.\/\_]+?\/([a-zA-Z0-9\-\_\.]+)\.mo$/) {
1486 my $loc = $1;
1487 if ($loc eq $localename) {} else {
1488 print " Changing localename from $localename to $loc\n";
1489 $localename = $loc;
1490 $restart = $restart + 1;
1491 }
1492 }
1493
1494 if ($infiles == 0 && $line2 =~ / Installed \(but unpackaged\) file\(s\) found\:/) {
1495 $infiles = 1;
1496 }
1497 }
1498 close(OUTPUTF);
1499 if (@allfiles == 0 || $mustrestart > 0) {
1500 if ($restart >= 1)
1501 {
1502 $rcount = $rcount + 1;
1503 if ($rcount < 10) {
1504 goto retry;
1505 }
1506 }
1507 print "Build failed ... stopping here.\n";
1508 exit(0);
1509 }
1510
1511}
1512
1513sub process_rpmlint {
1514 my $infiles = 0;
1515
1516
1517 if ($oscmode == 0) {
1518 return;
1519 }
1520
1521 print "Verifying package ....\n";
1522
1523 system("osc addremove &> /dev/null");
1524 system("osc ci -m \"Final import by autospectacle\" &> /dev/null");
1525
1526 open(OUTPUTF, "osc build --no-verify $name.spec 2>&1 |");
1527 while (<OUTPUTF>) {
1528 my $line2 = $_;
1529
1530# print "line is $line2\n";
1531 if ($infiles == 1 && $line2 =~ /RPM build errors/) {
1532 $infiles = 2;
1533 }
1534 if ($infiles == 1 && $line2 =~ /^Building/) {
1535 $infiles = 2;
1536 }
1537 if ($infiles == 1) {
1538 $line2 =~ s/\s*//g;
1539 push(@allfiles, $line2);
1540 }
1541 if ($infiles == 0 && $line2 =~ / Installed \(but unpackaged\) file\(s\) found\:/) {
1542 $infiles = 1;
1543 }
1544 }
1545 close(OUTPUTF);
1546
1547}
1548
1549sub guess_name_from_url {
1550 my ($bigurl) = @_;
1551
1552 @spliturl = split(/\//, $bigurl);
1553 while (@spliturl > 1) {
1554 shift(@spliturl);
1555 }
1556 my $tarfile = $spliturl[0];
1557
1558 # Ensure correct name resolution from .zip&tgz archives
1559 $tarfile =~ s/\.zip/\.tar/;
1560 $tarfile =~ s/\.tgz/\.tar/;
1561 $tarfile =~ s/\_/\-/g;
1562 if ($tarfile =~ /(.*?)\-([0-9\.\-\~]+.*?)\.tar/) {
1563 $name = $1;
1564 $version = $2;
1565 $version =~ s/\-/\_/g;
1566 }
1567}
1568
1569############################################################################
1570#
1571# Output functions
1572#
1573
1574sub print_name_and_description
1575{
1576 my @lines;
1577
1578 print OUTFILE "Name : $name\n";
1579 print OUTFILE "Version : $version\n";
1580 print OUTFILE "Release : 1\n";
1581
1582 # remove dupes
1583 undef %saw;
1584 @saw{@groups} = ();
1585 @out = sort keys %saw;
1586
1587 if (@out == 1) {
1588 foreach (@out) {
1589 print OUTFILE "Group : $_\n";
1590 }
1591 } else {
1592 print OUTFILE "Group : $group\n";
1593 }
1594 #
1595 # Work around spectacle bug
1596 $summary =~ s/\:\s/ /g;
1597 $summary =~ s/^([a-z])/\u$1/ig;
1598 $summary =~ s/\@//g;
1599 $summary = substr($summary, 0, 79);
1600
1601 $summary =~ s/\.^//g;
1602 if (length($summary) < 1) {
1603 $summary = "TO BE FILLED IN";
1604 }
1605 #
1606 print OUTFILE "Summary : $summary\n";
1607 print OUTFILE "Description: |\n";
1608
1609 $description =~ s/&quot;/\"/g;
1610 $description =~ s/\@//g;
1611 @lines = split(/\n/, $description);
1612 foreach (@lines) {
1613 print OUTFILE " $_\n";
1614 }
1615 if (length($url)>1) {
1616 print OUTFILE "URL : $url\n";
1617 }
1618
1619 # remove dupes
1620 undef %saw;
1621 @saw{@sources} = ();
1622 @out = sort keys %saw;
1623
1624 print OUTFILE "Sources : \n";
1625 foreach (@out) {
1626 $source = $_;
1627 $source =~ s/$version/\%\{version\}/g;
1628
1629 print OUTFILE " - $source\n";
1630 }
1631
1632 if (@patches > 0) {
1633 print OUTFILE "Patches: \n";
1634 foreach (@patches) {
1635 my $patch = $_;
1636 print OUTFILE " - $patch\n";
1637 }
1638 }
1639
1640 print OUTFILE "\n";
1641 if (length($configure)>2) {
1642 print OUTFILE "Configure : $configure\n";
1643 }
1644 if (length($localename) > 2) {
1645 print OUTFILE "LocaleName : $localename\n";
1646 }
1647 if (length($builder) > 2) {
1648 print OUTFILE "Builder : $builder\n";
1649 }
1650}
1651
1652sub write_makefile
1653{
1654 open(MAKEFILE, ">Makefile");
1655
1656 print MAKEFILE "PKG_NAME := $name\n";
1657 print MAKEFILE "SPECFILE = \$(addsuffix .spec, \$(PKG_NAME))\n";
1658 print MAKEFILE "YAMLFILE = \$(addsuffix .yaml, \$(PKG_NAME))\n";
1659 print MAKEFILE "\n";
1660 print MAKEFILE "include /usr/share/packaging-tools/Makefile.common\n";
1661
1662 close(MAKEFILE);
1663}
1664
1665sub write_changelog
1666{
1667 open(CHANGELOG, ">$name.changes");
1668 $date = ` date +"%a %b %d %Y"`;
1669 chomp($date);
1670 print CHANGELOG "* $date - Autospectacle <autospectacle\@meego.com> - $version\n";
1671 print CHANGELOG "- Initial automated packaging\n";
1672 close(CHANGELOG);
1673}
1674
1675sub write_yaml
1676{
1677 open(OUTFILE, ">$name.yaml");
1678 print_name_and_description();
1679 print_license();
1680 print_pkgconfig();
1681 print_buildreq();
1682 print_files();
1683 print_devel();
1684 print_doc();
1685 close(OUTFILE);
1686
1687 write_makefile();
1688 write_changelog();
1689
1690 system("rm $name.spec 2>/dev/null");
1691 system("specify &> /dev/null");
1692 if ($oscmode > 0) {
1693 system("osc addremove");
1694 system("osc ci -m \"Import by autospectacle\" &> /dev/null");
1695 }
1696
1697}
1698
1699sub write_bbfile
1700{
1701 my $curdir = `pwd`;
1702 chomp($curdir);
1703
1704 if ($python == 1) {
1705 $name =~ s/python-//;
1706 $name = lc("python-" . $name);
1707 }
1708
1709 if (-e "$curdir/${name}_$version.bb") {
1710 print "Wont overwrite file:";
1711 print "$curdir/${name}_$version.bb, exiting\n";
1712 return;
1713 }
1714 open(BBFILE, ">${name}_$version.bb");
1715
1716 print BBFILE "SUMMARY = \"$summary\"\n";
1717 print BBFILE "DESCRIPTION = \"$description\"\n";
1718 print BBFILE "HOMEPAGE = \"$homepage\"\n";
1719
1720 if ($python == 1) {
1721 print BBFILE "SRCNAME = \"$summary\"\n";
1722 }
1723
1724 print BBFILE "LICENSE = \"@license\"\n";
1725 print BBFILE "LIC_FILES_CHKSUM = \"";
1726 foreach (keys %lic_files) {
1727 print BBFILE "file://" . basename($_) . ";md5=$lic_files{$_} \\\n";
1728 }
1729 print BBFILE "\"\n\n";
1730
1731 if (@license <= 0) {
1732 print "Can NOT get license from package source files.\n";
1733 print "Please update the LICENSE and LIC_FILES_CHKSUM manually.\n";
1734 }
1735
1736 if (@buildreqs > 0) {
1737 my %saw;
1738 my @out = grep(!$saw{$_}++,@buildreqs);
1739 print BBFILE "DEPENDS = \"@out\"\n\n";
1740 };
1741
1742 if (@rdepends > 0) {
1743 print BBFILE "RDEPENDS_\$\{PN\} += \"";
1744 foreach (@rdepends) {
1745 print BBFILE "$_ \\\n\t";
1746 }
1747 print BBFILE "\"\n";
1748 }
1749
1750 if ($python == 1) {
1751 print BBFILE "PV = \"$pversion\"\n\n";
1752 }
1753
1754 print BBFILE "SRC_URI = \"";
1755 foreach (@sources) {
1756 print BBFILE "$_ \\\n";
1757 }
1758 print BBFILE "\"\n\n";
1759 print BBFILE "SRC_URI[md5sum] = \"$md5sum\"\n";
1760 print BBFILE "SRC_URI[sha256sum] = \"$sha256sum\"\n\n";
1761 if ($python == 1) {
1762 print BBFILE "S = \"\${WORKDIR}/\${SRCNAME}-\${PV}\"\n";
1763 }
1764
1765 if (@inherits) {
1766 print BBFILE "inherit ";
1767 foreach (@inherits) {
1768 print BBFILE "$_ ";
1769 }
1770 print BBFILE "\n";
1771 }
1772
1773 close(BBFILE);
1774 print "Create bb file: $curdir/${name}_$version.bb\n";
1775}
1776
1777sub calculate_sums
1778{
1779 @_ = basename $dir;
1780 my $md5output = `md5sum @_`;
1781 $md5output =~ /^([a-zA-Z0-9]*) /;
1782 $md5sum = $1;
1783 chomp($md5sum);
1784 my $sha256output = `sha256sum @_`;
1785 $sha256output =~ /^([a-zA-Z0-9]*) /;
1786 $sha256sum = $1;
1787 chomp($sha256sum);
1788}
1789
1790
1791############################################################################
1792#
1793# Main program
1794#
1795
1796if ( @ARGV < 1 || $ARGV[0] eq "--help" ) {
1797 print "Usage: $0 [-r] <url-of-source-tarballs>\n";
1798 exit(1);
1799}
1800
1801# Recusive parsing of python dependencies using
1802# easy_install
1803my $recurse_python = 0;
1804if ($ARGV[0] eq "-r") {
1805 $recurse_python = 1;
1806 shift @ARGV;
1807}
1808
1809if (@ARGV > 1) {
1810 my $i = 1;
1811 while ($i < @ARGV) {
1812 my $patch = $ARGV[$i];
1813 print "Adding patch $patch\n";
1814 push(@patches, $patch);
1815 $i++;
1816 }
1817}
1818
1819setup_licenses();
1820setup_files_rules();
1821setup_group_rules();
1822setup_pkgconfig_ban();
1823setup_failed_commands();
1824
1825if (-e ".osc/_packages") {
1826 $oscmode = 1;
1827}
1828
1829my $tmpdir = tempdir();
1830
1831$dir = $ARGV[0];
1832guess_name_from_url($dir);
1833push(@sources, $dir);
1834
1835#system("cd $tmpdir; curl -s -O $dir");
1836$orgdir = `pwd`;
1837chomp($orgdir);
1838my $outputdir = $name;
1839if (! $name) {
1840 $outputdir = basename $dir;
1841}
1842mkpath($outputdir);
1843chdir($outputdir);
1844print "Downloading package: $dir\n";
1845system("wget --quiet $dir") == 0 or die "Download $dir failed.";
1846
1847calculate_sums($outputdir);
1848
1849print "Unpacking to : $tmpdir\n";
1850
1851my @tgzfiles = <$orgdir/$outputdir/*.tgz>;
1852foreach (@tgzfiles) {
1853 my $tgz = basename $_;
1854 my $tar = $tgz;
1855 $tar =~ s/tgz/tar\.gz/g;
1856 $dir =~ s/tgz/tar\.gz/g;
1857 system("mv $orgdir/$outputdir/$tgz $orgdir/$outputdir/$tar");
1858 guess_name_from_url($dir);
1859}
1860
1861#
1862# I really really hate the fact that meego deleted the -a option from tar.
1863# this is a step backwards in time that is just silly.
1864#
1865
1866my @sourcetars = <$orgdir/$outputdir/*\.tar\.bz2 $orgdir/$outputdir/*\.tar\.gz $orgdir/$outputdir/*\.zip>;
1867if (scalar(@sourcetars) == 0) {
1868 print "Can NOT find source tarball. Exiting...\n";
1869 exit (1);
1870}
1871if (defined($sourcetars[0]) and $sourcetars[0] =~ ".*\.tar\.bz2") {
1872 system("cd $tmpdir; tar -jxf $sourcetars[0] &>/dev/null");
1873} elsif (defined($sourcetars[0]) and $sourcetars[0] =~ ".*\.tar\.gz") {
1874 system("cd $tmpdir; tar -zxf $sourcetars[0] &>/dev/null");
1875} elsif (defined($sourcetars[0]) and $sourcetars[0] =~ ".*\.zip") {
1876 system("cd $tmpdir; unzip $sourcetars[0] &>/dev/null");
1877}
1878
1879print "Parsing content ....\n";
1880my @dirs = <$tmpdir/*>;
1881foreach (@dirs) {
1882 $dir = $_;
1883}
1884
1885$fulldir = $dir;
1886
1887if ( -e "$dir/setup.py" ) {
1888 $python = 1;
1889 $tmp_stools = `grep -r setuptools $dir/setup.py`;
1890 if (length($tmp_stools) > 2) {
1891 push(@inherits, "setuptools");
1892 } else {
1893 push(@inherits, "distutils");
1894 }
1895
1896 $templic = `cd $dir; python setup.py --license;`;
1897 $templic =~ s/[\r\n]+//g;
1898 push(@license, $templic);
1899 $summary = `cd $dir; python setup.py --name`;
1900 $summary =~ s/[\r\n]+//g;
1901 $description = `cd $dir; python setup.py --description`;
1902 $description =~ s/[\r\n]+//g;
1903 $homepage = `cd $dir; python setup.py --url`;
1904 $homepage =~ s/[\r\n]+//g;
1905 $pversion = `cd $dir; python setup.py -V`;
1906 $pversion =~ s/[\r\n]+//g;
1907# $findoutput = `cd $dir; python setup.py --requires`;
1908# if (length($findoutput) < 3) {
1909 $findoutput = `find $dir/*.egg-info/ -name "requires.txt" 2>/dev/null`;
1910# }
1911 @findlist = split(/\n/, $findoutput);
1912 foreach (@findlist) {
1913 push(@rawpythondeps, `sed -e '/^\$/d' "$_" | sed '/^\\[/d'`);
1914 chomp(@rawpythondeps);
1915 push(@rdepends, `sed -e 's/python-//g' "$_" | sed '/^\\[/d'`);
1916 chomp(@rdepends);
1917 if ($recurse_python == 1) {
1918 foreach (@rawpythondeps) {
1919 my $ptempdir = tempdir();
1920 $purl = `easy_install -aeb $ptempdir "$_" 2>/dev/null`;
1921 $purl =~ s/#.*//g;
1922 @purllist = $purl =~ m/Downloading (.*:\/\/.*\n)/g;
1923 chomp(@purllist);
1924
1925 # Remove empty lines
1926 @purllist = grep(/\S/, @purllist);
1927
1928 # Recursively create recipes for dependencies
1929 if (@purllist != 0) {
1930 if (fork) {
1931 # Parent, do nothing
1932 } else {
1933 # child, execute
1934 print "Recursively creating recipe for: $purllist[0]\n";
1935 exec("cd .. ; create-recipe -r $purllist[0]");
1936 }
1937 }
1938 }
1939 wait;
1940 }
1941
1942 foreach $item (@rdepends) {
1943 @pyclean = split(/(\=|\<|\>).*/, $item);
1944 if (defined($pyclean[0])) {
1945 $item = lc("python-" . $pyclean[0]);
1946 }
1947 }
1948 }
1949}
1950
1951if ( -e "$dir/autogen.sh" ) {
1952 $configure = "autogen";
1953 $uses_configure = 1;
1954 push(@inherits, "autotools");
1955}
1956if ( -e "$dir/BUILD-CMAKE" ) {
1957 $configure = "cmake";
1958 push(@buildreqs, "cmake");
1959 $uses_configure = 1;
1960 push(@inherits, "cmake");
1961}
1962
1963if ( -e "$dir/configure" ) {
1964 $configure = "";
1965}
1966
1967my @files = <$dir/configure\.*>;
1968
1969my $findoutput = `find $dir -name "configure.ac" 2>/dev/null`;
1970my @findlist = split(/\n/, $findoutput);
1971foreach (@findlist) {
1972 push(@files, $_);
1973}
1974foreach (@files) {
1975 process_configure_ac("$_");
1976}
1977
1978$findoutput = `find $dir -name "*.pro" 2>/dev/null`;
1979@findlist = split(/\n/, $findoutput);
1980foreach (@findlist) {
1981 process_qmake_pro("$_");
1982}
1983
1984if (-e "$dir/$name.pro") {
1985 $builder = "qmake";
1986 push_pkgconfig_buildreq("Qt");
1987 push(@inherits, "qmake2");
1988}
1989
1990#
1991# This is a good place to generate configure.in
1992#
1993if (length($configure) > 2) {
1994 if ($configure eq "autogen") {
1995 system("cd $dir ; ./autogen.sh &> /dev/null");
1996 }
1997}
1998
1999
2000@files = <$dir/configure>;
2001foreach (@files) {
2002 process_configure("$_");
2003}
2004
2005if ($uses_configure == 0) {
2006 $configure = "none";
2007}
2008
2009@files = <$dir/docs/license.txt>;
2010foreach (@files) {
2011 guess_license_from_file("$_");
2012}
2013
2014@files = <$dir/COPY*>;
2015foreach (@files) {
2016 guess_license_from_file("$_");
2017}
2018
2019@files = <$dir/LICENSE*>;
2020foreach (@files) {
2021 guess_license_from_file("$_");
2022}
2023
2024
2025@files = <$dir/GPL*>;
2026foreach (@files) {
2027 guess_license_from_file("$_");
2028}
2029
2030
2031if ($python != 1) {
2032 guess_description($dir);
2033}
2034
2035#
2036# Output of bbfile file
2037#
2038write_bbfile();
2039chdir($orgdir);
2040exit 0;
2041
2042#
2043# Output of the yaml file
2044#
2045
2046
2047if ($oscmode == 1) {
2048 print "Creating OBS project $name ...\n";
2049 system("osc mkpac $name &> /dev/null");
2050 system("mkdir $name &> /dev/null");
2051 chdir($name);
2052 system("mv ../$name*\.tar\.* .");
2053}
2054
2055write_yaml();
2056print "Building package ....\n";
2057
2058if ($oscmode == 0) {
2059 guess_files_from_rpmbuild();
2060} else {
2061 guess_files_from_oscbuild();
2062}
2063
2064apply_files_rules();
2065
2066$printed_subpackages = 0;
2067write_yaml();
2068
2069process_rpmlint();
2070
2071print "Spectacle creation complete.\n";