common.tmpl 9.7 KB

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