Never assume -fvisibility=hidden for modules unless explicitly specified (consistent...
[samba.git] / source4 / build / smb_build / input.pm
1 # Samba Build System
2 # - the input checking functions
3 #
4 #  Copyright (C) Stefan (metze) Metzmacher 2004
5 #  Copyright (C) Jelmer Vernooij 2004
6 #  Released under the GNU GPL
7
8 use strict;
9 package smb_build::input;
10 use File::Basename;
11
12 sub strtrim($)
13 {
14         $_ = shift;
15         s/^[\t\n ]*//g;
16         s/[\t\n ]*$//g;
17         return $_;
18 }
19
20 sub str2array($)
21 {
22         $_ = shift;
23         s/^[\t\n ]*//g;
24         s/[\t\n ]*$//g;
25         s/([\t\n ]+)/ /g;
26
27         return () if (length($_)==0);
28         return split /[ \t\n]/;
29 }
30
31 sub add_libreplace($)
32 {
33         my ($part) = @_;
34
35         return if ($part->{NAME} eq "LIBREPLACE");
36         return if ($part->{NAME} eq "LIBREPLACE_HOSTCC");
37         return if ($part->{NAME} eq "REPLACE_READDIR");
38
39         foreach my $n (@{$part->{PRIVATE_DEPENDENCIES}}) {
40                 return if ($n eq "LIBREPLACE");
41                 return if ($n eq "LIBREPLACE_HOSTCC");
42         }
43         foreach my $n (@{$part->{PUBLIC_DEPENDENCIES}}) {
44                 return if ($n eq "LIBREPLACE");
45                 return if ($n eq "LIBREPLACE_HOSTCC");
46         }
47
48         if (defined($part->{USE_HOSTCC}) && $part->{USE_HOSTCC} eq "YES") {
49                 unshift (@{$part->{PRIVATE_DEPENDENCIES}}, "LIBREPLACE_HOSTCC");
50         } else {
51                 unshift (@{$part->{PRIVATE_DEPENDENCIES}}, "LIBREPLACE");
52         }
53 }
54
55 sub check_subsystem($$$)
56 {
57         my ($INPUT, $subsys, $default_ot) = @_;
58         return if ($subsys->{ENABLE} ne "YES");
59         
60         unless (defined($subsys->{OUTPUT_TYPE})) { $subsys->{OUTPUT_TYPE} = $default_ot; }
61         unless (defined($subsys->{INIT_FUNCTION_TYPE})) { $subsys->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
62         unless (defined($subsys->{INIT_FUNCTION_SENTINEL})) { $subsys->{INIT_FUNCTION_SENTINEL} = "NULL"; }
63 }
64
65 sub check_module($$$)
66 {
67         my ($INPUT, $mod, $default_ot) = @_;
68
69         die("Module $mod->{NAME} does not have a SUBSYSTEM set") if not defined($mod->{SUBSYSTEM});
70
71         if (not exists($INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS})) {
72                 $INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS} = [];
73         }
74
75         if (!(defined($INPUT->{$mod->{SUBSYSTEM}}))) {
76                 die("Unknown subsystem $mod->{SUBSYSTEM} for module $mod->{NAME}");
77         }
78
79         if ($INPUT->{$mod->{SUBSYSTEM}} eq "NO") {
80                 warn("Disabling module $mod->{NAME} because subsystem $mod->{SUBSYSTEM} is disabled");
81                 $mod->{ENABLE} = "NO";
82                 return;
83         }
84
85         return if ($mod->{ENABLE} ne "YES");
86
87         if (exists($INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTION_TYPE})) {
88                 $mod->{INIT_FUNCTION_TYPE} = $INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTION_TYPE};
89         } else {
90                 $mod->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)";
91         }
92
93         if (not defined($mod->{OUTPUT_TYPE})) {
94                 if ($INPUT->{$mod->{SUBSYSTEM}}->{TYPE} eq "EXT_LIB") {
95                         $mod->{OUTPUT_TYPE} = undef;
96                 } else {
97                         $mod->{OUTPUT_TYPE} = $default_ot;
98                 }
99         }
100
101         if (grep(/SHARED_LIBRARY/, @{$mod->{OUTPUT_TYPE}})) {
102                 my $sane_subsystem = lc($mod->{SUBSYSTEM});
103                 $sane_subsystem =~ s/^lib//;
104                 $mod->{INSTALLDIR} = "MODULESDIR/$sane_subsystem";
105                 push (@{$mod->{PUBLIC_DEPENDENCIES}}, $mod->{SUBSYSTEM});
106                 add_libreplace($mod);
107         } 
108         if (grep(/MERGED_OBJ/, @{$mod->{OUTPUT_TYPE}})) {
109                 push (@{$INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS}}, $mod->{INIT_FUNCTION}) if defined($mod->{INIT_FUNCTION});
110                 unshift (@{$INPUT->{$mod->{SUBSYSTEM}}{PRIVATE_DEPENDENCIES}}, $mod->{NAME});
111         }
112 }
113
114 sub check_library($$$)
115 {
116         my ($INPUT, $lib, $default_ot) = @_;
117
118         return if ($lib->{ENABLE} ne "YES");
119
120         unless (defined($lib->{OUTPUT_TYPE})) { $lib->{OUTPUT_TYPE} = $default_ot; }
121
122         if (defined($lib->{VERSION}) and not defined($lib->{SO_VERSION})) {
123                 print "$lib->{NAME}: Please specify SO_VERSION when specifying VERSION\n";
124                 return;
125         }
126
127         if (defined($lib->{SO_VERSION}) and not defined($lib->{VERSION})) {
128                 print "$lib->{NAME}: Please specify VERSION when specifying SO_VERSION\n";
129                 return;
130         }
131
132         unless (defined($lib->{INIT_FUNCTION_TYPE})) { $lib->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
133         unless (defined($lib->{INIT_FUNCTION_SENTINEL})) { $lib->{INIT_FUNCTION_SENTINEL} = "NULL"; }
134         unless (defined($lib->{INSTALLDIR})) { $lib->{INSTALLDIR} = "LIBDIR"; }
135
136         add_libreplace($lib);
137 }
138
139 sub check_python($$$)
140 {
141         my ($INPUT, $python, $default_ot) = @_;
142
143         return if ($INPUT->{LIBPYTHON}{ENABLE} ne "YES");
144
145         $python->{INSTALLDIR} = "PYTHONDIR";
146         unless (defined($python->{CFLAGS})) { $python->{CFLAGS} = []; }
147         if (defined($python->{SWIG_FILE})) {
148                 my $dirname = dirname($python->{SWIG_FILE});
149                 my $basename = basename($python->{SWIG_FILE}, ".i");
150
151                 $dirname .= "/" unless $dirname =~ /\/$/;
152                 $dirname = "" if $dirname eq "./";
153
154                 $python->{OBJ_FILES} = ["$dirname$basename\_wrap.o"];
155                 $python->{LIBRARY_REALNAME} = "_$basename.\$(SHLIBEXT)";
156                 $python->{PYTHON_FILES} = ["$dirname$basename.py"];
157                 push (@{$python->{CFLAGS}}, "\$(CFLAG_NO_UNUSED_MACROS)");
158                 push (@{$python->{CFLAGS}}, "\$(CFLAG_NO_CAST_QUAL)");
159                 $python->{INIT_FUNCTION} = "{ (char *)\"_$basename\", init_$basename }";
160         } else {
161                 my $basename = $python->{NAME};
162                 $basename =~ s/^python_//g;
163                 $python->{LIBRARY_REALNAME} = "$basename.\$(SHLIBEXT)";
164                 $python->{INIT_FUNCTION} = "{ (char *)\"$basename\", init$basename }";
165         }
166         push (@{$python->{CFLAGS}}, "\$(EXT_LIB_PYTHON_CFLAGS)");
167
168         $python->{SUBSYSTEM} = "LIBPYTHON";
169
170         check_module($INPUT, $python, $default_ot);
171 }
172
173 sub check_binary($$)
174 {
175         my ($INPUT, $bin) = @_;
176
177         return if ($bin->{ENABLE} ne "YES");
178
179         ($bin->{BINARY} = (lc $bin->{NAME})) if not defined($bin->{BINARY});
180
181         $bin->{OUTPUT_TYPE} = ["BINARY"];
182         add_libreplace($bin);
183 }
184
185 sub add_implicit($$)
186 {
187         my ($INPUT, $n) = @_;
188
189         $INPUT->{$n} = {
190                 TYPE => "MAKE_RULE",
191                 NAME => $n,
192                 TARGET => "",
193                 OUTPUT_TYPE => undef,
194                 LIBS => ["\$(".uc($n)."_LIBS)"],
195                 LDFLAGS => ["\$(".uc($n)."_LDFLAGS)"],
196                 CFLAGS => ["\$(".uc($n)."_CFLAGS)"],
197                 CPPFLAGS => ["\$(".uc($n)."_CPPFLAGS)"]
198         };
199 }
200
201 sub calc_unique_deps($$$$$$$$)
202 {
203         sub calc_unique_deps($$$$$$$$);
204         my ($name, $INPUT, $deps, $udeps, $withlibs, $forward, $pubonly, $busy) = @_;
205
206         foreach my $n (@$deps) {
207                 add_implicit($INPUT, $n) unless (defined($INPUT->{$n}));
208                 my $dep = $INPUT->{$n};
209                 if (grep (/^$n$/, @$busy)) {
210                         next if (@{$dep->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ");
211                         die("Recursive dependency: $n, list: " . join(',', @$busy));
212                 }
213                 next if (grep /^$n$/, @$udeps);
214
215                 push (@{$udeps}, $dep->{NAME}) if $forward;
216
217                 if (defined ($dep->{OUTPUT_TYPE}) && 
218                         ($withlibs or 
219                         (@{$dep->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ") or 
220                         (@{$dep->{OUTPUT_TYPE}}[0] eq "STATIC_LIBRARY"))) {
221                                 push (@$busy, $dep->{NAME});
222                                 calc_unique_deps($dep->{NAME}, $INPUT, $dep->{PUBLIC_DEPENDENCIES}, $udeps, $withlibs, $forward, $pubonly, $busy);
223                                 calc_unique_deps($dep->{NAME}, $INPUT, $dep->{PRIVATE_DEPENDENCIES}, $udeps, $withlibs, $forward, $pubonly, $busy) unless $pubonly;
224                                 pop (@$busy);
225                 }
226
227                 unshift (@{$udeps}, $dep->{NAME}) unless $forward;
228         }
229 }
230
231 sub check($$$$$)
232 {
233         my ($INPUT, $enabled, $subsys_ot, $lib_ot, $module_ot) = @_;
234
235         foreach my $part (values %$INPUT) {
236                 unless (defined($part->{PUBLIC_HEADERS})) {
237                         $part->{PUBLIC_HEADERS} = [];
238                 }
239                 
240                 if (defined($part->{PUBLIC_PROTO_HEADER})) {
241                         push (@{$part->{PUBLIC_HEADERS}}, $part->{PUBLIC_PROTO_HEADER});
242                 }
243
244                 if (defined($enabled->{$part->{NAME}})) { 
245                         $part->{ENABLE} = $enabled->{$part->{NAME}};
246                         next;
247                 }
248                 
249                 unless(defined($part->{ENABLE})) {
250                         if ($part->{TYPE} eq "EXT_LIB") {
251                                 $part->{ENABLE} = "NO";
252                         } else {
253                                 $part->{ENABLE} = "YES";
254                         }
255                 }
256         }
257
258         foreach my $part (values %$INPUT) {
259                 $part->{LINK_FLAGS} = [];
260                 $part->{FULL_OBJ_LIST} = ["\$($part->{NAME}_OBJ_LIST)"];
261
262                 if ($part->{TYPE} eq "SUBSYSTEM") { 
263                         check_subsystem($INPUT, $part, $subsys_ot);
264                 } elsif ($part->{TYPE} eq "MODULE") {
265                         check_module($INPUT, $part, $module_ot);
266                 } elsif ($part->{TYPE} eq "LIBRARY") {
267                         check_library($INPUT, $part, $lib_ot);
268                 } elsif ($part->{TYPE} eq "BINARY") {
269                         check_binary($INPUT, $part);
270                 } elsif ($part->{TYPE} eq "PYTHON") {
271                         check_python($INPUT, $part, $module_ot);
272                 } elsif ($part->{TYPE} eq "EXT_LIB") {
273                 } else {
274                         die("Unknown type $part->{TYPE}");
275                 }
276         }
277
278         foreach my $part (values %$INPUT) {
279                 if (defined($part->{INIT_FUNCTIONS})) {
280                         push (@{$part->{LINK_FLAGS}}, "\$(DYNEXP)");
281                 }
282         }
283
284         foreach my $part (values %$INPUT) {
285                 $part->{UNIQUE_DEPENDENCIES_LINK} = [];
286                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_LINK}, 0, 0, 0, []);
287                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_LINK}, 0, 0, 0, []);
288         }
289
290         foreach my $part (values %$INPUT) {
291                 $part->{UNIQUE_DEPENDENCIES_COMPILE} = [];
292                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_COMPILE}, 1, 1, 1, []);
293                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_COMPILE}, 1, 1, 1, []);
294         }
295
296         foreach my $part (values %$INPUT) {
297                 $part->{UNIQUE_DEPENDENCIES_ALL} = [];
298                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_ALL}, 1, 0, 0, []);
299                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_ALL}, 1, 0, 0, []);
300         }
301
302         return $INPUT;
303 }
304
305 1;