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