Added ocaml-findlib for cross-compiler environment.
[fedora-mingw.git] / show-build-order.pl
1 #!/usr/bin/perl -w
2 #
3 # Show the order to build Fedora MinGW spec files.
4 # By Richard Jones <rjones@redhat.com>
5
6 use strict;
7
8 my $debug = 0;
9 chomp (my $pwd = `pwd`);
10
11 sub main {
12     my %br;
13     my $specfile;
14     my $packagename;
15
16     my @specfiles = <*/*.spec>;
17
18     # Get BRs for each specfile.
19     foreach $specfile (@specfiles) {
20         $packagename = $specfile;
21         $packagename =~ s{^.*/}{};
22         $packagename =~ s{\.spec$}{};
23
24         $br{$packagename} = [];
25
26         open SPEC,$specfile or die "$specfile: $!";
27         while (<SPEC>) {
28             if (m/^BuildRequires:(.*)/) {
29                 my $brs = $1;
30                 my @brs = eval 'split /,/, $brs';
31                 @brs = map { trim ($_) } @brs;
32                 @brs = map { remove_trailers ($_) } @brs;
33                 unshift @{$br{$packagename}}, @brs;
34             }
35         }
36
37         if ($debug) {
38             print "BRs for $packagename = [";
39             print (join "],[", @{$br{$packagename}});
40             print "]\n";
41         }
42     }
43
44     foreach $packagename (keys %br) {
45         my @brs = @{$br{$packagename}};
46         @brs = uniq (sort @brs);
47         $br{$packagename} = \@brs;
48
49         if ($debug) {
50             print "uniq BRs for $packagename = [";
51             print (join "],[", @{$br{$packagename}});
52             print "]\n";
53         }
54     }
55
56     # Some packages we want to ignore for now.
57     delete $br{"mingw32-cyrus-sasl"};
58     delete $br{"mingw32-wix"};
59     delete $br{"mingw32-example"};
60     delete $br{"mingw32-gdb"};
61     delete $br{"mingw32-python"};
62     delete $br{"mingw32-pidgin"};
63     delete $br{"mingw32-nspr"};
64     delete $br{"mingw32-nss"};
65
66     # There is a dependency loop (gcc -> runtime/w32api -> gcc)
67     # which has to be manually resolved below.  Break that loop.
68     my @gcc_brs = @{$br{"mingw32-gcc"}};
69     @gcc_brs = grep { $_ ne "mingw32-runtime" && $_ ne "mingw32-w32api" } @gcc_brs;
70     $br{"mingw32-gcc"} = \@gcc_brs;
71
72     # Use tsort to generate a topological ordering.
73     open TSORT,">/tmp/tsort.tmp" or die "/tmp/tsort.tmp: $!";
74     foreach $packagename (keys %br) {
75         my $br;
76         foreach $br (@{$br{$packagename}}) {
77             print "writing $br $packagename\n" if $debug;
78             print TSORT $br, " ", $packagename, "\n";
79         }
80     }
81     close TSORT;
82
83     system ("tsort < /tmp/tsort.tmp > /tmp/tsort2.tmp") == 0
84         or die "system: tsort: $?";
85
86     # Read in list of packages.
87     open PACKAGES,"/tmp/tsort2.tmp" or die "/tmp/tsort2.tmp: $!";
88     unless ($debug) {
89         unlink "/tmp/tsort.tmp";
90         unlink "/tmp/tsort2.tmp";
91     }
92
93     my %installed;
94
95     while (<PACKAGES>) {
96         chomp;
97         if (/^mingw32-(.*)/ && exists $br{$_}) {
98             $packagename = $_;
99             my $dirname = $1;
100
101             print "considering $packagename\n" if $debug;
102
103             my @brs = @{$br{$packagename}};
104
105             # Are all BR RPMs installed?
106             my $br;
107             foreach $br (@brs) {
108                 if (! rpm_installed ($br) && !exists $installed{$br}) {
109                     print "# as root: rpm -Uvh $br*.rpm\n";
110                     $installed{$br} = 1;
111                 }
112             }
113
114             # Special case for mingw32-gcc deps.
115             if ($packagename eq "mingw32-gcc" &&
116                 (!rpm_installed ("mingw32-runtime") ||
117                  !rpm_installed ("mingw32-w32api"))) {
118                 print "rpmbuild -ba --define \"_sourcedir $pwd/runtime-bootstrap\" runtime-bootstrap/mingw32-runtime-bootstrap.spec\n";
119                 print "# as root: rpm -Uvh mingw32-runtime-bootstrap*.rpm\n";
120                 $installed{"mingw32-runtime-bootstrap"} = 1;
121
122                 print "rpmbuild -ba --define \"_sourcedir $pwd/w32api-bootstrap\" w32api-bootstrap/mingw32-w32api-bootstrap.spec\n";
123                 print "# as root: rpm -Uvh mingw32-w32api-bootstrap*.rpm\n";
124                 $installed{"mingw32-w32api-bootstrap"} = 1;
125             }
126
127             # Spec file.
128             my $specfile = "$dirname/$packagename.spec";
129             die "$specfile: file missing" unless -f $specfile;
130
131             my $rpmbuild =
132                 "rpmbuild -ba --define \"_sourcedir $pwd/$dirname\"";
133             print "$rpmbuild $specfile\n";
134         }
135     }
136 }
137
138 sub rpm_installed {
139     local $_ = shift;
140     return (system ("rpm -q $_ > /dev/null") == 0);
141 }
142
143 sub trim {
144     local $_ = shift;
145     s/^\s+//;
146     s/\s+$//;
147     return $_;
148 }
149
150 sub uniq {
151     my %hash;
152     local $_;
153
154     $hash{$_} = 1 foreach (@_);
155     return sort keys %hash;
156 }
157
158 # foo >= 3.1 --> foo
159 # foo-devel --> foo
160 # and a few other exceptions
161 sub remove_trailers {
162     local $_ = shift;
163     s/\s*[<>=].*$//;
164
165     # -devel & -doc come from the base package.
166     s/-devel$//;
167     s/-doc$//;
168
169     # mingw32-gcc-c++ etc.
170     s/^mingw32-gcc-.*/mingw32-gcc/;
171
172     return $_;
173 }
174
175 &main()