]>
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. | |
186a31e5 RL |
12 | sub extensionlesslib { |
13 | my @result = map { $_ =~ /(\.a)?$/; $` } @_; | |
14 | return @result if wantarray; | |
15 | return $result[0]; | |
16 | } | |
ddf1847d RL |
17 | sub resolvedepends { |
18 | my $thing = shift; | |
186a31e5 | 19 | my $extensionlessthing = extensionlesslib($thing); |
ddf1847d | 20 | my @listsofar = @_; # to check if we're looping |
33105818 RL |
21 | my @list = @{$unified_info{depends}->{$thing} // |
22 | $unified_info{depends}->{$extensionlessthing}}; | |
ddf1847d RL |
23 | my @newlist = (); |
24 | if (scalar @list) { | |
25 | foreach my $item (@list) { | |
186a31e5 | 26 | my $extensionlessitem = extensionlesslib($item); |
ddf1847d | 27 | # It's time to break off when the dependency list starts looping |
186a31e5 | 28 | next if grep { extensionlesslib($_) eq $extensionlessitem } @listsofar; |
ddf1847d RL |
29 | push @newlist, $item, resolvedepends($item, @listsofar, $item); |
30 | } | |
31 | } | |
32 | @newlist; | |
33 | } | |
34 | sub reducedepends { | |
35 | my @list = @_; | |
36 | my @newlist = (); | |
33105818 | 37 | my %replace = (); |
ddf1847d RL |
38 | while (@list) { |
39 | my $item = shift @list; | |
186a31e5 | 40 | my $extensionlessitem = extensionlesslib($item); |
33105818 RL |
41 | if (grep { $extensionlessitem eq extensionlesslib($_) } @list) { |
42 | if ($item ne $extensionlessitem) { | |
46f4e1be | 43 | # If this instance of the library is explicitly static, we |
33105818 RL |
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 | } | |
ddf1847d | 51 | } |
33105818 | 52 | map { $replace{$_} // $_; } @newlist; |
ddf1847d RL |
53 | } |
54 | ||
d4605727 RL |
55 | # dogenerate is responsible for producing all the recipes that build |
56 | # generated source files. It recurses in case a dependency is also a | |
57 | # generated source file. | |
ae4c7450 RL |
58 | sub dogenerate { |
59 | my $src = shift; | |
60 | return "" if $cache{$src}; | |
d4605727 RL |
61 | my $obj = shift; |
62 | my $bin = shift; | |
ae4c7450 RL |
63 | my %opts = @_; |
64 | if ($unified_info{generate}->{$src}) { | |
05a7aee0 RL |
65 | die "$src is generated by Configure, should not appear in build file\n" |
66 | if ref $unified_info{generate}->{$src} eq ""; | |
8d34daf0 | 67 | my $script = $unified_info{generate}->{$src}->[0]; |
ae4c7450 | 68 | $OUT .= generatesrc(src => $src, |
66a24ab8 | 69 | product => $bin, |
ae4c7450 | 70 | generator => $unified_info{generate}->{$src}, |
8d34daf0 RL |
71 | generator_incs => $unified_info{includes}->{$script}, |
72 | generator_deps => $unified_info{depends}->{$script}, | |
ae4c7450 | 73 | deps => $unified_info{depends}->{$src}, |
609e4be8 RL |
74 | incs => [ @{$unified_info{includes}->{$obj}}, |
75 | @{$unified_info{includes}->{$bin}} ], | |
7b34f0fa RL |
76 | defs => [ @{$unified_info{defines}->{$obj}}, |
77 | @{$unified_info{defines}->{$bin}} ], | |
ae4c7450 RL |
78 | %opts); |
79 | foreach (@{$unified_info{depends}->{$src}}) { | |
d4605727 | 80 | dogenerate($_, $obj, $bin, %opts); |
ae4c7450 RL |
81 | } |
82 | } | |
83 | $cache{$src} = 1; | |
84 | } | |
85 | ||
ddf1847d RL |
86 | # doobj is responsible for producing all the recipes that build |
87 | # object files as well as dependency files. | |
88 | sub doobj { | |
89 | my $obj = shift; | |
b23238f9 | 90 | return "" if $cache{$obj}; |
ddf1847d | 91 | my $bin = shift; |
45502bfe | 92 | my %opts = @_; |
ddf1847d | 93 | if (@{$unified_info{sources}->{$obj}}) { |
81183680 | 94 | $OUT .= src2obj(obj => $obj, |
84f38675 | 95 | product => $bin, |
ddf1847d | 96 | srcs => $unified_info{sources}->{$obj}, |
ae4c7450 | 97 | deps => $unified_info{depends}->{$obj}, |
609e4be8 RL |
98 | incs => [ @{$unified_info{includes}->{$obj}}, |
99 | @{$unified_info{includes}->{$bin}} ], | |
7b34f0fa RL |
100 | defs => [ @{$unified_info{defines}->{$obj}}, |
101 | @{$unified_info{defines}->{$bin}} ], | |
45502bfe | 102 | %opts); |
ae4c7450 RL |
103 | foreach ((@{$unified_info{sources}->{$obj}}, |
104 | @{$unified_info{depends}->{$obj}})) { | |
d4605727 | 105 | dogenerate($_, $obj, $bin, %opts); |
ae4c7450 | 106 | } |
ddf1847d | 107 | } |
b23238f9 | 108 | $cache{$obj} = 1; |
ddf1847d RL |
109 | } |
110 | ||
111 | # dolib is responsible for building libraries. It will call | |
f6196227 | 112 | # obj2shlib is shared libraries are produced, and obj2lib in all |
ddf1847d RL |
113 | # cases. It also makes sure all object files for the library are |
114 | # built. | |
115 | sub dolib { | |
116 | my $lib = shift; | |
b23238f9 | 117 | return "" if $cache{$lib}; |
33105818 | 118 | unless ($disabled{shared} || $lib =~ /\.a$/) { |
f6196227 | 119 | my $obj2shlib = defined &obj2shlib ? \&obj2shlib : \&libobj2shlib; |
f5fb6f05 | 120 | $OUT .= $obj2shlib->(lib => $lib, |
5f825749 | 121 | attrs => $unified_info{attributes}->{$lib}, |
bec2db18 | 122 | objs => $unified_info{shared_sources}->{$lib}, |
5cae2d34 | 123 | deps => [ reducedepends(resolvedepends($lib)) ]); |
81183680 RL |
124 | foreach ((@{$unified_info{shared_sources}->{$lib}}, |
125 | @{$unified_info{sources}->{$lib}})) { | |
126 | # If this is somehow a compiled object, take care of it that way | |
127 | # Otherwise, it might simply be generated | |
128 | if (defined $unified_info{sources}->{$_}) { | |
5cae2d34 RL |
129 | doobj($_, $lib, intent => "shlib", |
130 | attrs => $unified_info{attributes}->{$lib}); | |
81183680 RL |
131 | } else { |
132 | dogenerate($_, undef, undef, intent => "lib"); | |
133 | } | |
2110febb | 134 | } |
ddf1847d RL |
135 | } |
136 | $OUT .= obj2lib(lib => $lib, | |
5f825749 | 137 | attrs => $unified_info{attributes}->{$lib}, |
81183680 | 138 | objs => [ @{$unified_info{sources}->{$lib}} ]); |
2110febb | 139 | foreach (@{$unified_info{sources}->{$lib}}) { |
5cae2d34 RL |
140 | doobj($_, $lib, intent => "lib", |
141 | attrs => $unified_info{attributes}->{$lib}); | |
2110febb | 142 | } |
b23238f9 | 143 | $cache{$lib} = 1; |
ddf1847d RL |
144 | } |
145 | ||
1842f369 | 146 | # domodule is responsible for building modules. It will call |
5386287c | 147 | # obj2dso, and also makes sure all object files for the library |
ddf1847d | 148 | # are built. |
1842f369 | 149 | sub domodule { |
ddf1847d | 150 | my $lib = shift; |
b23238f9 | 151 | return "" if $cache{$lib}; |
5386287c | 152 | $OUT .= obj2dso(lib => $lib, |
5f825749 | 153 | attrs => $unified_info{attributes}->{$lib}, |
22b41467 | 154 | objs => $unified_info{sources}->{$lib}, |
5cae2d34 | 155 | deps => [ resolvedepends($lib) ]); |
22b41467 | 156 | foreach (@{$unified_info{sources}->{$lib}}) { |
66a24ab8 RL |
157 | # If this is somehow a compiled object, take care of it that way |
158 | # Otherwise, it might simply be generated | |
159 | if (defined $unified_info{sources}->{$_}) { | |
5cae2d34 RL |
160 | doobj($_, $lib, intent => "dso", |
161 | attrs => $unified_info{attributes}->{$lib}); | |
66a24ab8 RL |
162 | } else { |
163 | dogenerate($_, undef, $lib, intent => "dso"); | |
164 | } | |
2110febb | 165 | } |
b23238f9 | 166 | $cache{$lib} = 1; |
ddf1847d RL |
167 | } |
168 | ||
169 | # dobin is responsible for building programs. It will call obj2bin, | |
170 | # and also makes sure all object files for the library are built. | |
171 | sub dobin { | |
172 | my $bin = shift; | |
b23238f9 | 173 | return "" if $cache{$bin}; |
ddf1847d RL |
174 | my $deps = [ reducedepends(resolvedepends($bin)) ]; |
175 | $OUT .= obj2bin(bin => $bin, | |
5f825749 | 176 | attrs => $unified_info{attributes}->{$bin}, |
81183680 | 177 | objs => [ @{$unified_info{sources}->{$bin}} ], |
5cae2d34 | 178 | deps => $deps); |
2110febb | 179 | foreach (@{$unified_info{sources}->{$bin}}) { |
5cae2d34 RL |
180 | doobj($_, $bin, intent => "bin", |
181 | attrs => $unified_info{attributes}->{$bin}); | |
2110febb | 182 | } |
b23238f9 | 183 | $cache{$bin} = 1; |
ddf1847d RL |
184 | } |
185 | ||
186 | # dobin is responsible for building scripts from templates. It will | |
187 | # call in2script. | |
188 | sub doscript { | |
189 | my $script = shift; | |
b23238f9 | 190 | return "" if $cache{$script}; |
ddf1847d | 191 | $OUT .= in2script(script => $script, |
5f825749 | 192 | attrs => $unified_info{attributes}->{$script}, |
5cae2d34 | 193 | sources => $unified_info{sources}->{$script}); |
b23238f9 | 194 | $cache{$script} = 1; |
ddf1847d RL |
195 | } |
196 | ||
0ad1d94d RL |
197 | sub dodir { |
198 | my $dir = shift; | |
199 | return "" if !exists(&generatedir) or $cache{$dir}; | |
200 | $OUT .= generatedir(dir => $dir, | |
201 | deps => $unified_info{dirinfo}->{$dir}->{deps}, | |
202 | %{$unified_info{dirinfo}->{$_}->{products}}); | |
203 | $cache{$dir} = 1; | |
204 | } | |
205 | ||
8a67946e RL |
206 | # Start with populating the cache with all the overrides |
207 | %cache = map { $_ => 1 } @{$unified_info{overrides}}; | |
208 | ||
4f858293 RL |
209 | # Build mandatory generated headers |
210 | foreach (@{$unified_info{depends}->{""}}) { dogenerate($_); } | |
211 | ||
1842f369 | 212 | # Build all known libraries, modules, programs and scripts. |
ddf1847d | 213 | # Everything else will be handled as a consequence. |
f246f90e | 214 | foreach (@{$unified_info{libraries}}) { dolib($_); } |
1842f369 | 215 | foreach (@{$unified_info{modules}}) { domodule($_); } |
f246f90e RL |
216 | foreach (@{$unified_info{programs}}) { dobin($_); } |
217 | foreach (@{$unified_info{scripts}}) { doscript($_); } | |
ddf1847d | 218 | |
0ad1d94d | 219 | foreach (sort keys %{$unified_info{dirinfo}}) { dodir($_); } |
ddf1847d | 220 | -} |