Home | History | Annotate | Line # | Download | only in Configurations
      1 {- # -*- Mode: perl -*-
      2 
      3  use File::Basename;
      4 
      5  # A cache of objects for which a recipe has already been generated
      6  my %cache;
      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.
     12  sub extensionlesslib {
     13      my @result = map { $_ =~ /(\.a)?$/; $` } @_;
     14      return @result if wantarray;
     15      return $result[0];
     16  }
     17  sub resolvedepends {
     18      my $thing = shift;
     19      my $extensionlessthing = extensionlesslib($thing);
     20      my @listsofar = @_;    # to check if we're looping
     21      my @list = @{$unified_info{depends}->{$thing} //
     22                       $unified_info{depends}->{$extensionlessthing}};
     23      my @newlist = ();
     24      if (scalar @list) {
     25          foreach my $item (@list) {
     26              my $extensionlessitem = extensionlesslib($item);
     27              # It's time to break off when the dependency list starts looping
     28              next if grep { extensionlesslib($_) eq $extensionlessitem } @listsofar;
     29              push @newlist, $item, resolvedepends($item, @listsofar, $item);
     30          }
     31      }
     32      @newlist;
     33  }
     34  sub reducedepends {
     35      my @list = @_;
     36      my @newlist = ();
     37      my %replace = ();
     38      while (@list) {
     39          my $item = shift @list;
     40          my $extensionlessitem = extensionlesslib($item);
     41          if (grep { $extensionlessitem eq extensionlesslib($_) } @list) {
     42              if ($item ne $extensionlessitem) {
     43                  # If this instance of the library is explicitly static, we
     44                  # prefer that to any shared library name, since it must have
     45                  # been done on purpose.
     46                  $replace{$extensionlessitem} = $item;
     47              }
     48          } else {
     49              push @newlist, $item;
     50          }
     51      }
     52      map { $replace{$_} // $_; } @newlist;
     53  }
     54 
     55  # is_installed checks if a given file will be installed (i.e. they are
     56  # not defined _NO_INST in build.info)
     57  sub is_installed {
     58      my $product = shift;
     59      if (grep { $product eq $_ }
     60          map { (@{$unified_info{install}->{$_}}) }
     61          keys %{$unified_info{install}}) {
     62          return 1;
     63      }
     64      return 0;
     65  }
     66 
     67  # dogenerate is responsible for producing all the recipes that build
     68  # generated source files.  It recurses in case a dependency is also a
     69  # generated source file.
     70  sub dogenerate {
     71      my $src = shift;
     72      return "" if $cache{$src};
     73      my $obj = shift;
     74      my $bin = shift;
     75      my %opts = @_;
     76      if ($unified_info{generate}->{$src}) {
     77          die "$src is generated by Configure, should not appear in build file\n"
     78              if ref $unified_info{generate}->{$src} eq "";
     79          my $script = $unified_info{generate}->{$src}->[0];
     80          $OUT .= generatesrc(src => $src,
     81                              generator => $unified_info{generate}->{$src},
     82                              generator_incs => $unified_info{includes}->{$script},
     83                              generator_deps => $unified_info{depends}->{$script},
     84                              deps => $unified_info{depends}->{$src},
     85                              incs => $unified_info{includes}->{$obj},
     86                              %opts);
     87          foreach (@{$unified_info{depends}->{$src}}) {
     88              dogenerate($_, $obj, $bin, %opts);
     89          }
     90      }
     91      $cache{$src} = 1;
     92  }
     93 
     94  # doobj is responsible for producing all the recipes that build
     95  # object files as well as dependency files.
     96  sub doobj {
     97      my $obj = shift;
     98      return "" if $cache{$obj};
     99      my $bin = shift;
    100      my %opts = @_;
    101      if (@{$unified_info{sources}->{$obj}}) {
    102          $OUT .= src2obj(obj => $obj,
    103                          product => $bin,
    104                          srcs => $unified_info{sources}->{$obj},
    105                          deps => $unified_info{depends}->{$obj},
    106                          incs => $unified_info{includes}->{$obj},
    107                          %opts);
    108          foreach ((@{$unified_info{sources}->{$obj}},
    109                    @{$unified_info{depends}->{$obj}})) {
    110              dogenerate($_, $obj, $bin, %opts);
    111          }
    112      }
    113      $cache{$obj} = 1;
    114  }
    115 
    116  # dolib is responsible for building libraries.  It will call
    117  # libobj2shlib is shared libraries are produced, and obj2lib in all
    118  # cases.  It also makes sure all object files for the library are
    119  # built.
    120  sub dolib {
    121      my $lib = shift;
    122      return "" if $cache{$lib};
    123      unless ($disabled{shared} || $lib =~ /\.a$/) {
    124          $OUT .= libobj2shlib(shlib => $unified_info{sharednames}->{$lib},
    125                               lib => $lib,
    126                               objs => [ @{$unified_info{shared_sources}->{$lib}},
    127                                         @{$unified_info{sources}->{$lib}} ],
    128                               deps => [ reducedepends(resolvedepends($lib)) ],
    129                               installed => is_installed($lib));
    130          foreach ((@{$unified_info{shared_sources}->{$lib}},
    131                    @{$unified_info{sources}->{$lib}})) {
    132              # If this is somehow a compiled object, take care of it that way
    133              # Otherwise, it might simply be generated
    134              if (defined $unified_info{sources}->{$_}) {
    135                  doobj($_, $lib, intent => "lib", installed => is_installed($lib));
    136              } else {
    137                  dogenerate($_, undef, undef, intent => "lib");
    138              }
    139          }
    140      }
    141      $OUT .= obj2lib(lib => $lib,
    142                      objs => [ @{$unified_info{sources}->{$lib}} ]);
    143      foreach (@{$unified_info{sources}->{$lib}}) {
    144          doobj($_, $lib, intent => "lib", installed => is_installed($lib));
    145      }
    146      $cache{$lib} = 1;
    147  }
    148 
    149  # doengine is responsible for building engines.  It will call
    150  # obj2dso, and also makes sure all object files for the library
    151  # are built.
    152  sub doengine {
    153      my $lib = shift;
    154      return "" if $cache{$lib};
    155      $OUT .= obj2dso(lib => $lib,
    156                      objs => [ @{$unified_info{sources}->{$lib}},
    157                                @{$unified_info{shared_sources}->{$lib}} ],
    158                      deps => [ resolvedepends($lib) ],
    159                      installed => is_installed($lib));
    160      foreach ((@{$unified_info{sources}->{$lib}},
    161                @{$unified_info{shared_sources}->{$lib}})) {
    162          doobj($_, $lib, intent => "dso", installed => is_installed($lib));
    163      }
    164      $cache{$lib} = 1;
    165  }
    166 
    167  # dobin is responsible for building programs.  It will call obj2bin,
    168  # and also makes sure all object files for the library are built.
    169  sub dobin {
    170      my $bin = shift;
    171      return "" if $cache{$bin};
    172      my $deps = [ reducedepends(resolvedepends($bin)) ];
    173      $OUT .= obj2bin(bin => $bin,
    174                      objs => [ @{$unified_info{sources}->{$bin}} ],
    175                      deps => $deps,
    176                      installed => is_installed($bin));
    177      foreach (@{$unified_info{sources}->{$bin}}) {
    178          doobj($_, $bin, intent => "bin", installed => is_installed($bin));
    179      }
    180      $cache{$bin} = 1;
    181  }
    182 
    183  # dobin is responsible for building scripts from templates.  It will
    184  # call in2script.
    185  sub doscript {
    186      my $script = shift;
    187      return "" if $cache{$script};
    188      $OUT .= in2script(script => $script,
    189                        sources => $unified_info{sources}->{$script},
    190                        installed => is_installed($script));
    191      $cache{$script} = 1;
    192  }
    193 
    194  sub dodir {
    195      my $dir = shift;
    196      return "" if !exists(&generatedir) or $cache{$dir};
    197      $OUT .= generatedir(dir => $dir,
    198                          deps => $unified_info{dirinfo}->{$dir}->{deps},
    199                          %{$unified_info{dirinfo}->{$_}->{products}});
    200      $cache{$dir} = 1;
    201  }
    202 
    203  # Start with populating the cache with all the overrides
    204  %cache = map { $_ => 1 } @{$unified_info{overrides}};
    205 
    206  # Build mandatory generated headers
    207  foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); }
    208 
    209  # Build all known libraries, engines, programs and scripts.
    210  # Everything else will be handled as a consequence.
    211  foreach (@{$unified_info{libraries}}) { dolib($_);    }
    212  foreach (@{$unified_info{engines}})   { doengine($_); }
    213  foreach (@{$unified_info{programs}})  { dobin($_);    }
    214  foreach (@{$unified_info{scripts}})   { doscript($_); }
    215 
    216  foreach (sort keys %{$unified_info{dirinfo}})  { dodir($_); }
    217 
    218  # Finally, should there be any applicable BEGINRAW/ENDRAW sections,
    219  # they are added here.
    220  $OUT .= $_."\n" foreach @{$unified_info{rawlines}};
    221 -}
    222