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