- fix building in btrfs VMs
[platform/upstream/build.git] / expanddeps
1 #!/usr/bin/perl -w
2
3 BEGIN {
4   unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
5 }
6
7 use strict;
8
9 use Build;
10
11 my ($dist, $rpmdeps, $archs, $configdir, $useusedforbuild);
12
13 while (@ARGV)  {
14   if ($ARGV[0] eq '--dist') {
15     shift @ARGV;
16     $dist = shift @ARGV;
17     next;
18   }
19   if ($ARGV[0] eq '--depfile') {
20     shift @ARGV;
21     $rpmdeps = shift @ARGV;
22     next;
23   }
24   if ($ARGV[0] eq '--archpath') {
25     shift @ARGV;
26     $archs = shift @ARGV;
27     next;
28   }
29   if ($ARGV[0] eq '--configdir') {
30     shift @ARGV;
31     $configdir = shift @ARGV;
32     next;
33   }
34   if ($ARGV[0] eq '--useusedforbuild') {
35     shift @ARGV;
36     $useusedforbuild = 1;
37     next;
38   }
39   if ($ARGV[0] eq '--define') {
40     shift @ARGV;
41     my $def = shift @ARGV;
42     Build::define($def);
43     next;
44   }
45   if ($ARGV[0] eq '--with') {
46     shift @ARGV;
47     my $def = shift @ARGV;
48     Build::define("_with_$def --with-$def");
49     next;
50   }
51   if ($ARGV[0] eq '--without') {
52     shift @ARGV;
53     my $def = shift @ARGV;
54     Build::define("_without_$def --without-$def");
55     next;
56   }
57   last;
58 }
59 $configdir = '.' unless defined $configdir;
60 $archs = '' unless defined $archs;
61 die("you must specfiy a depfile!\n") unless defined $rpmdeps;
62
63 my @extradeps = grep {!/(^|\/)(?:PKGBUILD|_preinstallimage)$/ && !/\.(?:spec|dsc|kiwi)$/} @ARGV;
64 my @specs = grep {/(^|\/)(?:PKGBUILD|_preinstallimage)$/ || /\.(?:spec|dsc|kiwi)$/} @ARGV;
65 die("can only work with at most one spec\n") if @specs > 1;
66 my $spec = $specs[0];
67
68 my @archs = split(':', $archs);
69 if ($spec =~ /(^|\/)PKGBUILD$/) {
70   push @archs, 'any' unless grep {$_ eq 'any'} @archs;
71 } else {
72   push @archs, 'noarch' unless grep {$_ eq 'noarch'} @archs;
73 }
74
75 my (%fn, %prov, %req);
76
77 my %packs;
78 my %repo;
79 my %ids;
80
81 my %packs_arch;
82 my %packs_done;
83 open(F, '<', $rpmdeps) || die("$rpmdeps: $!\n");
84 # WARNING: the following code assumes that the 'I' tag comes last
85 my ($pkgF, $pkgP, $pkgR);
86 while(<F>) {
87   chomp;
88   if (/^F:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
89     $pkgF = $2;
90     next if $fn{$1};
91     $fn{$1} = $2;
92     my $pack = $1;
93     $pack =~ /^(.*)\.([^\.]+)$/ or die;
94     push @{$packs_arch{$2}}, $1;
95   } elsif (/^P:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
96     $pkgP = $2;
97     next if $prov{$1};
98     $prov{$1} = $2;
99   } elsif (/^R:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
100     $pkgR = $2;
101     next if $req{$1};
102     $req{$1} = $2;
103   } elsif (/^I:(.*?)-\d+\/\d+\/\d+: (.*)$/) {
104     if ($ids{$1} && !$packs_done{$1} && defined($pkgF) && defined($pkgP) && defined($pkgR)) {
105       my $i = $1;
106       my $oldid = $ids{$1};
107       my $newid = $2;
108       if (Build::Rpm::verscmp($oldid, $newid) < 0) {
109         $ids{$i}  = $newid;
110         $fn{$i}   = $pkgF;
111         $prov{$i} = $pkgP;
112         $req{$i}  = $pkgR;
113       }
114     } else {
115       next if $ids{$1};
116       $ids{$1} = $2;
117     }
118     undef $pkgF;
119     undef $pkgP;
120     undef $pkgR;
121   } elsif ($_ eq 'D:') {
122     %packs_done = %ids;
123   }
124 }
125 close F;
126
127 for my $arch (@archs) {
128   $packs{$_} ||= "$_.$arch" for @{$packs_arch{$arch} || []};
129 }
130
131 # XXX: move to separate tool
132 if (!defined($dist) || $dist eq '') {
133   my $rpmarch = (grep {$fn{"rpm.$_"}} @archs)[0];
134   if (!$rpmarch) {
135     $dist = 'default';
136   } else {
137     my $rpmfn = $fn{"rpm.$rpmarch"};
138     if ($rpmfn =~ /^[a-z]+:\/\//) {
139       require File::Temp;
140       my $tmpdir = File::Temp::tempdir('CLEANUP' => 1);
141       $rpmfn =~ s/.*\//$tmpdir\// unless system("$INC[0]/download", $tmpdir, $rpmfn);
142     }
143     my $rpmdist = '';
144     if ($rpmfn =~ /^\// && -e $rpmfn) {
145       my %res = Build::Rpm::rpmq($rpmfn, 1010);
146       $rpmdist = $res{1010}->[0] || '';
147     }
148     $dist = Build::dist_canon($rpmdist, $archs[0]);
149     # need some extra work for sles11 :(
150     if ($dist =~ /^sles11-/) {
151       my %res = Build::Rpm::rpmq($rpmfn, 1049);
152       $dist =~ s/^sles11-/sles11sp2-/ if grep {/^liblzma/} @{$res{1049} || []};
153     }
154   }
155   print STDERR "Warning: distribution not specified, assuming '$dist' (see $configdir).\n";
156 }
157
158 my $cf = Build::read_config_dist($dist, $archs[0], $configdir);
159 $cf->{'warnings'} = 1;
160
161 my $dofileprovides = %{$cf->{'fileprovides'}};
162
163 for my $pack (keys %packs) {
164   my $r = {};
165   my (@s, $s, @pr, @re);
166   @s = split(' ', $prov{$packs{$pack}} || '');
167   while (@s) {
168     $s = shift @s;
169     next if !$dofileprovides && $s =~ /^\//;
170     if ($s =~ /^rpmlib\(/) {
171       splice(@s, 0, 2);
172       next;
173     }
174     push @pr, $s;
175     splice(@s, 0, 2) if @s && $s[0] =~ /^[<=>]/;
176   }
177   @s = split(' ', $req{$packs{$pack}} || '');
178   while (@s) {
179     $s = shift @s;
180     next if !$dofileprovides && $s =~ /^\//;
181     if ($s =~ /^rpmlib\(/) {
182       splice(@s, 0, 2);
183       next;
184     }
185     push @re, $s;
186     splice(@s, 0, 2) if @s && $s[0] =~ /^[<=>]/;
187   }
188   $r->{'provides'} = \@pr;
189   $r->{'requires'} = \@re;
190   $repo{$pack} = $r;
191 }
192
193
194 #######################################################################
195
196 sub print_rpmlist
197 {
198   for (@_) {
199     print "$_ $fn{$packs{$_}}\n";
200     print "rpmid: $_:$ids{$packs{$_}}\n" if exists $ids{$packs{$_}};
201   }
202   print "preinstall: @{$cf->{'preinstall'} || []}\n";
203   print "vminstall: @{$cf->{'vminstall'} || []}\n";
204   print "cbpreinstall: @{$cf->{'cbpreinstall'} || []}\n"; # preinstall if is_emulator_arch
205   print "cbinstall: @{$cf->{'cbinstall'} || []}\n";       # install if is_emulator_arch
206   print "runscripts: @{$cf->{'runscripts'} || []}\n";
207   print "dist: $dist\n" if defined $dist;
208 }
209
210 if ($useusedforbuild) {
211   die("Need a specfile/dscfile for --usedforbuild\n") unless defined $spec;
212   local *F;
213   open(F, '<', $spec) || die("$spec: $!\n");
214   my @usedforbuild;
215   my @buildrequires;
216   while(<F>) {
217     chomp;
218     if (/^#\s*usedforbuild\s*(.*)$/) {
219       push @usedforbuild, split(' ', $1);
220     }
221     if (/^buildrequires:\s*(.*)$/i) {
222       push @buildrequires, split(' ', $1);
223     }
224   }
225   close F;
226   @usedforbuild = @buildrequires unless @usedforbuild;
227   @usedforbuild = Build::unify(@usedforbuild) if @usedforbuild;
228   my @errors;
229   for (@usedforbuild) {
230     push @errors, "package $_ not found" unless $packs{$_} && $fn{$packs{$_}};
231   }
232   if (@errors) {
233     print STDERR "expansion error\n";
234     print STDERR "  $_\n" for @errors;
235     exit(1);
236   }
237   print_rpmlist(@usedforbuild);
238   exit(0);
239 }
240
241 #######################################################################
242
243 my ($packname, $packvers, $subpacks, @packdeps);
244 $subpacks = [];
245
246 if ($spec) {
247   my $d;
248   if ($spec =~ /\.kiwi$/) {
249     # just set up kiwi root for now
250     $d = {
251       'deps' => [ 'kiwi', 'zypper', 'createrepo', 'squashfs' ],
252       'subpacks' => [],
253     };
254   } else {
255     $d = Build::parse($cf, $spec);
256   }
257   $packname = $d->{'name'};
258   $packvers = $d->{'version'};
259   $subpacks = $d->{'subpacks'};
260   @packdeps = @{$d->{'deps'} || []};
261   push(@packdeps, @{$d->{'prereqs'}}) if $d->{'prereqs'};
262 }
263
264 Build::readdeps($cf, undef, \%repo);
265
266 #######################################################################
267
268 my @bdeps = Build::get_build($cf, $subpacks, @packdeps, @extradeps);
269
270 if (!shift @bdeps) {
271   print STDERR "expansion error\n";
272   print STDERR "  $_\n" for @bdeps;
273   exit(1);
274 }
275
276 print_rpmlist(@bdeps);