update tizen version to tizen20221207
[tools/build.git] / expanddeps
1 #!/usr/bin/perl -w
2
3 ################################################################
4 #
5 # Copyright (c) 1995-2014 SUSE Linux Products GmbH
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License version 2 or 3 as
9 # published by the Free Software Foundation.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program (see the file COPYING); if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 #
21 ################################################################
22
23 BEGIN {
24   unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
25 }
26
27 use strict;
28
29 use Build;
30 use File::Basename;
31
32 my ($dist, $rpmdeps, $archs, $configdir, $useusedforbuild, $installonly, $noinstall, $usehigherdeps, $isvm);
33
34 $configdir = ($::ENV{'BUILD_DIR'} || '/usr/lib/build') . '/configs';
35
36 while (@ARGV)  {
37   if ($ARGV[0] eq '--dist') {
38     shift @ARGV;
39     $dist = shift @ARGV;
40     next;
41   }
42   if ($ARGV[0] eq '--depfile') {
43     shift @ARGV;
44     $rpmdeps = shift @ARGV;
45     next;
46   }
47   if ($ARGV[0] eq '--archpath') {
48     shift @ARGV;
49     $archs = shift @ARGV;
50     next;
51   }
52   if ($ARGV[0] eq '--configdir') {
53     shift @ARGV;
54     $configdir = shift @ARGV;
55     next;
56   }
57   if ($ARGV[0] eq '--useusedforbuild') {
58     shift @ARGV;
59     $useusedforbuild = 1;
60     next;
61   }
62   if ($ARGV[0] eq '--define') {
63     shift @ARGV;
64     my $def = shift @ARGV;
65     Build::define($def);
66     next;
67   }
68   if ($ARGV[0] eq '--with') {
69     shift @ARGV;
70     my $def = shift @ARGV;
71     Build::define("_with_$def --with-$def");
72     next;
73   }
74   if ($ARGV[0] eq '--without') {
75     shift @ARGV;
76     my $def = shift @ARGV;
77     Build::define("_without_$def --without-$def");
78     next;
79   }
80   if ($ARGV[0] eq '--usehigherdeps') {
81     shift @ARGV;
82     $usehigherdeps = 1;
83     next;
84   }
85   if ($ARGV[0] eq '--vm') {
86     shift @ARGV;
87     $isvm = 1;
88     next;
89   }
90   last;
91 }
92
93 $archs = '' unless defined $archs;
94 die("you must specfiy a depfile!\n") unless defined $rpmdeps;
95
96 # split args in recipe and pkgnames
97 my $recipe;
98 my @extradeps;
99 for my $arg (@ARGV) {
100   my $buildtype = Build::recipe2buildtype($arg);
101   if ($buildtype) {
102     die("can only work with at most one recipe file\n") if defined $recipe;
103     $recipe = $arg;
104   } else {
105     push @extradeps, $arg;
106   }
107 }
108
109 my $binarytype;
110 my @archs = split(':', $archs);
111 if ($recipe && $recipe =~ /(^|\/)PKGBUILD$/) {
112   push @archs, 'any' unless grep {$_ eq 'any'} @archs;
113   $binarytype = 'arch';
114 } elsif ($recipe && $recipe =~ /\.dsc$/) {
115   push @archs, 'all' unless grep {$_ eq 'noarch'} @archs;
116   $binarytype = 'deb';
117 } else {
118   push @archs, 'noarch' unless grep {$_ eq 'noarch'} @archs;
119   $binarytype = 'rpm';
120 }
121
122 # read dist if we can
123 my $cf;
124 if (defined($dist) && $dist ne '') {
125   $cf = Build::read_config_dist($dist, $archs[0] || 'noarch', $configdir);
126   $binarytype = $cf->{'binarytype'} if $cf->{'binarytype'} && $cf->{'binarytype'} ne 'UNDEFINED';
127 }
128
129 my (%fn, %prov, %req, %con, %obs, %rec, %sup);
130
131 my %packs;
132 my %repo;
133 my %ids;
134
135 my %packs_arch;
136 my %packs_done;
137
138 # XXX: move to separate tool
139 if (!defined($dist) || $dist eq '') {
140   my $rpmarch = (grep {$fn{"rpm.$_"}} @archs)[0];
141   if (!$rpmarch) {
142     $dist = 'default';
143   } else {
144     my $rpmfn = $fn{"rpm.$rpmarch"};
145     if ($rpmfn =~ /^[a-z]+:\/\//) {
146       require File::Temp;
147       my $tmpdir = File::Temp::tempdir('CLEANUP' => 1);
148       $rpmfn =~ s/.*\//$tmpdir\// unless system("$INC[0]/download", $tmpdir, $rpmfn);
149     }
150     my $rpmdist = '';
151     if ($rpmfn =~ /^\// && -e $rpmfn) {
152       my %res = Build::Rpm::rpmq($rpmfn, 1010);
153       $rpmdist = $res{1010}->[0] || '';
154     }
155     $dist = Build::dist_canon($rpmdist, $archs[0]);
156     # need some extra work for sles11 :(
157     if ($dist =~ /^sles11-/) {
158       my %res = Build::Rpm::rpmq($rpmfn, 1049);
159       $dist =~ s/^sles11-/sles11sp2-/ if grep {/^liblzma/} @{$res{1049} || []};
160     }
161   }
162   print STDERR "Warning: distribution not specified, assuming '$dist' (see $configdir).\n";
163 }
164
165 $cf ||= Build::read_config_dist($dist, $archs[0] || 'noarch', $configdir);
166 $cf->{'warnings'} = 1;
167
168 my $dofileprovides = %{$cf->{'fileprovides'}};
169
170 my %exportfilters = %{$cf->{'exportfilter'}};
171
172 open(F, '<', $rpmdeps) || die("$rpmdeps: $!\n");
173 # WARNING: the following code assumes that the 'I' tag comes last
174 my ($pkgF, $pkgP, $pkgR, $pkgC, $pkgO, $pkgr, $pkgs);
175
176 my $verscmp = \&Build::Rpm::verscmp;
177
178 if ($binarytype && $binarytype eq 'deb') {
179   $verscmp = \&Build::Deb::verscmp;
180   for my $arch (@archs) {
181     $arch = Build::Deb::basearch($arch) unless $arch =~ /^i[456]86$/;
182   }
183 }
184
185 while(<F>) {
186   chomp;
187   if (/^F:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
188     my $pkgname = basename($2);
189     $pkgF = $2;
190         next if $fn{$1};
191         $fn{$1} = $2;
192         my $pack = $1;
193         $pack =~ /^(.*)\.([^\.]+)$/ or die;
194         push @{$packs_arch{$2}}, $1;
195     my $basename = $1;
196     my $arch = $2;
197     for(keys %exportfilters) {
198       next if ($pkgname !~ /$_/);
199       for (@{$exportfilters{$_}}) {
200         my $a = $_;
201         next if ($a eq ".");
202         next if (! grep ($_ eq $a, @archs));
203         $packs{$basename} = "$basename.$arch"
204       }
205     }
206   } elsif (/^P:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
207     $pkgP = $2;
208     next if $prov{$1};
209     $prov{$1} = $2;
210   } elsif (/^R:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
211     $pkgR = $2;
212     next if $req{$1};
213     $req{$1} = $2;
214   } elsif (/^C:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
215     $pkgC = $2;
216     next if $con{$1};
217     $con{$1} = $2;
218   } elsif (/^O:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
219     $pkgO = $2;
220     next if $obs{$1};
221     $obs{$1} = $2;
222   } elsif (/^r:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
223     $pkgr = $2;
224   } elsif (/^s:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
225     $pkgs = $2;
226   } elsif (/^I:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
227     #next if $packs_done{$1};
228    my $r = 0;
229    if ($usehigherdeps) {
230      $r = 1;
231    } else {
232      if ($packs_done{$1}) {
233        undef $pkgF;
234        undef $pkgP;
235        undef $pkgR;
236        undef $pkgC;
237        undef $pkgO;
238        undef $pkgr;
239        undef $pkgs;
240        $r = 0;
241      } else {
242        $r = 1;
243      }
244    }
245
246    next unless ($r);
247     my ($i, $newid) = ($1, $2);
248     undef $i unless !$ids{$i} || $verscmp->($ids{$i}, $newid) < 0;
249     undef $i unless defined($pkgF) && defined($pkgP) && defined($pkgR);
250     if (defined $i) {
251       $i =~ /^(.*)\.([^\.]+)$/ or die;
252       push @{$packs_arch{$2}}, $1;
253       $ids{$i}  = $newid;
254       $fn{$i}   = $pkgF;
255       $prov{$i} = $pkgP;
256       delete $req{$i};
257       delete $rec{$i};
258       delete $con{$i};
259       delete $obs{$i};
260       delete $rec{$i};
261       delete $sup{$i};
262       $req{$i}  = $pkgR if defined $pkgR;
263       $con{$i}  = $pkgC if defined $pkgC;
264       $obs{$i}  = $pkgO if defined $pkgO;
265       $rec{$i}  = $pkgr if defined $pkgr;
266       $sup{$i}  = $pkgs if defined $pkgs;
267     } else {
268        #also need to clean the below values.
269        undef $pkgF;
270        undef $pkgP;
271        undef $pkgR;
272        undef $pkgC;
273        undef $pkgO;
274        undef $pkgr;
275        undef $pkgs;
276        next if $ids{$1};
277        $ids{$1} = $2;
278         }
279     undef $pkgF;
280     undef $pkgP;
281     undef $pkgR;
282     undef $pkgC;
283     undef $pkgO;
284     undef $pkgr;
285     undef $pkgs;
286   } elsif ($_ eq 'D:') {
287     %packs_done = %ids;
288   }
289 }
290 close F;
291
292 for my $arch (@archs) {
293   $packs{$_} ||= "$_.$arch" for @{$packs_arch{$arch} || []};
294 }
295
296
297 for my $pack (keys %packs) {
298   my $r = {};
299   my (@s, $s, @pr, @re, @co, @ob, @rc, @su);
300   @s = split(' ', $prov{$packs{$pack}} || '');
301   while (@s) {
302     $s = shift @s;
303     next if !$dofileprovides && $s =~ /^\//;
304     if ($s =~ /^rpmlib\(/) {
305       splice(@s, 0, 2);
306       next;
307     }
308     push @pr, $s;
309     while (@s && $s[0] =~ /^[\(<=>|]/) {
310       $pr[-1] .= " $s[0] $s[1]";
311       $pr[-1] =~ s/ \((.*)\)/ $1/;
312       $pr[-1] =~ s/(<|>){2}/$1/;
313       splice(@s, 0, 2);
314     }
315   }
316   @s = split(' ', $req{$packs{$pack}} || '');
317   while (@s) {
318     $s = shift @s;
319     next if !$dofileprovides && $s =~ /^\//;
320     if ($s =~ /^rpmlib\(/) {
321       splice(@s, 0, 2);
322       next;
323     }
324     push @re, $s;
325     while (@s && $s[0] =~ /^[\(<=>|]/) {
326       $re[-1] .= " $s[0] $s[1]";
327       $re[-1] =~ s/ \((.*)\)/ $1/;
328       $re[-1] =~ s/(<|>){2}/$1/;
329       splice(@s, 0, 2);
330     }
331   }
332  @s = split(' ', $con{$packs{$pack}} || '');
333  while (@s) {
334    $s = shift @s;
335    next if !$dofileprovides && $s =~ /^\//;
336    push @co, $s;
337    while (@s && $s[0] =~ /^[\(<=>|]/) {
338      $co[-1] .= " $s[0] $s[1]";
339      $co[-1] =~ s/ \((.*)\)/ $1/;
340      $co[-1] =~ s/(<|>){2}/$1/;
341      splice(@s, 0, 2);
342    }
343  }
344  @s = split(' ', $obs{$packs{$pack}} || '');
345  while (@s) {
346    $s = shift @s;
347    next if !$dofileprovides && $s =~ /^\//;
348    push @ob, $s;
349    while (@s && $s[0] =~ /^[\(<=>|]/) {
350      $ob[-1] .= " $s[0] $s[1]";
351      $ob[-1] =~ s/ \((.*)\)/ $1/;
352      $ob[-1] =~ s/(<|>){2}/$1/;
353      splice(@s, 0, 2);
354    }
355  }
356   @s = split(' ', $rec{$packs{$pack}} || '');
357   while (@s) {
358     $s = shift @s;
359     next if !$dofileprovides && $s =~ /^\//;
360     if ($s =~ /^rpmlib\(/) {
361       splice(@s, 0, 2);
362       next;
363     }
364     push @rc, $s;
365     while (@s && $s[0] =~ /^[\(<=>|]/) {
366       $rc[-1] .= " $s[0] $s[1]";
367       $rc[-1] =~ s/ \((.*)\)/ $1/;
368       $rc[-1] =~ s/(<|>){2}/$1/;
369       splice(@s, 0, 2);
370     }
371   }
372   @s = split(' ', $sup{$packs{$pack}} || '');
373   while (@s) {
374     $s = shift @s;
375     next if !$dofileprovides && $s =~ /^\//;
376           if ($s =~ /^rpmlib\(/) {
377         splice(@s, 0, 2);
378             next;
379     }
380     push @su, $s;
381     while (@s && $s[0] =~ /^[\(<=>|]/) {
382       $su[-1] .= " $s[0] $s[1]";
383       $su[-1] =~ s/ \((.*)\)/ $1/;
384       $su[-1] =~ s/(<|>){2}/$1/;
385       splice(@s, 0, 2);
386     }
387   }
388   $r->{'provides'} = \@pr;
389   $r->{'requires'} = \@re;
390   $r->{'conflicts'} = \@co;
391   $r->{'obsoletes'} = \@ob;
392   $r->{'recommends'} = \@rc;
393   $r->{'supplements'} = \@su;
394   $repo{$pack} = $r;
395 }
396
397
398 #######################################################################
399
400 sub print_rpmlist {
401   for (@_) {
402     print "$_ $fn{$packs{$_}}\n";
403     print "rpmid: $_:$ids{$packs{$_}}\n" if exists $ids{$packs{$_}};
404   }
405   print "preinstall: @{$cf->{'preinstall'} || []}\n";
406   print "vminstall: @{$cf->{'vminstall'} || []}\n";
407   print "runscripts: @{$cf->{'runscripts'} || []}\n";
408   print "dist: $dist\n" if defined $dist;
409   print "installonly: $installonly\n" if defined $installonly;
410   print "noinstall: $noinstall\n" if defined $noinstall;
411 }
412
413 if ($useusedforbuild) {
414   die("Need a recipe file for --usedforbuild\n") unless defined $recipe;
415   local *F;
416   open(F, '<', $recipe) || die("$recipe: $!\n");
417   my @usedforbuild;
418   my @buildrequires;
419   while(<F>) {
420     chomp;
421     if (/^#\s*usedforbuild\s*(.*)$/) {
422       push @usedforbuild, split(' ', $1);
423     }
424     if (/^buildrequires:\s*(.*)$/i) {
425       push @buildrequires, split(' ', $1);
426     }
427   }
428   close F;
429   @usedforbuild = @buildrequires unless @usedforbuild;
430   @usedforbuild = Build::unify(@usedforbuild) if @usedforbuild;
431   my @errors;
432   for (@usedforbuild) {
433     push @errors, "package $_ not found" unless $packs{$_} && $fn{$packs{$_}};
434   }
435   if (@errors) {
436     print STDERR "expansion error\n";
437     print STDERR "  $_\n" for @errors;
438     exit(1);
439   }
440   print_rpmlist(@usedforbuild);
441   exit(0);
442 }
443
444 #######################################################################
445 my @packdeps;
446 my $subpacks = [];
447
448 my $buildtype = '';
449 my $extrasysdeps;
450
451 if ($recipe) {
452   my $d = Build::parse($cf, $recipe) || {};
453   $buildtype = Build::recipe2buildtype($recipe) || '';
454   $cf->{'type'} = $buildtype if $buildtype;
455   if ($buildtype eq 'kiwi') {
456     # lets see if this is a product or image build
457     $buildtype = $d->{'imagetype'} && $d->{'imagetype'}->[0] eq 'product' ? 'kiwi-product' : 'kiwi-image';
458     $extrasysdeps = [ grep {/^kiwi-.*:/} @{$d->{'deps'} || []} ];
459   }
460   $subpacks = $d->{'subpacks'};
461   unshift @extradeps, @{$d->{'deps'} || []};
462   if ($d->{'prereqs'}) {
463     my %deps = map {$_ => 1} (@extradeps, @{$d->{'subpacks'} || []});
464     push @extradeps, '--directdepsend--', grep {!$deps{$_} && !/^%/} @{$d->{'prereqs'}};
465   }
466 }
467
468 Build::readdeps($cf, undef, \%repo);
469
470 #######################################################################
471
472 my @sysdeps = Build::get_sysbuild($cf, $buildtype, $extrasysdeps);
473
474 if ($buildtype eq 'kiwi-image' || $buildtype eq 'kiwi-product') {
475   # just use the sysdeps for now, ignore real deps
476   print_rpmlist(@sysdeps);
477   exit(0);
478 }
479
480 push @extradeps, '--ignoreignore--' if @sysdeps;
481 if ($isvm) {
482   push @packdeps, @{$cf->{'vminstall'}};
483 }
484 my @bdeps = Build::get_build($cf, $subpacks, @extradeps);
485
486 if (!shift @bdeps) {
487   print STDERR "expansion error\n";
488   print STDERR "  $_\n" for @bdeps;
489   exit(1);
490 }
491
492 if (@sysdeps) {
493   if (!shift @sysdeps) {
494     print STDERR "expansion error\n";
495     print STDERR "  $_\n" for @sysdeps;
496     exit(1);
497   }
498   my %sysdeps = map {$_ => 1} @sysdeps;
499   my %bdeps = map {$_ => 1} @bdeps;
500   $installonly = join(' ', grep {!$bdeps{$_}} @sysdeps);
501   $noinstall = join(' ', grep {!$sysdeps{$_}} @bdeps);
502   @bdeps = Build::unify(@sysdeps, @bdeps);
503 }
504
505 # make sure all preinstalls are in bdeps;
506 @bdeps = Build::unify(@bdeps, Build::get_preinstalls($cf));
507 @bdeps = Build::unify(@bdeps, Build::get_vminstalls($cf)) if $isvm;
508
509 print_rpmlist(@bdeps);