Use realpath for now to work around .. tricks.
[samba.git] / source4 / build / smb_build / makefile.pm
1 # Samba Build System
2 # - create output for Makefile
3 #
4 #  Copyright (C) Stefan (metze) Metzmacher 2004
5 #  Copyright (C) Jelmer Vernooij 2005
6 #  Released under the GNU GPL
7
8 package smb_build::makefile;
9 use smb_build::env;
10 use smb_build::output;
11 use File::Basename;
12 use strict;
13
14 use base 'smb_build::env';
15 use Cwd 'abs_path';
16
17 sub new($$$)
18 {
19         my ($myname, $config, $mkfile) = @_;
20         my $self = new smb_build::env($config);
21         
22         bless($self, $myname);
23
24         $self->{output} = "";
25
26         $self->{mkfile} = $mkfile;
27
28         $self->output("################################################\n");
29         $self->output("# Autogenerated by build/smb_build/makefile.pm #\n");
30         $self->output("################################################\n");
31         $self->output("\n");
32
33         if (!$self->{automatic_deps}) {
34                 $self->output("ALL_PREDEP = proto\n");
35                 $self->output(".NOTPARALLEL:\n");
36         }
37
38         return $self;
39 }
40
41 sub output($$)
42 {
43         my ($self, $text) = @_;
44
45         $self->{output} .= $text;
46 }
47
48 sub _prepare_mk_files($)
49 {
50         my $self = shift;
51         my @tmp = ();
52
53         foreach (@smb_build::config_mk::parsed_files) {
54                 s/ .*$//g;
55                 push (@tmp, $_);
56         }
57
58         if ($self->{gnu_make}) {
59                 $self->output("
60 ifneq (\$(MAKECMDGOALS),clean)
61 ifneq (\$(MAKECMDGOALS),distclean)
62 ifneq (\$(MAKECMDGOALS),realdistclean)
63 ");
64         }
65
66         $self->output("MK_FILES = " . array2oneperline(\@tmp) . "\n");
67
68         if ($self->{gnu_make}) {
69                 $self->output("
70 endif
71 endif
72 endif
73 ");
74         }
75 }
76
77 sub array2oneperline($)
78 {
79         my $array = shift;
80         my $output = "";
81
82         foreach (@$array) {
83                 next unless defined($_);
84
85                 $output .= " \\\n\t\t$_";
86         }
87
88         return $output;
89 }
90
91 sub _prepare_list($$$)
92 {
93         my ($self,$ctx,$var) = @_;
94         my @tmparr = ();
95
96         push(@tmparr, @{$ctx->{$var}}) if defined($ctx->{$var});
97
98         my $tmplist = array2oneperline(\@tmparr);
99         return if ($tmplist eq "");
100
101         $self->output("$ctx->{NAME}_$var =$tmplist\n");
102 }
103
104 sub SharedModulePrimitives($$)
105 {
106         my ($self,$ctx) = @_;
107         
108         #FIXME
109 }
110
111 sub SharedModule($$)
112 {
113         my ($self,$ctx) = @_;
114
115         my $sane_subsystem = lc($ctx->{SUBSYSTEM});
116         $sane_subsystem =~ s/^lib//;
117         
118         if ($ctx->{TYPE} eq "PYTHON") {
119                 $self->output("PYTHON_DSOS += $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}\n");
120         } else {
121                 $self->output("PLUGINS += $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}\n");
122                 $self->output("installplugins:: $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}\n");
123                 $self->output("\t\@echo Installing $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME} as \$(DESTDIR)\$(modulesdir)/$sane_subsystem/$ctx->{LIBRARY_REALNAME}\n");
124                 $self->output("\t\@mkdir -p \$(DESTDIR)\$(modulesdir)/$sane_subsystem/\n");
125                 $self->output("\t\@cp $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME} \$(DESTDIR)\$(modulesdir)/$sane_subsystem/$ctx->{LIBRARY_REALNAME}\n");
126                 if (defined($ctx->{ALIASES})) {
127                         foreach (@{$ctx->{ALIASES}}) {
128                                 $self->output("\t\@ln -fs $ctx->{LIBRARY_REALNAME} \$(DESTDIR)\$(modulesdir)/$sane_subsystem/$_.\$(SHLIBEXT)\n");
129                         }
130                 }
131
132                 $self->output("uninstallplugins::\n");
133                 $self->output("\t\@echo Uninstalling \$(DESTDIR)\$(modulesdir)/$sane_subsystem/$ctx->{LIBRARY_REALNAME}\n");
134                 $self->output("\t\@-rm \$(DESTDIR)\$(modulesdir)/$sane_subsystem/$ctx->{LIBRARY_REALNAME}\n");
135
136                 if (defined($ctx->{ALIASES})) {
137                         foreach (@{$ctx->{ALIASES}}) {
138                                 $self->output("\t\@-rm \$(DESTDIR)\$(modulesdir)/$sane_subsystem/$_.\$(SHLIBEXT)\n");
139                         }
140                 }
141         }
142
143         $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
144         $self->_prepare_list($ctx, "FULL_OBJ_LIST");
145         $self->_prepare_list($ctx, "DEPEND_LIST");
146         $self->_prepare_list($ctx, "LINK_FLAGS");
147
148         if (defined($ctx->{INIT_FUNCTION}) and $ctx->{TYPE} ne "PYTHON" and
149                 $ctx->{INIT_FUNCTION_TYPE} =~ /\(\*\)/) {
150                 $self->output("\$($ctx->{NAME}_OBJ_LIST): CFLAGS+=-D$ctx->{INIT_FUNCTION}=init_module\n");
151         }
152
153         $self->output(<< "__EOD__"
154
155 $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}: \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST)
156         \@echo Linking \$\@
157         \@mkdir -p \$(\@D)
158         \@\$(MDLD) \$(LDFLAGS) \$(MDLD_FLAGS) \$(INTERN_LDFLAGS) -o \$\@ \$(INSTALL_LINK_FLAGS) \\
159                 \$($ctx->{NAME}\_FULL_OBJ_LIST) \\
160                 \$($ctx->{NAME}_LINK_FLAGS)
161 __EOD__
162 );
163
164         if (defined($ctx->{ALIASES})) {
165                 foreach (@{$ctx->{ALIASES}}) {
166                         $self->output("\t\@ln -fs $ctx->{LIBRARY_REALNAME} $ctx->{SHAREDDIR}/$_.\$(SHLIBEXT)\n");
167                 }
168         }
169         $self->output("\n");
170 }
171
172 sub SharedLibraryPrimitives($$)
173 {
174         my ($self,$ctx) = @_;
175
176         $self->output("$ctx->{NAME}_SOVERSION = $ctx->{SO_VERSION}\n") if (defined($ctx->{SO_VERSION}));
177         $self->output("$ctx->{NAME}_VERSION = $ctx->{VERSION}\n") if (defined($ctx->{VERSION}));
178
179         if (not grep(/STATIC_LIBRARY/, @{$ctx->{OUTPUT_TYPE}})) {
180                 $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
181                 $self->_prepare_list($ctx, "FULL_OBJ_LIST");
182         }
183 }
184
185 sub SharedLibrary($$)
186 {
187         my ($self,$ctx) = @_;
188
189         $self->output("SHARED_LIBS += $ctx->{RESULT_SHARED_LIBRARY}\n") if (defined($ctx->{SO_VERSION}));
190
191         $self->_prepare_list($ctx, "DEPEND_LIST");
192         $self->_prepare_list($ctx, "LINK_FLAGS");
193
194         $self->output(<< "__EOD__"
195
196 $ctx->{RESULT_SHARED_LIBRARY}: \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST)
197         \@echo Linking \$\@
198         \@mkdir -p $ctx->{SHAREDDIR}
199         \@\$(SHLD) \$(LDFLAGS) \$(SHLD_FLAGS) \$(INTERN_LDFLAGS) -o \$\@ \$(INSTALL_LINK_FLAGS) \\
200                 \$($ctx->{NAME}\_FULL_OBJ_LIST) \\
201                 \$($ctx->{NAME}_LINK_FLAGS) \\
202                 \$(if \$(SONAMEFLAG), \$(SONAMEFLAG)$ctx->{LIBRARY_SONAME})
203 __EOD__
204 );
205         if ($ctx->{LIBRARY_REALNAME} ne $ctx->{LIBRARY_SONAME}) {
206                 $self->output("\t\@test \$($ctx->{NAME}_VERSION) = \$($ctx->{NAME}_SOVERSION) || ln -fs $ctx->{LIBRARY_REALNAME} $ctx->{SHAREDDIR}/$ctx->{LIBRARY_SONAME}\n");
207         }
208         $self->output("ifdef $ctx->{NAME}_SOVERSION\n");
209         $self->output("\t\@ln -fs $ctx->{LIBRARY_REALNAME} $ctx->{SHAREDDIR}/$ctx->{LIBRARY_DEBUGNAME}\n");
210         $self->output("endif\n");
211 }
212
213 sub MergedObj($$)
214 {
215         my ($self, $ctx) = @_;
216
217         return unless defined($ctx->{OUTPUT});
218
219         $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
220         $self->output(<< "__EOD__"
221 #
222 $ctx->{RESULT_MERGED_OBJ}: \$($ctx->{NAME}_OBJ_LIST)
223         \@echo Partially linking \$@
224         \@mkdir -p bin/mergedobj
225         \$(PARTLINK) -o \$@ \$($ctx->{NAME}_OBJ_LIST)
226
227 __EOD__
228 );
229 }
230
231 sub StaticLibraryPrimitives($$)
232 {
233         my ($self,$ctx) = @_;
234
235         return unless (defined($ctx->{OBJ_FILES}));
236
237         push (@{$self->{static_libs}}, $ctx->{RESULT_STATIC_LIBRARY}) if ($ctx->{TYPE} eq "LIBRARY");
238
239         $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
240         $self->_prepare_list($ctx, "FULL_OBJ_LIST");
241 }
242
243 sub InitFunctions($$)
244 {
245         my ($self, $ctx) = @_;
246         $self->output("\$($ctx->{NAME}_OBJ_LIST): CFLAGS+=-DSTATIC_$ctx->{NAME}_MODULES=\"\\\"\$($ctx->{NAME}_INIT_FUNCTIONS)$ctx->{INIT_FUNCTION_SENTINEL}\\\"\"\n");
247 }
248
249 sub StaticLibrary($$)
250 {
251         my ($self,$ctx) = @_;
252
253         return unless (defined($ctx->{OBJ_FILES}));
254
255         $self->output("STATIC_LIBS += $ctx->{RESULT_STATIC_LIBRARY}\n") if ($ctx->{TYPE} eq "LIBRARY");
256         $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
257         $self->output("$ctx->{RESULT_STATIC_LIBRARY}: \$($ctx->{NAME}_FULL_OBJ_LIST)\n");
258 }
259
260 sub Header($$)
261 {
262         my ($self,$ctx) = @_;
263
264         return if ($#{$ctx->{PUBLIC_HEADERS}} == -1);
265
266         $self->output("PUBLIC_HEADERS += \$(realpath \$(addprefix $ctx->{BASEDIR}/, " . join(" ", @{$ctx->{PUBLIC_HEADERS}}) . "))\n");
267 }
268
269 sub Binary($$)
270 {
271         my ($self,$ctx) = @_;
272
273         unless (defined($ctx->{INSTALLDIR})) {
274         } elsif ($ctx->{INSTALLDIR} eq "SBINDIR") {
275                 $self->output("SBIN_PROGS += $ctx->{RESULT_BINARY}\n");
276         } elsif ($ctx->{INSTALLDIR} eq "BINDIR") {
277                 $self->output("BIN_PROGS += $ctx->{RESULT_BINARY}\n");
278         }
279
280         $self->output("binaries:: $ctx->{TARGET_BINARY}\n");
281
282         $self->_prepare_list($ctx, "FULL_OBJ_LIST");
283         $self->_prepare_list($ctx, "DEPEND_LIST");
284         $self->_prepare_list($ctx, "LINK_FLAGS");
285
286 $self->output(<< "__EOD__"
287 $ctx->{RESULT_BINARY}: \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST)
288         \@echo Linking \$\@
289 __EOD__
290         );
291
292         if (defined($ctx->{USE_HOSTCC}) && $ctx->{USE_HOSTCC} eq "YES") {
293                 $self->output(<< "__EOD__"
294         \@\$(HOSTLD) \$(HOSTLD_FLAGS) -L\${builddir}/bin/static -o \$\@ \$(INSTALL_LINK_FLAGS) \\
295                 \$\($ctx->{NAME}_LINK_FLAGS)
296 __EOD__
297                 );
298         } else {
299                 $self->output(<< "__EOD__"
300         \@\$(BNLD) \$(BNLD_FLAGS) \$(INTERN_LDFLAGS) -o \$\@ \$(INSTALL_LINK_FLAGS) \\
301                 \$\($ctx->{NAME}_LINK_FLAGS) 
302
303 __EOD__
304                 );
305         }
306 }
307
308 sub PythonFiles($$)
309 {
310         my ($self,$ctx) = @_;
311
312         foreach (@{$ctx->{PYTHON_FILES}}) {
313                 my $target = "bin/python/".basename($_);
314                 $self->output("$target: \$(realpath \$(addprefix $ctx->{BASEDIR}/, $_))\n\n");
315                 $self->output("PYTHON_PYS += $target\n");
316         }
317 }
318
319 sub Manpage($$)
320 {
321         my ($self,$ctx) = @_;
322
323         $self->output("MANPAGES += \$(realpath \$(addprefix $ctx->{BASEDIR}/, $ctx->{MANPAGE}))\n");
324 }
325
326 sub ProtoHeader($$)
327 {
328         my ($self,$ctx) = @_;
329
330         my $target = "";
331         my $comment = "Creating ";
332
333         my $priv = undef;
334         my $pub = undef;
335
336         if (defined($ctx->{PRIVATE_PROTO_HEADER})) {
337                 $priv = "\$(realpath \$(addprefix $ctx->{BASEDIR}/, $ctx->{PRIVATE_PROTO_HEADER}))";
338                 $target .= $priv;
339                 $comment .= $priv;
340                 if (defined($ctx->{PUBLIC_PROTO_HEADER})) {
341                         $comment .= " and ";
342                         $target.= " ";
343                 }
344                 $self->output("PROTO_HEADERS += $priv\n");
345         } else {
346                 $ctx->{PRIVATE_PROTO_HEADER} = $ctx->{PUBLIC_PROTO_HEADER};
347                 $priv = "\$(realpath \$(addprefix $ctx->{BASEDIR}/, $ctx->{PRIVATE_PROTO_HEADER}))";
348         }
349
350         if (defined($ctx->{PUBLIC_PROTO_HEADER})) {
351                 $pub = "\$(realpath \$(addprefix $ctx->{BASEDIR}/, $ctx->{PUBLIC_PROTO_HEADER}))";
352                 $comment .= $pub;
353                 $target .= $pub;
354                 $self->output("PROTO_HEADERS += $pub\n");
355         } else {
356                 $ctx->{PUBLIC_PROTO_HEADER} = $ctx->{PRIVATE_PROTO_HEADER};
357                 $pub = "\$(realpath \$(addprefix $ctx->{BASEDIR}/, $ctx->{PUBLIC_PROTO_HEADER}))";
358         }
359
360         $self->output("$pub: $ctx->{MK_FILE} \$($ctx->{NAME}_OBJ_LIST:.o=.c) \$(srcdir)/script/mkproto.pl\n");
361         $self->output("\t\@echo \"$comment\"\n");
362         $self->output("\t\@\$(PERL) \$(srcdir)/script/mkproto.pl --srcdir=\$(srcdir) --builddir=\$(builddir) --private=$priv --public=$pub \$($ctx->{NAME}_OBJ_LIST)\n\n");
363 }
364
365 sub write($$)
366 {
367         my ($self, $file) = @_;
368
369         $self->_prepare_mk_files();
370
371         $self->output($self->{mkfile});
372
373         if ($self->{automatic_deps}) {
374                 $self->output("
375 ifneq (\$(MAKECMDGOALS),clean)
376 ifneq (\$(MAKECMDGOALS),distclean)
377 ifneq (\$(MAKECMDGOALS),realdistclean)
378 ifneq (\$(SKIP_DEP_FILES),yes)
379 -include \$(DEP_FILES)
380 endif
381 endif
382 endif
383 endif
384
385 ifneq (\$(SKIP_DEP_FILES),yes)
386 clean::
387         \@echo Removing dependency files
388         \@find . -name '*.d' -o -name '*.hd' | xargs rm -f
389 endif
390 ");
391         } else {
392                 $self->output("include \$(srcdir)/static_deps.mk\n");
393         }
394
395         open(MAKEFILE,">$file") || die ("Can't open $file\n");
396         print MAKEFILE $self->{output};
397         close(MAKEFILE);
398
399         print __FILE__.": creating $file\n";
400 }
401
402 1;