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