1 | package gentemplate;
|
---|
2 |
|
---|
3 | use strict;
|
---|
4 | use warnings;
|
---|
5 | use Carp;
|
---|
6 |
|
---|
7 | use Exporter;
|
---|
8 | use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
|
---|
9 | @ISA = qw(Exporter);
|
---|
10 | @EXPORT = qw(gentemplate);
|
---|
11 |
|
---|
12 | use File::Basename;
|
---|
13 |
|
---|
14 | sub gentemplate {
|
---|
15 | my %opts = @_;
|
---|
16 |
|
---|
17 | my $generator = OpenSSL::GenTemplate->new(%opts);
|
---|
18 |
|
---|
19 | # Build mandatory header file generators
|
---|
20 | foreach (@{$generator->{info}->{depends}->{""}}) { $generator->dogenerate($_); }
|
---|
21 |
|
---|
22 | # Build all known targets, libraries, modules, programs and scripts.
|
---|
23 | # Everything else will be handled as a consequence.
|
---|
24 | foreach (@{$generator->{info}->{targets}}) { $generator->dotarget($_); }
|
---|
25 | foreach (@{$generator->{info}->{libraries}}) { $generator->dolib($_); }
|
---|
26 | foreach (@{$generator->{info}->{modules}}) { $generator->domodule($_); }
|
---|
27 | foreach (@{$generator->{info}->{programs}}) { $generator->dobin($_); }
|
---|
28 | foreach (@{$generator->{info}->{scripts}}) { $generator->doscript($_); }
|
---|
29 | foreach (sort keys %{$generator->{info}->{htmldocs}}) { $generator->dodocs('html', $_); }
|
---|
30 | foreach (sort keys %{$generator->{info}->{mandocs}}) { $generator->dodocs('man', $_); }
|
---|
31 | foreach (sort keys %{$generator->{info}->{dirinfo}}) { $generator->dodir($_); }
|
---|
32 | }
|
---|
33 |
|
---|
34 | package OpenSSL::GenTemplate;
|
---|
35 |
|
---|
36 | use OpenSSL::Util;
|
---|
37 |
|
---|
38 | sub new {
|
---|
39 | my $class = shift;
|
---|
40 | my %opts = @_;
|
---|
41 |
|
---|
42 | my $data = {
|
---|
43 | output => $opts{output},
|
---|
44 | config => $opts{config} // {},
|
---|
45 | disabled => $opts{disabled} // {},
|
---|
46 | info => $opts{unified_info} // {},
|
---|
47 | };
|
---|
48 |
|
---|
49 | return bless $data, $class;
|
---|
50 | };
|
---|
51 |
|
---|
52 | sub emit {
|
---|
53 | my $self = shift;
|
---|
54 | my $name = shift;
|
---|
55 | my %opts = @_;
|
---|
56 | my $fh = $self->{output};
|
---|
57 |
|
---|
58 | die "No name?" unless $name;
|
---|
59 | print $fh "{-\n ", $name, '(', dump_data(\%opts), ');', " \n-}"
|
---|
60 | unless defined $opts{attrs}->{skip};
|
---|
61 | }
|
---|
62 |
|
---|
63 | my $debug_resolvedepends = $ENV{BUILDFILE_DEBUG_DEPENDS};
|
---|
64 | my $debug_rules = $ENV{BUILDFILE_DEBUG_RULES};
|
---|
65 |
|
---|
66 | # A cache of objects for which a recipe has already been generated
|
---|
67 | our %cache;
|
---|
68 |
|
---|
69 | # collectdepends, expanddepends and reducedepends work together to make
|
---|
70 | # sure there are no duplicate or weak dependencies and that they are in
|
---|
71 | # the right order. This is used to sort the list of libraries that a
|
---|
72 | # build depends on.
|
---|
73 | sub extensionlesslib {
|
---|
74 | my @result = map { $_ =~ /(\.a)?$/; $` } @_;
|
---|
75 | return @result if wantarray;
|
---|
76 | return $result[0];
|
---|
77 | }
|
---|
78 |
|
---|
79 | # collectdepends dives into the tree of dependencies and returns
|
---|
80 | # a list of all the non-weak ones.
|
---|
81 | sub collectdepends {
|
---|
82 | my $self = shift;
|
---|
83 | return () unless @_;
|
---|
84 |
|
---|
85 | my $thing = shift;
|
---|
86 | my $extensionlessthing = extensionlesslib($thing);
|
---|
87 | my @listsofar = @_; # to check if we're looping
|
---|
88 | my @list = @{ $self->{info}->{depends}->{$thing} //
|
---|
89 | $self->{info}->{depends}->{$extensionlessthing}
|
---|
90 | // [] };
|
---|
91 | my @newlist = ();
|
---|
92 |
|
---|
93 | print STDERR "DEBUG[collectdepends] $thing > ", join(' ', @listsofar), "\n"
|
---|
94 | if $debug_resolvedepends;
|
---|
95 | foreach my $item (@list) {
|
---|
96 | my $extensionlessitem = extensionlesslib($item);
|
---|
97 | # It's time to break off when the dependency list starts looping
|
---|
98 | next if grep { extensionlesslib($_) eq $extensionlessitem } @listsofar;
|
---|
99 | # Don't add anything here if the dependency is weak
|
---|
100 | next if defined $self->{info}->{attributes}->{depends}->{$thing}->{$item}->{'weak'};
|
---|
101 | my @resolved = $self->collectdepends($item, @listsofar, $item);
|
---|
102 | push @newlist, $item, @resolved;
|
---|
103 | }
|
---|
104 | print STDERR "DEBUG[collectdepends] $thing < ", join(' ', @newlist), "\n"
|
---|
105 | if $debug_resolvedepends;
|
---|
106 | @newlist;
|
---|
107 | }
|
---|
108 |
|
---|
109 | # expanddepends goes through a list of stuff, checks if they have any
|
---|
110 | # dependencies, and adds them at the end of the current position if
|
---|
111 | # they aren't already present later on.
|
---|
112 | sub expanddepends {
|
---|
113 | my $self = shift;
|
---|
114 | my @after = ( @_ );
|
---|
115 | print STDERR "DEBUG[expanddepends]> ", join(' ', @after), "\n"
|
---|
116 | if $debug_resolvedepends;
|
---|
117 | my @before = ();
|
---|
118 | while (@after) {
|
---|
119 | my $item = shift @after;
|
---|
120 | print STDERR "DEBUG[expanddepends]\\ ", join(' ', @before), "\n"
|
---|
121 | if $debug_resolvedepends;
|
---|
122 | print STDERR "DEBUG[expanddepends] - ", $item, "\n"
|
---|
123 | if $debug_resolvedepends;
|
---|
124 | my @middle = (
|
---|
125 | $item,
|
---|
126 | map {
|
---|
127 | my $x = $_;
|
---|
128 | my $extlessx = extensionlesslib($x);
|
---|
129 | if (grep { $extlessx eq extensionlesslib($_) } @before
|
---|
130 | and
|
---|
131 | !grep { $extlessx eq extensionlesslib($_) } @after) {
|
---|
132 | print STDERR "DEBUG[expanddepends] + ", $x, "\n"
|
---|
133 | if $debug_resolvedepends;
|
---|
134 | ( $x )
|
---|
135 | } else {
|
---|
136 | print STDERR "DEBUG[expanddepends] ! ", $x, "\n"
|
---|
137 | if $debug_resolvedepends;
|
---|
138 | ()
|
---|
139 | }
|
---|
140 | } @{$self->{info}->{depends}->{$item} // []}
|
---|
141 | );
|
---|
142 | print STDERR "DEBUG[expanddepends] = ", join(' ', @middle), "\n"
|
---|
143 | if $debug_resolvedepends;
|
---|
144 | print STDERR "DEBUG[expanddepends]/ ", join(' ', @after), "\n"
|
---|
145 | if $debug_resolvedepends;
|
---|
146 | push @before, @middle;
|
---|
147 | }
|
---|
148 | print STDERR "DEBUG[expanddepends]< ", join(' ', @before), "\n"
|
---|
149 | if $debug_resolvedepends;
|
---|
150 | @before;
|
---|
151 | }
|
---|
152 |
|
---|
153 | # reducedepends looks through a list, and checks if each item is
|
---|
154 | # repeated later on. If it is, the earlier copy is dropped.
|
---|
155 | sub reducedepends {
|
---|
156 | my @list = @_;
|
---|
157 | print STDERR "DEBUG[reducedepends]> ", join(' ', @list), "\n"
|
---|
158 | if $debug_resolvedepends;
|
---|
159 | my @newlist = ();
|
---|
160 | my %replace = ();
|
---|
161 | while (@list) {
|
---|
162 | my $item = shift @list;
|
---|
163 | my $extensionlessitem = extensionlesslib($item);
|
---|
164 | if (grep { $extensionlessitem eq extensionlesslib($_) } @list) {
|
---|
165 | if ($item ne $extensionlessitem) {
|
---|
166 | # If this instance of the library is explicitly static, we
|
---|
167 | # prefer that to any shared library name, since it must have
|
---|
168 | # been done on purpose.
|
---|
169 | $replace{$extensionlessitem} = $item;
|
---|
170 | }
|
---|
171 | } else {
|
---|
172 | push @newlist, $item;
|
---|
173 | }
|
---|
174 | }
|
---|
175 | @newlist = map { $replace{$_} // $_; } @newlist;
|
---|
176 | print STDERR "DEBUG[reducedepends]< ", join(' ', @newlist), "\n"
|
---|
177 | if $debug_resolvedepends;
|
---|
178 | @newlist;
|
---|
179 | }
|
---|
180 |
|
---|
181 | # Do it all
|
---|
182 | # This takes multiple inputs and combine them into a single list of
|
---|
183 | # interdependent things. The returned value will include all the input.
|
---|
184 | # Callers are responsible for taking away the things they are building.
|
---|
185 | sub resolvedepends {
|
---|
186 | my $self = shift;
|
---|
187 | print STDERR "DEBUG[resolvedepends] START (", join(', ', @_), ")\n"
|
---|
188 | if $debug_resolvedepends;
|
---|
189 | my @all =
|
---|
190 | reducedepends($self->expanddepends(map { ( $_, $self->collectdepends($_) ) } @_));
|
---|
191 | print STDERR "DEBUG[resolvedepends] END (", join(', ', @_), ") : ",
|
---|
192 | join(',', map { "\n $_" } @all), "\n"
|
---|
193 | if $debug_resolvedepends;
|
---|
194 | @all;
|
---|
195 | }
|
---|
196 |
|
---|
197 | # dogenerate is responsible for producing all the recipes that build
|
---|
198 | # generated source files. It recurses in case a dependency is also a
|
---|
199 | # generated source file.
|
---|
200 | sub dogenerate {
|
---|
201 | my $self = shift;
|
---|
202 | my $src = shift;
|
---|
203 | # Safety measure
|
---|
204 | return "" unless defined $self->{info}->{generate}->{$src};
|
---|
205 | return "" if $cache{$src};
|
---|
206 | my $obj = shift;
|
---|
207 | my $bin = shift;
|
---|
208 | my %opts = @_;
|
---|
209 | if ($self->{info}->{generate}->{$src}) {
|
---|
210 | die "$src is generated by Configure, should not appear in build file\n"
|
---|
211 | if ref $self->{info}->{generate}->{$src} eq "";
|
---|
212 | my $script = $self->{info}->{generate}->{$src}->[0];
|
---|
213 | my %attrs = %{$self->{info}->{attributes}->{generate}->{$src} // {}};
|
---|
214 | $self->emit('generatesrc',
|
---|
215 | src => $src,
|
---|
216 | product => $bin,
|
---|
217 | generator => $self->{info}->{generate}->{$src},
|
---|
218 | generator_incs => $self->{info}->{includes}->{$script} // [],
|
---|
219 | generator_deps => $self->{info}->{depends}->{$script} // [],
|
---|
220 | deps => $self->{info}->{depends}->{$src} // [],
|
---|
221 | incs => [ defined $obj ? @{$self->{info}->{includes}->{$obj} // []} : (),
|
---|
222 | defined $bin ? @{$self->{info}->{includes}->{$bin} // []} : () ],
|
---|
223 | defs => [ defined $obj ? @{$self->{info}->{defines}->{$obj} // []} : (),
|
---|
224 | defined $bin ? @{$self->{info}->{defines}->{$bin} // []} : () ],
|
---|
225 | attrs => { %attrs },
|
---|
226 | %opts);
|
---|
227 | foreach (@{$self->{info}->{depends}->{$src} // []}) {
|
---|
228 | $self->dogenerate($_, $obj, $bin, %opts);
|
---|
229 | }
|
---|
230 | # The generator itself may be is generated
|
---|
231 | if ($self->{info}->{generate}->{$script}) {
|
---|
232 | $self->dogenerate($script, $obj, $bin, %opts);
|
---|
233 | }
|
---|
234 | }
|
---|
235 | $cache{$src} = 1;
|
---|
236 | }
|
---|
237 |
|
---|
238 | sub dotarget {
|
---|
239 | my $self = shift;
|
---|
240 | my $target = shift;
|
---|
241 | return "" if $cache{$target};
|
---|
242 | $self->emit('generatetarget',
|
---|
243 | target => $target,
|
---|
244 | deps => $self->{info}->{depends}->{$target} // []);
|
---|
245 | foreach (@{$self->{info}->{depends}->{$target} // []}) {
|
---|
246 | $self->dogenerate($_);
|
---|
247 | }
|
---|
248 | $cache{$target} = 1;
|
---|
249 | }
|
---|
250 |
|
---|
251 | # doobj is responsible for producing all the recipes that build
|
---|
252 | # object files as well as dependency files.
|
---|
253 | sub doobj {
|
---|
254 | my $self = shift;
|
---|
255 | my $obj = shift;
|
---|
256 | return "" if $cache{$obj};
|
---|
257 | my $bin = shift;
|
---|
258 | my %opts = @_;
|
---|
259 | if (@{$self->{info}->{sources}->{$obj} // []}) {
|
---|
260 | my @srcs = @{$self->{info}->{sources}->{$obj}};
|
---|
261 | my @deps = @{$self->{info}->{depends}->{$obj} // []};
|
---|
262 | my @incs = ( @{$self->{info}->{includes}->{$obj} // []},
|
---|
263 | @{$self->{info}->{includes}->{$bin} // []} );
|
---|
264 | my @defs = ( @{$self->{info}->{defines}->{$obj} // []},
|
---|
265 | @{$self->{info}->{defines}->{$bin} // []} );
|
---|
266 | print STDERR "DEBUG[doobj] \@srcs for $obj ($bin) : ",
|
---|
267 | join(",", map { "\n $_" } @srcs), "\n"
|
---|
268 | if $debug_rules;
|
---|
269 | print STDERR "DEBUG[doobj] \@deps for $obj ($bin) : ",
|
---|
270 | join(",", map { "\n $_" } @deps), "\n"
|
---|
271 | if $debug_rules;
|
---|
272 | print STDERR "DEBUG[doobj] \@incs for $obj ($bin) : ",
|
---|
273 | join(",", map { "\n $_" } @incs), "\n"
|
---|
274 | if $debug_rules;
|
---|
275 | print STDERR "DEBUG[doobj] \@defs for $obj ($bin) : ",
|
---|
276 | join(",", map { "\n $_" } @defs), "\n"
|
---|
277 | if $debug_rules;
|
---|
278 | print STDERR "DEBUG[doobj] \%opts for $obj ($bin) : ", ,
|
---|
279 | join(",", map { "\n $_ = $opts{$_}" } sort keys %opts), "\n"
|
---|
280 | if $debug_rules;
|
---|
281 | $self->emit('src2obj',
|
---|
282 | obj => $obj, product => $bin,
|
---|
283 | srcs => [ @srcs ], deps => [ @deps ],
|
---|
284 | incs => [ @incs ], defs => [ @defs ],
|
---|
285 | %opts);
|
---|
286 | foreach ((@{$self->{info}->{sources}->{$obj}},
|
---|
287 | @{$self->{info}->{depends}->{$obj} // []})) {
|
---|
288 | $self->dogenerate($_, $obj, $bin, %opts);
|
---|
289 | }
|
---|
290 | }
|
---|
291 | $cache{$obj} = 1;
|
---|
292 | }
|
---|
293 |
|
---|
294 | # Helper functions to grab all applicable intermediary files.
|
---|
295 | # This is particularly useful when a library is given as source
|
---|
296 | # rather than a dependency. In that case, we consider it to be a
|
---|
297 | # container with object file references, or possibly references
|
---|
298 | # to further libraries to pilfer in the same way.
|
---|
299 | sub getsrclibs {
|
---|
300 | my $self = shift;
|
---|
301 | my $section = shift;
|
---|
302 |
|
---|
303 | # For all input, see if it sources static libraries. If it does,
|
---|
304 | # return them together with the result of a recursive call.
|
---|
305 | map { ( $_, getsrclibs($section, $_) ) }
|
---|
306 | grep { $_ =~ m|\.a$| }
|
---|
307 | map { @{$self->{info}->{$section}->{$_} // []} }
|
---|
308 | @_;
|
---|
309 | }
|
---|
310 |
|
---|
311 | sub getlibobjs {
|
---|
312 | my $self = shift;
|
---|
313 | my $section = shift;
|
---|
314 |
|
---|
315 | # For all input, see if it's an intermediary file (library or object).
|
---|
316 | # If it is, collect the result of a recursive call, or if that returns
|
---|
317 | # an empty list, the element itself. Return the result.
|
---|
318 | map {
|
---|
319 | my @x = $self->getlibobjs($section, @{$self->{info}->{$section}->{$_}});
|
---|
320 | @x ? @x : ( $_ );
|
---|
321 | }
|
---|
322 | grep { defined $self->{info}->{$section}->{$_} }
|
---|
323 | @_;
|
---|
324 | }
|
---|
325 |
|
---|
326 | # dolib is responsible for building libraries. It will call
|
---|
327 | # obj2shlib if shared libraries are produced, and obj2lib in all
|
---|
328 | # cases. It also makes sure all object files for the library are
|
---|
329 | # built.
|
---|
330 | sub dolib {
|
---|
331 | my $self = shift;
|
---|
332 | my $lib = shift;
|
---|
333 | return "" if $cache{$lib};
|
---|
334 |
|
---|
335 | my %attrs = %{$self->{info}->{attributes}->{libraries}->{$lib} // {}};
|
---|
336 |
|
---|
337 | my @deps = ( $self->resolvedepends(getsrclibs('sources', $lib)) );
|
---|
338 |
|
---|
339 | # We support two types of objs, those who are specific to this library
|
---|
340 | # (they end up in @objs) and those that we get indirectly, via other
|
---|
341 | # libraries (they end up in @foreign_objs). We get the latter any time
|
---|
342 | # someone has done something like this in build.info:
|
---|
343 | # SOURCE[libfoo.a]=libbar.a
|
---|
344 | # The indirect object files must be kept in a separate array so they
|
---|
345 | # don't get rebuilt unnecessarily (and with incorrect auxiliary
|
---|
346 | # information).
|
---|
347 | #
|
---|
348 | # Object files can't be collected commonly for shared and static
|
---|
349 | # libraries, because we contain their respective object files in
|
---|
350 | # {shared_sources} and {sources}, and because the implications are
|
---|
351 | # slightly different for each library form.
|
---|
352 | #
|
---|
353 | # We grab all these "foreign" object files recursively with getlibobjs().
|
---|
354 |
|
---|
355 | unless ($self->{disabled}->{shared} || $lib =~ /\.a$/) {
|
---|
356 | # If this library sources other static libraries and those
|
---|
357 | # libraries are marked {noinst}, there's no need to include
|
---|
358 | # all of their object files. Instead, we treat those static
|
---|
359 | # libraries as dependents alongside any other library this
|
---|
360 | # one depends on, and let symbol resolution do its job.
|
---|
361 | my @sourced_libs = ();
|
---|
362 | my @objs = ();
|
---|
363 | my @foreign_objs = ();
|
---|
364 | my @deps = ();
|
---|
365 | foreach (@{$self->{info}->{shared_sources}->{$lib} // []}) {
|
---|
366 | if ($_ !~ m|\.a$|) {
|
---|
367 | push @objs, $_;
|
---|
368 | } elsif ($self->{info}->{attributes}->{libraries}->{$_}->{noinst}) {
|
---|
369 | push @deps, $_;
|
---|
370 | } else {
|
---|
371 | push @deps, $self->getsrclibs('sources', $_);
|
---|
372 | push @foreign_objs, $self->getlibobjs('sources', $_);
|
---|
373 | }
|
---|
374 | }
|
---|
375 | @deps = ( grep { $_ ne $lib } $self->resolvedepends($lib, @deps) );
|
---|
376 | print STDERR "DEBUG[dolib:shlib] \%attrs for $lib : ", ,
|
---|
377 | join(",", map { "\n $_ = $attrs{$_}" } sort keys %attrs), "\n"
|
---|
378 | if %attrs && $debug_rules;
|
---|
379 | print STDERR "DEBUG[dolib:shlib] \@deps for $lib : ",
|
---|
380 | join(",", map { "\n $_" } @deps), "\n"
|
---|
381 | if @deps && $debug_rules;
|
---|
382 | print STDERR "DEBUG[dolib:shlib] \@objs for $lib : ",
|
---|
383 | join(",", map { "\n $_" } @objs), "\n"
|
---|
384 | if @objs && $debug_rules;
|
---|
385 | print STDERR "DEBUG[dolib:shlib] \@foreign_objs for $lib : ",
|
---|
386 | join(",", map { "\n $_" } @foreign_objs), "\n"
|
---|
387 | if @foreign_objs && $debug_rules;
|
---|
388 | $self->emit('obj2shlib',
|
---|
389 | lib => $lib,
|
---|
390 | attrs => { %attrs },
|
---|
391 | objs => [ @objs, @foreign_objs ],
|
---|
392 | deps => [ @deps ]);
|
---|
393 | foreach (@objs) {
|
---|
394 | # If this is somehow a compiled object, take care of it that way
|
---|
395 | # Otherwise, it might simply be generated
|
---|
396 | if (defined $self->{info}->{sources}->{$_}) {
|
---|
397 | if($_ =~ /\.a$/) {
|
---|
398 | $self->dolib($_);
|
---|
399 | } else {
|
---|
400 | $self->doobj($_, $lib, intent => "shlib", attrs => { %attrs });
|
---|
401 | }
|
---|
402 | } else {
|
---|
403 | $self->dogenerate($_, undef, undef, intent => "lib");
|
---|
404 | }
|
---|
405 | }
|
---|
406 | }
|
---|
407 | {
|
---|
408 | # When putting static libraries together, we cannot rely on any
|
---|
409 | # symbol resolution, so for all static libraries used as source for
|
---|
410 | # this one, as well as other libraries they depend on, we simply
|
---|
411 | # grab all their object files unconditionally,
|
---|
412 | # Symbol resolution will happen when any program, module or shared
|
---|
413 | # library is linked with this one.
|
---|
414 | my @objs = ();
|
---|
415 | my @sourcedeps = ();
|
---|
416 | my @foreign_objs = ();
|
---|
417 | foreach (@{$self->{info}->{sources}->{$lib}}) {
|
---|
418 | if ($_ !~ m|\.a$|) {
|
---|
419 | push @objs, $_;
|
---|
420 | } else {
|
---|
421 | push @sourcedeps, $_;
|
---|
422 | }
|
---|
423 | }
|
---|
424 | @sourcedeps = ( grep { $_ ne $lib } $self->resolvedepends(@sourcedeps) );
|
---|
425 | print STDERR "DEBUG[dolib:lib] : \@sourcedeps for $_ : ",
|
---|
426 | join(",", map { "\n $_" } @sourcedeps), "\n"
|
---|
427 | if @sourcedeps && $debug_rules;
|
---|
428 | @foreign_objs = $self->getlibobjs('sources', @sourcedeps);
|
---|
429 | print STDERR "DEBUG[dolib:lib] \%attrs for $lib : ", ,
|
---|
430 | join(",", map { "\n $_ = $attrs{$_}" } sort keys %attrs), "\n"
|
---|
431 | if %attrs && $debug_rules;
|
---|
432 | print STDERR "DEBUG[dolib:lib] \@objs for $lib : ",
|
---|
433 | join(",", map { "\n $_" } @objs), "\n"
|
---|
434 | if @objs && $debug_rules;
|
---|
435 | print STDERR "DEBUG[dolib:lib] \@foreign_objs for $lib : ",
|
---|
436 | join(",", map { "\n $_" } @foreign_objs), "\n"
|
---|
437 | if @foreign_objs && $debug_rules;
|
---|
438 | $self->emit('obj2lib',
|
---|
439 | lib => $lib, attrs => { %attrs },
|
---|
440 | objs => [ @objs, @foreign_objs ]);
|
---|
441 | foreach (@objs) {
|
---|
442 | $self->doobj($_, $lib, intent => "lib", attrs => { %attrs });
|
---|
443 | }
|
---|
444 | }
|
---|
445 | $cache{$lib} = 1;
|
---|
446 | }
|
---|
447 |
|
---|
448 | # domodule is responsible for building modules. It will call
|
---|
449 | # obj2dso, and also makes sure all object files for the library
|
---|
450 | # are built.
|
---|
451 | sub domodule {
|
---|
452 | my $self = shift;
|
---|
453 | my $module = shift;
|
---|
454 | return "" if $cache{$module};
|
---|
455 | my %attrs = %{$self->{info}->{attributes}->{modules}->{$module} // {}};
|
---|
456 | my @objs = @{$self->{info}->{sources}->{$module}};
|
---|
457 | my @deps = ( grep { $_ ne $module }
|
---|
458 | $self->resolvedepends($module) );
|
---|
459 | print STDERR "DEBUG[domodule] \%attrs for $module :",
|
---|
460 | join(",", map { "\n $_ = $attrs{$_}" } sort keys %attrs), "\n"
|
---|
461 | if $debug_rules;
|
---|
462 | print STDERR "DEBUG[domodule] \@objs for $module : ",
|
---|
463 | join(",", map { "\n $_" } @objs), "\n"
|
---|
464 | if $debug_rules;
|
---|
465 | print STDERR "DEBUG[domodule] \@deps for $module : ",
|
---|
466 | join(",", map { "\n $_" } @deps), "\n"
|
---|
467 | if $debug_rules;
|
---|
468 | $self->emit('obj2dso',
|
---|
469 | module => $module,
|
---|
470 | attrs => { %attrs },
|
---|
471 | objs => [ @objs ],
|
---|
472 | deps => [ @deps ]);
|
---|
473 | foreach (@{$self->{info}->{sources}->{$module}}) {
|
---|
474 | # If this is somehow a compiled object, take care of it that way
|
---|
475 | # Otherwise, it might simply be generated
|
---|
476 | if (defined $self->{info}->{sources}->{$_}) {
|
---|
477 | $self->doobj($_, $module, intent => "dso", attrs => { %attrs });
|
---|
478 | } else {
|
---|
479 | $self->dogenerate($_, undef, $module, intent => "dso");
|
---|
480 | }
|
---|
481 | }
|
---|
482 | $cache{$module} = 1;
|
---|
483 | }
|
---|
484 |
|
---|
485 | # dobin is responsible for building programs. It will call obj2bin,
|
---|
486 | # and also makes sure all object files for the library are built.
|
---|
487 | sub dobin {
|
---|
488 | my $self = shift;
|
---|
489 | my $bin = shift;
|
---|
490 | return "" if $cache{$bin};
|
---|
491 | my %attrs = %{$self->{info}->{attributes}->{programs}->{$bin} // {}};
|
---|
492 | my @objs = @{$self->{info}->{sources}->{$bin}};
|
---|
493 | my @deps = ( grep { $_ ne $bin } $self->resolvedepends($bin) );
|
---|
494 | print STDERR "DEBUG[dobin] \%attrs for $bin : ",
|
---|
495 | join(",", map { "\n $_ = $attrs{$_}" } sort keys %attrs), "\n"
|
---|
496 | if %attrs && $debug_rules;
|
---|
497 | print STDERR "DEBUG[dobin] \@objs for $bin : ",
|
---|
498 | join(",", map { "\n $_" } @objs), "\n"
|
---|
499 | if @objs && $debug_rules;
|
---|
500 | print STDERR "DEBUG[dobin] \@deps for $bin : ",
|
---|
501 | join(",", map { "\n $_" } @deps), "\n"
|
---|
502 | if @deps && $debug_rules;
|
---|
503 | $self->emit('obj2bin',
|
---|
504 | bin => $bin,
|
---|
505 | attrs => { %attrs },
|
---|
506 | objs => [ @objs ],
|
---|
507 | deps => [ @deps ]);
|
---|
508 | foreach (@objs) {
|
---|
509 | $self->doobj($_, $bin, intent => "bin", attrs => { %attrs });
|
---|
510 | }
|
---|
511 | $cache{$bin} = 1;
|
---|
512 | }
|
---|
513 |
|
---|
514 | # doscript is responsible for building scripts from templates. It will
|
---|
515 | # call in2script.
|
---|
516 | sub doscript {
|
---|
517 | my $self = shift;
|
---|
518 | my $script = shift;
|
---|
519 | return "" if $cache{$script};
|
---|
520 | $self->emit('in2script',
|
---|
521 | script => $script,
|
---|
522 | attrs => $self->{info}->{attributes}->{scripts}->{$script} // {},
|
---|
523 | sources => $self->{info}->{sources}->{$script});
|
---|
524 | $cache{$script} = 1;
|
---|
525 | }
|
---|
526 |
|
---|
527 | sub dodir {
|
---|
528 | my $self = shift;
|
---|
529 | my $dir = shift;
|
---|
530 | return "" if !exists(&generatedir) or $cache{$dir};
|
---|
531 | $self->emit('generatedir',
|
---|
532 | dir => $dir,
|
---|
533 | deps => $self->{info}->{dirinfo}->{$dir}->{deps} // [],
|
---|
534 | %{$self->{info}->{dirinfo}->{$_}->{products}});
|
---|
535 | $cache{$dir} = 1;
|
---|
536 | }
|
---|
537 |
|
---|
538 | # dodocs is responsible for building documentation from .pods.
|
---|
539 | # It will call generatesrc.
|
---|
540 | sub dodocs {
|
---|
541 | my $self = shift;
|
---|
542 | my $type = shift;
|
---|
543 | my $section = shift;
|
---|
544 | foreach my $doc (@{$self->{info}->{"${type}docs"}->{$section}}) {
|
---|
545 | next if $cache{$doc};
|
---|
546 | $self->emit('generatesrc',
|
---|
547 | src => $doc,
|
---|
548 | generator => $self->{info}->{generate}->{$doc});
|
---|
549 | foreach ((@{$self->{info}->{depends}->{$doc} // []})) {
|
---|
550 | $self->dogenerate($_, undef, undef);
|
---|
551 | }
|
---|
552 | $cache{$doc} = 1;
|
---|
553 | }
|
---|
554 | }
|
---|
555 |
|
---|
556 | 1;
|
---|