27a00890b437953a0b994eb828478d4d20bea377
[kai/samba-autobuild/.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         unless (defined($mod->{INIT_FUNCTION_SENTINEL})) { $mod->{INIT_FUNCTION_SENTINEL} = "NULL"; }
94
95         if (not defined($mod->{OUTPUT_TYPE})) {
96                 if ((not defined($INPUT->{$mod->{SUBSYSTEM}})) or
97                         (not defined($INPUT->{$mod->{SUBSYSTEM}}->{TYPE})) or 
98                         $INPUT->{$mod->{SUBSYSTEM}}->{TYPE} eq "EXT_LIB") {
99                         $mod->{OUTPUT_TYPE} = ["SHARED_LIBRARY"];
100                 } else {
101                         $mod->{OUTPUT_TYPE} = $default_ot;
102                 }
103         }
104
105         if (grep(/SHARED_LIBRARY/, @{$mod->{OUTPUT_TYPE}})) {
106                 my $sane_subsystem = lc($mod->{SUBSYSTEM});
107                 $sane_subsystem =~ s/^lib//;
108                 $mod->{INSTALLDIR} = "MODULESDIR/$sane_subsystem";
109                 push (@{$mod->{PUBLIC_DEPENDENCIES}}, $mod->{SUBSYSTEM});
110                 add_libreplace($mod);
111         } 
112         if (grep(/MERGED_OBJ/, @{$mod->{OUTPUT_TYPE}}) and $mod->{TYPE} ne "PYTHON") {
113                 push (@{$INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS}}, $mod->{INIT_FUNCTION}) if defined($mod->{INIT_FUNCTION});
114                 push (@{$INPUT->{$mod->{SUBSYSTEM}}{PRIVATE_DEPENDENCIES}}, $mod->{NAME});
115         }
116 }
117
118 sub check_library($$$)
119 {
120         my ($INPUT, $lib, $default_ot) = @_;
121
122         return if ($lib->{ENABLE} ne "YES");
123
124         unless (defined($lib->{OUTPUT_TYPE})) { $lib->{OUTPUT_TYPE} = $default_ot; }
125
126         unless (defined($lib->{INIT_FUNCTION_TYPE})) { $lib->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
127         unless (defined($lib->{INIT_FUNCTION_SENTINEL})) { $lib->{INIT_FUNCTION_SENTINEL} = "NULL"; }
128         unless (defined($lib->{INSTALLDIR})) { $lib->{INSTALLDIR} = "LIBDIR"; }
129
130         add_libreplace($lib);
131 }
132
133 sub check_python($$$)
134 {
135         my ($INPUT, $python, $default_ot) = @_;
136
137         return if ($INPUT->{LIBPYTHON}{ENABLE} ne "YES");
138
139         $python->{INSTALLDIR} = "PYTHONDIR";
140         unless (defined($python->{CFLAGS})) { $python->{CFLAGS} = []; }
141         my $basename = $python->{NAME};
142         $basename =~ s/^python_//g;
143         unless (defined($python->{LIBRARY_REALNAME})) {
144                 $python->{LIBRARY_REALNAME} = "$basename.\$(SHLIBEXT)";
145         }
146         $python->{INIT_FUNCTION} = "{ (char *)\"$basename\", init$basename }";
147         push (@{$python->{CFLAGS}}, "\$(EXT_LIB_PYTHON_CFLAGS)");
148
149         $python->{SUBSYSTEM} = "LIBPYTHON";
150
151         check_module($INPUT, $python, $default_ot);
152 }
153
154 sub check_binary($$)
155 {
156         my ($INPUT, $bin) = @_;
157
158         return if ($bin->{ENABLE} ne "YES");
159
160         ($bin->{BINARY} = (lc $bin->{NAME})) if not defined($bin->{BINARY});
161         unless (defined($bin->{INIT_FUNCTION_SENTINEL})) { $bin->{INIT_FUNCTION_SENTINEL} = "NULL"; }
162         unless (defined($bin->{INIT_FUNCTION_TYPE})) { $bin->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
163
164         $bin->{OUTPUT_TYPE} = ["BINARY"];
165         add_libreplace($bin);
166 }
167
168 sub add_implicit($$)
169 {
170         my ($INPUT, $n) = @_;
171
172         $INPUT->{$n}->{TYPE} = "MAKE_RULE";
173         $INPUT->{$n}->{NAME} = $n;
174         $INPUT->{$n}->{OUTPUT_TYPE} = undef;
175         $INPUT->{$n}->{LIBS} = ["\$(".uc($n)."_LIBS)"];
176         $INPUT->{$n}->{LDFLAGS} = ["\$(".uc($n)."_LDFLAGS)"];
177         $INPUT->{$n}->{CFLAGS} = ["\$(".uc($n)."_CFLAGS)"];
178         $INPUT->{$n}->{CPPFLAGS} = ["\$(".uc($n)."_CPPFLAGS)"];
179         $INPUT->{$n}->{ENABLE} = "YES";
180 }
181
182 sub calc_unique_deps($$$$$$$$)
183 {
184         sub calc_unique_deps($$$$$$$$);
185         my ($name, $INPUT, $deps, $udeps, $withlibs, $forward, $pubonly, $busy) = @_;
186
187         foreach my $n (@$deps) {
188                 add_implicit($INPUT, $n) unless (defined($INPUT->{$n}) and defined($INPUT->{$n}->{TYPE}));
189                 my $dep = $INPUT->{$n};
190                 if (grep (/^$n$/, @$busy)) {
191                         next if (@{$dep->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ");
192                         die("Recursive dependency: $n, list: " . join(',', @$busy));
193                 }
194                 next if (grep /^$n$/, @$udeps);
195
196                 push (@{$udeps}, $n) if $forward;
197
198                 if (defined ($dep->{OUTPUT_TYPE}) && 
199                         ($withlibs or 
200                         (@{$dep->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ") or 
201                         (@{$dep->{OUTPUT_TYPE}}[0] eq "STATIC_LIBRARY"))) {
202                                 push (@$busy, $n);
203                                 calc_unique_deps($n, $INPUT, $dep->{PUBLIC_DEPENDENCIES}, $udeps, $withlibs, $forward, $pubonly, $busy);
204                                 calc_unique_deps($n, $INPUT, $dep->{PRIVATE_DEPENDENCIES}, $udeps, $withlibs, $forward, $pubonly, $busy) unless $pubonly;
205                                 pop (@$busy);
206                 }
207
208                 unshift (@{$udeps}, $n) unless $forward;
209         }
210 }
211
212 sub check($$$$$)
213 {
214         my ($INPUT, $enabled, $subsys_ot, $lib_ot, $module_ot) = @_;
215
216         foreach my $part (values %$INPUT) {
217                 if (defined($enabled->{$part->{NAME}})) { 
218                         $part->{ENABLE} = $enabled->{$part->{NAME}};
219                         next;
220                 }
221                 
222                 unless(defined($part->{ENABLE})) {
223                         if ($part->{TYPE} eq "EXT_LIB") {
224                                 $part->{ENABLE} = "NO";
225                         } else {
226                                 $part->{ENABLE} = "YES";
227                         }
228                 }
229         }
230
231         foreach my $part (values %$INPUT) {
232                 $part->{LINK_FLAGS} = [];
233                 $part->{FULL_OBJ_LIST} = ["\$($part->{NAME}_OBJ_FILES)"];
234
235                 if ($part->{TYPE} eq "SUBSYSTEM") { 
236                         check_subsystem($INPUT, $part, $subsys_ot);
237                 } elsif ($part->{TYPE} eq "MODULE") {
238                         check_module($INPUT, $part, $module_ot);
239                 } elsif ($part->{TYPE} eq "LIBRARY") {
240                         check_library($INPUT, $part, $lib_ot);
241                 } elsif ($part->{TYPE} eq "BINARY") {
242                         check_binary($INPUT, $part);
243                 } elsif ($part->{TYPE} eq "PYTHON") {
244                         check_python($INPUT, $part, $module_ot);
245                 } elsif ($part->{TYPE} eq "EXT_LIB") {
246                 } else {
247                         die("Unknown type $part->{TYPE}");
248                 }
249         }
250
251         foreach my $part (values %$INPUT) {
252                 if (defined($part->{INIT_FUNCTIONS})) {
253                         push (@{$part->{LINK_FLAGS}}, "\$(DYNEXP)");
254                 }
255         }
256
257         foreach my $part (values %$INPUT) {
258                 $part->{UNIQUE_DEPENDENCIES_LINK} = [];
259                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_LINK}, 0, 0, 0, []);
260                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_LINK}, 0, 0, 0, []);
261         }
262
263         foreach my $part (values %$INPUT) {
264                 $part->{UNIQUE_DEPENDENCIES_COMPILE} = [];
265                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_COMPILE}, 1, 1, 1, []);
266                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_COMPILE}, 1, 1, 1, []);
267         }
268
269         foreach my $part (values %$INPUT) {
270                 $part->{UNIQUE_DEPENDENCIES_ALL} = [];
271                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_ALL}, 1, 0, 0, []);
272                 calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_ALL}, 1, 0, 0, []);
273         }
274
275         return $INPUT;
276 }
277
278 1;