]>
Commit | Line | Data |
---|---|---|
ddf1847d RL |
1 | {- # -*- Mode: perl -*- |
2 | ||
0ad1d94d RL |
3 | use File::Basename; |
4 | ||
5 | # A cache of objects for which a recipe has already been generated | |
6 | my %cache; | |
ddf1847d RL |
7 | |
8 | # resolvedepends and reducedepends work in tandem to make sure | |
9 | # there are no duplicate dependencies and that they are in the | |
10 | # right order. This is especially used to sort the list of | |
11 | # libraries that a build depends on. | |
186a31e5 RL |
12 | sub extensionlesslib { |
13 | my @result = map { $_ =~ /(\.a)?$/; $` } @_; | |
14 | return @result if wantarray; | |
15 | return $result[0]; | |
16 | } | |
ddf1847d RL |
17 | sub resolvedepends { |
18 | my $thing = shift; | |
186a31e5 | 19 | my $extensionlessthing = extensionlesslib($thing); |
ddf1847d | 20 | my @listsofar = @_; # to check if we're looping |
186a31e5 | 21 | my @list = @{$unified_info{depends}->{$extensionlessthing}}; |
ddf1847d RL |
22 | my @newlist = (); |
23 | if (scalar @list) { | |
24 | foreach my $item (@list) { | |
186a31e5 | 25 | my $extensionlessitem = extensionlesslib($item); |
ddf1847d | 26 | # It's time to break off when the dependency list starts looping |
186a31e5 | 27 | next if grep { extensionlesslib($_) eq $extensionlessitem } @listsofar; |
ddf1847d RL |
28 | push @newlist, $item, resolvedepends($item, @listsofar, $item); |
29 | } | |
30 | } | |
31 | @newlist; | |
32 | } | |
33 | sub reducedepends { | |
34 | my @list = @_; | |
35 | my @newlist = (); | |
36 | while (@list) { | |
37 | my $item = shift @list; | |
186a31e5 | 38 | my $extensionlessitem = extensionlesslib($item); |
ddf1847d | 39 | push @newlist, $item |
186a31e5 | 40 | unless grep { $extensionlessitem eq extensionlesslib($_) } @list; |
ddf1847d RL |
41 | } |
42 | @newlist; | |
43 | } | |
44 | ||
84f38675 RL |
45 | # is_installed checks if a given file will be installed (i.e. they are |
46 | # not defined _NO_INST in build.info) | |
47 | sub is_installed { | |
48 | my $product = shift; | |
49 | if (grep { $product eq $_ } | |
50 | map { (@{$unified_info{install}->{$_}}) } | |
51 | keys %{$unified_info{install}}) { | |
52 | return 1; | |
53 | } | |
54 | return 0; | |
55 | } | |
56 | ||
d4605727 RL |
57 | # dogenerate is responsible for producing all the recipes that build |
58 | # generated source files. It recurses in case a dependency is also a | |
59 | # generated source file. | |
ae4c7450 RL |
60 | sub dogenerate { |
61 | my $src = shift; | |
62 | return "" if $cache{$src}; | |
d4605727 RL |
63 | my $obj = shift; |
64 | my $bin = shift; | |
ae4c7450 RL |
65 | my %opts = @_; |
66 | if ($unified_info{generate}->{$src}) { | |
05a7aee0 RL |
67 | die "$src is generated by Configure, should not appear in build file\n" |
68 | if ref $unified_info{generate}->{$src} eq ""; | |
8d34daf0 | 69 | my $script = $unified_info{generate}->{$src}->[0]; |
ae4c7450 RL |
70 | $OUT .= generatesrc(src => $src, |
71 | generator => $unified_info{generate}->{$src}, | |
8d34daf0 RL |
72 | generator_incs => $unified_info{includes}->{$script}, |
73 | generator_deps => $unified_info{depends}->{$script}, | |
ae4c7450 | 74 | deps => $unified_info{depends}->{$src}, |
d4605727 RL |
75 | incs => [ @{$unified_info{includes}->{$bin}}, |
76 | @{$unified_info{includes}->{$obj}} ], | |
ae4c7450 RL |
77 | %opts); |
78 | foreach (@{$unified_info{depends}->{$src}}) { | |
d4605727 | 79 | dogenerate($_, $obj, $bin, %opts); |
ae4c7450 RL |
80 | } |
81 | } | |
82 | $cache{$src} = 1; | |
83 | } | |
84 | ||
ddf1847d RL |
85 | # doobj is responsible for producing all the recipes that build |
86 | # object files as well as dependency files. | |
87 | sub doobj { | |
88 | my $obj = shift; | |
b23238f9 | 89 | return "" if $cache{$obj}; |
ddf1847d RL |
90 | (my $obj_no_o = $obj) =~ s|\.o$||; |
91 | my $bin = shift; | |
45502bfe | 92 | my %opts = @_; |
ddf1847d RL |
93 | if (@{$unified_info{sources}->{$obj}}) { |
94 | $OUT .= src2obj(obj => $obj_no_o, | |
84f38675 | 95 | product => $bin, |
ddf1847d | 96 | srcs => $unified_info{sources}->{$obj}, |
ae4c7450 | 97 | deps => $unified_info{depends}->{$obj}, |
ddf1847d | 98 | incs => [ @{$unified_info{includes}->{$bin}}, |
45502bfe RL |
99 | @{$unified_info{includes}->{$obj}} ], |
100 | %opts); | |
ae4c7450 RL |
101 | foreach ((@{$unified_info{sources}->{$obj}}, |
102 | @{$unified_info{depends}->{$obj}})) { | |
d4605727 | 103 | dogenerate($_, $obj, $bin, %opts); |
ae4c7450 | 104 | } |
ddf1847d | 105 | } |
b23238f9 | 106 | $cache{$obj} = 1; |
ddf1847d RL |
107 | } |
108 | ||
109 | # dolib is responsible for building libraries. It will call | |
110 | # libobj2shlib is shared libraries are produced, and obj2lib in all | |
111 | # cases. It also makes sure all object files for the library are | |
112 | # built. | |
113 | sub dolib { | |
114 | my $lib = shift; | |
b23238f9 | 115 | return "" if $cache{$lib}; |
84af1bae | 116 | unless ($disabled{shared}) { |
ddf1847d RL |
117 | my %ordinals = |
118 | $unified_info{ordinals}->{$lib} | |
119 | ? (ordinals => $unified_info{ordinals}->{$lib}) : (); | |
120 | $OUT .= libobj2shlib(shlib => $unified_info{sharednames}->{$lib}, | |
121 | lib => $lib, | |
122 | objs => [ map { (my $x = $_) =~ s|\.o$||; $x } | |
2a08d1a0 RL |
123 | (@{$unified_info{sources}->{$lib}}, |
124 | @{$unified_info{shared_sources}->{$lib}}) ], | |
ddf1847d | 125 | deps => [ reducedepends(resolvedepends($lib)) ], |
84f38675 | 126 | installed => is_installed($lib), |
ddf1847d | 127 | %ordinals); |
2110febb | 128 | foreach (@{$unified_info{shared_sources}->{$lib}}) { |
84f38675 | 129 | doobj($_, $lib, intent => "lib", installed => is_installed($lib)); |
2110febb | 130 | } |
ddf1847d RL |
131 | } |
132 | $OUT .= obj2lib(lib => $lib, | |
133 | objs => [ map { (my $x = $_) =~ s|\.o$||; $x } | |
134 | @{$unified_info{sources}->{$lib}} ]); | |
2110febb RL |
135 | foreach (@{$unified_info{sources}->{$lib}}) { |
136 | doobj($_, $lib, intent => "lib"); | |
137 | } | |
b23238f9 | 138 | $cache{$lib} = 1; |
ddf1847d RL |
139 | } |
140 | ||
141 | # doengine is responsible for building engines. It will call | |
5386287c | 142 | # obj2dso, and also makes sure all object files for the library |
ddf1847d RL |
143 | # are built. |
144 | sub doengine { | |
145 | my $lib = shift; | |
b23238f9 | 146 | return "" if $cache{$lib}; |
5386287c RL |
147 | $OUT .= obj2dso(lib => $lib, |
148 | objs => [ map { (my $x = $_) =~ s|\.o$||; $x } | |
2a08d1a0 RL |
149 | (@{$unified_info{sources}->{$lib}}, |
150 | @{$unified_info{shared_sources}->{$lib}}) ], | |
84f38675 RL |
151 | deps => [ resolvedepends($lib) ], |
152 | installed => is_installed($lib)); | |
2110febb RL |
153 | foreach ((@{$unified_info{sources}->{$lib}}, |
154 | @{$unified_info{shared_sources}->{$lib}})) { | |
84f38675 | 155 | doobj($_, $lib, intent => "dso", installed => is_installed($lib)); |
2110febb | 156 | } |
b23238f9 | 157 | $cache{$lib} = 1; |
ddf1847d RL |
158 | } |
159 | ||
160 | # dobin is responsible for building programs. It will call obj2bin, | |
161 | # and also makes sure all object files for the library are built. | |
162 | sub dobin { | |
163 | my $bin = shift; | |
b23238f9 | 164 | return "" if $cache{$bin}; |
ddf1847d RL |
165 | my $deps = [ reducedepends(resolvedepends($bin)) ]; |
166 | $OUT .= obj2bin(bin => $bin, | |
167 | objs => [ map { (my $x = $_) =~ s|\.o$||; $x } | |
168 | @{$unified_info{sources}->{$bin}} ], | |
84f38675 RL |
169 | deps => $deps, |
170 | installed => is_installed($bin)); | |
2110febb | 171 | foreach (@{$unified_info{sources}->{$bin}}) { |
84f38675 | 172 | doobj($_, $bin, intent => "bin", installed => is_installed($bin)); |
2110febb | 173 | } |
b23238f9 | 174 | $cache{$bin} = 1; |
ddf1847d RL |
175 | } |
176 | ||
177 | # dobin is responsible for building scripts from templates. It will | |
178 | # call in2script. | |
179 | sub doscript { | |
180 | my $script = shift; | |
b23238f9 | 181 | return "" if $cache{$script}; |
ddf1847d | 182 | $OUT .= in2script(script => $script, |
84f38675 RL |
183 | sources => $unified_info{sources}->{$script}, |
184 | installed => is_installed($script)); | |
b23238f9 | 185 | $cache{$script} = 1; |
ddf1847d RL |
186 | } |
187 | ||
0ad1d94d RL |
188 | sub dodir { |
189 | my $dir = shift; | |
190 | return "" if !exists(&generatedir) or $cache{$dir}; | |
191 | $OUT .= generatedir(dir => $dir, | |
192 | deps => $unified_info{dirinfo}->{$dir}->{deps}, | |
193 | %{$unified_info{dirinfo}->{$_}->{products}}); | |
194 | $cache{$dir} = 1; | |
195 | } | |
196 | ||
8a67946e RL |
197 | # Start with populating the cache with all the overrides |
198 | %cache = map { $_ => 1 } @{$unified_info{overrides}}; | |
199 | ||
0ad1d94d RL |
200 | # For convenience collect information regarding directories where |
201 | # files are generated, those generated files and the end product | |
202 | # they end up in where applicable. Then, add build rules for those | |
203 | # directories | |
204 | if (exists &generatedir) { | |
205 | my %loopinfo = ( "dso" => [ @{$unified_info{engines}} ], | |
206 | "lib" => [ @{$unified_info{libraries}} ], | |
207 | "bin" => [ @{$unified_info{programs}} ], | |
208 | "script" => [ @{$unified_info{scripts}} ] ); | |
209 | foreach my $type (keys %loopinfo) { | |
210 | foreach my $product (@{$loopinfo{$type}}) { | |
211 | my %dirs = (); | |
212 | my $pd = dirname($product); | |
ec772a81 RL |
213 | |
214 | # We already have a "test" target, and the current directory | |
215 | # is just silly to make a target for | |
216 | $dirs{$pd} = 1 unless $pd eq "test" || $pd eq "."; | |
217 | ||
0ad1d94d RL |
218 | foreach (@{$unified_info{sources}->{$product}}) { |
219 | my $d = dirname($_); | |
ec772a81 RL |
220 | |
221 | # We don't want to create targets for source directories | |
222 | # when building out of source | |
223 | next if ($config{sourcedir} ne $config{builddir} | |
224 | && $d =~ m|^\Q$config{sourcedir}\E|); | |
225 | # We already have a "test" target, and the current directory | |
226 | # is just silly to make a target for | |
227 | next if $d eq "test" || $d eq "."; | |
228 | ||
0ad1d94d RL |
229 | $dirs{$d} = 1; |
230 | push @{$unified_info{dirinfo}->{$d}->{deps}}, $_ | |
231 | if $d ne $pd; | |
232 | } | |
233 | foreach (keys %dirs) { | |
234 | push @{$unified_info{dirinfo}->{$_}->{products}->{$type}}, | |
235 | $product; | |
236 | } | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
4f858293 RL |
241 | # Build mandatory generated headers |
242 | foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); } | |
243 | ||
ddf1847d RL |
244 | # Build all known libraries, engines, programs and scripts. |
245 | # Everything else will be handled as a consequence. | |
f246f90e RL |
246 | foreach (@{$unified_info{libraries}}) { dolib($_); } |
247 | foreach (@{$unified_info{engines}}) { doengine($_); } | |
248 | foreach (@{$unified_info{programs}}) { dobin($_); } | |
249 | foreach (@{$unified_info{scripts}}) { doscript($_); } | |
ddf1847d | 250 | |
0ad1d94d RL |
251 | foreach (sort keys %{$unified_info{dirinfo}}) { dodir($_); } |
252 | ||
ddf1847d RL |
253 | # Finally, should there be any applicable BEGINRAW/ENDRAW sections, |
254 | # they are added here. | |
2110febb | 255 | $OUT .= $_."\n" foreach @{$unified_info{rawlines}}; |
ddf1847d | 256 | -} |