summaryrefslogtreecommitdiff
path: root/source4/build/smb_build
diff options
context:
space:
mode:
Diffstat (limited to 'source4/build/smb_build')
-rw-r--r--source4/build/smb_build/README.txt83
-rw-r--r--source4/build/smb_build/TODO25
-rw-r--r--source4/build/smb_build/config_mk.pm284
-rwxr-xr-xsource4/build/smb_build/dot.pl63
-rw-r--r--source4/build/smb_build/input.pm277
-rw-r--r--source4/build/smb_build/main.pl104
-rw-r--r--source4/build/smb_build/makefile.pm281
-rw-r--r--source4/build/smb_build/output.pm172
-rw-r--r--source4/build/smb_build/summary.pm79
9 files changed, 1368 insertions, 0 deletions
diff --git a/source4/build/smb_build/README.txt b/source4/build/smb_build/README.txt
new file mode 100644
index 0000000000..eac3905cce
--- /dev/null
+++ b/source4/build/smb_build/README.txt
@@ -0,0 +1,83 @@
+The Samba Build System
+======================
+
+The build system basically has two main parts: the autoconf-generated
+shell scripts which check for availability of functions and libraries
+which is stored in the .m4 files and the information about the various
+subsystems which is stored in the .mk files.
+
+Object Types
+------------
+the build system knows about the following object types
+
+SUBSYSTEM:
+ a SUBSYSTEM is basicly a collection of functions, which provide an
+ an generic API for a specific problem (e.g. libldb provides an api
+ for gneric ldb databases. libldb_plugin provides a generic api
+ for calling ldb plugins, so 'libldb' and 'libldb_plugin' are subsystems)
+
+MODULE:
+ a MODULE is a specify implementation of a API provided by a SUBSYSTEM.
+ (e.g. 'libldb_tdb' and 'libldb_ldap' are implementations of the subsystem 'libldb' API,
+ and 'libldb_plugin_timestamp' is a module of the 'libldb_plugin' subsystem)
+
+EXT_LIB:
+ an EXT_LIB is an external library which is needed by a SUBSYSTEM, MODULE, BINARY or LIBRARY.
+ (e.g. 'gtk' or 'KRB5')
+
+BINARY:
+ a BINARY means a executable binary file.
+ (e.g. 'smbtorture' or 'ldbedit')
+ a BINARY typically has only commandline handling and basic
+ functionality code in it and depends on the functions of
+ SUBSYSTEM's (REQUIRED_SUBSYSTEMS).
+
+LIBRARY:
+ a LIBRARY means a static and/or shared library,
+ which depends on the used OS.
+ (e.g. for libldb 'libldb.so', 'libldb.so.0' 'libldb.so.0.0.1'
+ and libldb.a are created on linux)
+ a LIBRARY typicly has only glue code in it and depends on
+ SUBSYSTEM's (REQUIRED_SUBSYSTEMS).
+
+File summary:
+-------------
+public.m4 - public M4 macros of the build system
+config_mk.pm - Support for reading .mk files
+dot.pm - Support for generating .dot files for analysis of dependencies
+input.pm - Input validation
+main.pm - Main
+makefile.pm - Makefile generation
+output.pm - Dependency calculation
+
+Layout
+-------
+
+Toplevel file: configure.in
+- included by autogen.sh: aclocal.m4
+ which includes the SMB_YXZ*() macros
+
+- default tests of the build system
+ are in build/smb_build/check_*.m4
+ (mostly compiler and basic C type and function
+ checks)
+
+- subsystem specific stuff should be included by 'SMB_INCLUDE_M4()'
+
+
+Generating the configure file
+-------------------------
+you need to rerun ./autogen.sh when 'configure.in' or any
+'.m4' file was modified, then you need to rerun configure.
+
+
+Generating config.status
+-----------------------------
+you need to run ./config.status (or 'configure') after a '.mk'
+file was changed.
+
+
+Examples
+--------
+for now please take a look at the .m4 and .mk files
+you find in the source tree, they should be a good reference to start.
diff --git a/source4/build/smb_build/TODO b/source4/build/smb_build/TODO
new file mode 100644
index 0000000000..adfe17d423
--- /dev/null
+++ b/source4/build/smb_build/TODO
@@ -0,0 +1,25 @@
+- use pkg-config files in the buildsystem?
+- let the build system implement some make functions($(patsubst),$(wildcard),...) and use our own implementations where `make' does not support them
+- include extra_flags.txt using Makefile construction if
+ supported by current make
+- fix shared module loading for selftest during builds without install
+- remove recursive dependency between LIBSOCKET, LIBCLI_NBT and LIBCLI_RESOLVE
+- clearer distinction between dcerpc and ndr. seperate interface tables? Maybe get rid of
+ NDR's table altogether and use dlopen/dlsym ?
+- saner names for:
+ libcli.so.0.0.1 (rename to libsmb?)
+ libcli_cldap.so.0.0.1 (rename to libcldap?)
+ libcli_nbt.so.0.0.1 (rename to libnbt?)
+ libcli_wrepl.so.0.0.1 (rename to libwrepl?)
+- generate headermap.txt
+
+set of test scripts that check the code:
+- configure_check_unused.pl
+- find_unused_macros.pl
+- find_unused_makefilevars.pl
+- find_unused_options.sh
+- findstatic.pl
+- minimal_includes.pl
+- check dependencies based on #include lines ?
+- check whether private headers are not used outside their own subsystem
+- undocumented (no manpage) installed binaries
diff --git a/source4/build/smb_build/config_mk.pm b/source4/build/smb_build/config_mk.pm
new file mode 100644
index 0000000000..8c7d75221c
--- /dev/null
+++ b/source4/build/smb_build/config_mk.pm
@@ -0,0 +1,284 @@
+# Samba Build System
+# - config.mk parsing functions
+#
+# Copyright (C) Stefan (metze) Metzmacher 2004
+# Copyright (C) Jelmer Vernooij 2005
+# Released under the GNU GPL
+#
+
+package smb_build::config_mk;
+use smb_build::input;
+use File::Basename;
+
+use strict;
+
+my $section_types = {
+ "EXT_LIB" => {
+ "LIBS" => "list",
+ "CFLAGS" => "list",
+ "CPPFLAGS" => "list",
+ "LDFLAGS" => "list",
+ },
+ "PYTHON" => {
+ "LIBRARY_REALNAME" => "string",
+ "PRIVATE_DEPENDENCIES" => "list",
+ "PUBLIC_DEPENDENCIES" => "list",
+ "ENABLE" => "bool",
+ "LDFLAGS" => "list",
+ },
+ "SUBSYSTEM" => {
+ "PRIVATE_DEPENDENCIES" => "list",
+ "PUBLIC_DEPENDENCIES" => "list",
+
+ "ENABLE" => "bool",
+
+ "CFLAGS" => "list",
+ "LDFLAGS" => "list",
+ "STANDARD_VISIBILITY" => "string",
+ "INIT_FUNCTION_SENTINEL" => "string"
+ },
+ "MODULE" => {
+ "SUBSYSTEM" => "string",
+
+ "INIT_FUNCTION" => "string",
+
+ "PRIVATE_DEPENDENCIES" => "list",
+
+ "ALIASES" => "list",
+
+ "ENABLE" => "bool",
+
+ "OUTPUT_TYPE" => "list",
+
+ "CFLAGS" => "list"
+ },
+ "BINARY" => {
+
+ "PRIVATE_DEPENDENCIES" => "list",
+
+ "ENABLE" => "bool",
+
+ "INSTALLDIR" => "string",
+ "LDFLAGS" => "list",
+ "STANDARD_VISIBILITY" => "string",
+
+ "USE_HOSTCC" => "bool"
+ },
+ "LIBRARY" => {
+ "LIBRARY_REALNAME" => "string",
+
+ "INIT_FUNCTION_TYPE" => "string",
+ "INIT_FUNCTION_SENTINEL" => "string",
+ "OUTPUT_TYPE" => "list",
+
+ "PRIVATE_DEPENDENCIES" => "list",
+ "PUBLIC_DEPENDENCIES" => "list",
+
+ "ENABLE" => "bool",
+
+ "CFLAGS" => "list",
+ "LDFLAGS" => "list",
+ "STANDARD_VISIBILITY" => "string"
+ }
+};
+
+use vars qw(@parsed_files);
+
+@parsed_files = ();
+
+sub _read_config_file($$$)
+{
+ use Cwd;
+
+ my ($srcdir, $builddir, $filename) = @_;
+ my @dirlist;
+
+ # We need to change our working directory because config.mk files can
+ # give shell commands as the argument to "include". These shell
+ # commands can take arguments that are relative paths and we don't have
+ # a way of sensibly rewriting these.
+ my $cwd = getcwd;
+ chomp $cwd;
+
+ if ($srcdir ne $builddir) {
+ # Push the builddir path on the front, so we prefer builddir
+ # to srcdir when the file exists in both.
+ @dirlist = ($builddir, $srcdir);
+ } else {
+ @dirlist = ($srcdir);
+ }
+
+ foreach my $d (@dirlist) {
+ my @lines;
+ my $basedir;
+
+ chdir $cwd;
+ chdir $d;
+
+ # We need to catch the exception from open in the case where
+ # the filename is actually a shell pipeline. Why is this
+ # different to opening a regular file? Because this is perl!
+ eval {
+ open(CONFIG_MK, "./$filename");
+ @lines = <CONFIG_MK>;
+ close(CONFIG_MK);
+ };
+
+ chdir $cwd;
+ next unless (@lines);
+
+ # I blame abartlett for this crazy hack -- jpeach
+ if ($filename =~ /\|$/) {
+ $basedir = $builddir;
+ } else {
+ $basedir = dirname($filename);
+ push(@parsed_files, $filename);
+ }
+ $basedir =~ s!^($builddir|$srcdir)[/]!!;
+ return ($filename, $basedir, @lines);
+ }
+
+ chdir $cwd;
+ return;
+}
+
+###########################################################
+# The parsing function which parses the file
+#
+# $result = _parse_config_mk($input, $srcdir, $builddir, $filename)
+#
+# $filename - the path of the config.mk file
+# which should be parsed
+sub run_config_mk($$$$)
+{
+ sub run_config_mk($$$$);
+ my ($input, $srcdir, $builddir, $filename) = @_;
+ my $result;
+ my $linenum = -1;
+ my $infragment = 0;
+ my $section = "GLOBAL";
+ my $makefile = "";
+
+ my $basedir;
+
+ my $parsing_file;
+ my @lines;
+
+ $ENV{builddir} = $builddir;
+ $ENV{srcdir} = $srcdir;
+
+ ($parsing_file, $basedir, @lines) =
+ _read_config_file($srcdir, $builddir, $filename);
+
+ die ("$0: can't open '$filename'")
+ unless ($parsing_file and $basedir and @lines);
+
+ my $line = "";
+ my $prev = "";
+
+ # Emit a line that lets us match up final makefile output with the
+ # corresponding input files. The curlies are so you can match the
+ # BEGIN/END pairs in a text editor.
+ $makefile .= "# BEGIN{ $parsing_file\n";
+
+ foreach (@lines) {
+ $linenum++;
+
+ # lines beginning with '#' are ignored
+ next if (/^\#.*$/);
+
+ if (/^(.*)\\$/) {
+ $prev .= $1;
+ next;
+ } else {
+ $line = "$prev$_";
+ $prev = "";
+ }
+
+ if ($line =~ /^\[([-a-zA-Z0-9_.:]+)\][\t ]*$/)
+ {
+ $section = $1;
+ $infragment = 0;
+
+ $result->{$section}{EXISTS}{KEY} = "EXISTS";
+ $result->{$section}{EXISTS}{VAL} = 1;
+ next;
+ }
+
+ # include
+ if ($line =~ /^mkinclude (.*)$/) {
+ my $subfile= $1;
+ my $subdir = dirname($filename);
+ $subdir =~ s/^\.$//g;
+ $subdir =~ s/^\.\///g;
+ $subdir .= "/" if ($subdir ne "");
+ $makefile .= "basedir := $subdir\n";
+ $makefile .= run_config_mk($input, $srcdir, $builddir, $subdir.$subfile);
+ next;
+ }
+
+ # empty line
+ if ($line =~ /^[ \t]*$/) {
+ $section = "GLOBAL";
+ if ($infragment) { $makefile.="\n"; }
+ next;
+ }
+
+ # global stuff is considered part of the makefile
+ if ($section eq "GLOBAL") {
+ if (!$infragment) { $makefile.="\n"; }
+ $makefile .= $line;
+ $infragment = 1;
+ next;
+ }
+
+ # Assignment
+ if ($line =~ /^([a-zA-Z0-9_]+)[\t ]*=(.*)$/) {
+ $result->{$section}{$1}{VAL} = $2;
+ $result->{$section}{$1}{KEY} = $1;
+
+ next;
+ }
+
+ die("$parsing_file:$linenum: Bad line");
+ }
+
+ $makefile .= "# }END $parsing_file\n";
+
+ foreach my $section (keys %{$result}) {
+ my ($type, $name) = split(/::/, $section, 2);
+
+ my $sectype = $section_types->{$type};
+ if (not defined($sectype)) {
+ die($parsing_file.":[".$section."] unknown section type \"".$type."\"!");
+ }
+
+ $input->{$name}{NAME} = $name;
+ $input->{$name}{TYPE} = $type;
+ $input->{$name}{MK_FILE} = $parsing_file;
+ $input->{$name}{BASEDIR} = $basedir;
+
+ foreach my $key (values %{$result->{$section}}) {
+ next if ($key->{KEY} eq "EXISTS");
+ $key->{VAL} = smb_build::input::strtrim($key->{VAL});
+ my $vartype = $sectype->{$key->{KEY}};
+ if (not defined($vartype)) {
+ die($parsing_file.":[".$section."]: unknown attribute type \"$key->{KEY}\"!");
+ }
+ if ($vartype eq "string") {
+ $input->{$name}{$key->{KEY}} = $key->{VAL};
+ } elsif ($vartype eq "list") {
+ $input->{$name}{$key->{KEY}} = [smb_build::input::str2array($key->{VAL})];
+ } elsif ($vartype eq "bool") {
+ if (($key->{VAL} ne "YES") and ($key->{VAL} ne "NO")) {
+ die("Invalid value for bool attribute $key->{KEY}: $key->{VAL} in section $section");
+ }
+ $input->{$name}{$key->{KEY}} = $key->{VAL};
+ }
+ }
+ }
+
+ return $makefile;
+}
+
+1;
diff --git a/source4/build/smb_build/dot.pl b/source4/build/smb_build/dot.pl
new file mode 100755
index 0000000000..b30c320c6e
--- /dev/null
+++ b/source4/build/smb_build/dot.pl
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+# Samba4 Dependency Graph Generator
+# (C) 2004-2005 Jelmer Vernooij <jelmer@samba.org>
+# Published under the GNU GPL
+
+use strict;
+use lib 'build';
+use smb_build::config_mk;
+
+my $subsys = shift @ARGV;
+
+sub contains($$)
+{
+ my ($haystack,$needle) = @_;
+ foreach (@$haystack) {
+ return 1 if ($_ eq $needle);
+ }
+ return 0;
+}
+
+sub generate($$$)
+{
+ my ($depend,$only,$name) = @_;
+ my $res = "digraph $name {\n";
+
+ foreach my $part (values %{$depend}) {
+ next if (defined($only) and not contains($only,$part->{NAME}));
+ foreach my $elem (@{$part->{PUBLIC_DEPENDENCIES}}) {
+ $res .= "\t\"$part->{NAME}\" -> \"$elem\" [style=filled]; /* public */\n";
+ }
+ foreach my $elem (@{$part->{PRIVATE_DEPENDENCIES}}) {
+ $res .= "\t\"$part->{NAME}\" -> \"$elem\" [style=dotted]; /* private */\n";
+ }
+ }
+
+ return $res . "}\n";
+}
+
+my $INPUT = {};
+smb_build::config_mk::run_config_mk($INPUT, '.', '.', "main.mk");
+
+my $name = "samba4";
+
+my $only;
+if (defined($subsys)) {
+ my $DEPEND = smb_build::input::check($INPUT, \%config::enabled,
+ "MERGED_OBJ", "SHARED_LIBRARY", "SHARED_LIBRARY");
+
+ die("No such subsystem $subsys") unless (defined($DEPEND->{$subsys}));
+
+ $only = $DEPEND->{$subsys}->{UNIQUE_DEPENDENCIES_ALL};
+ push (@$only, "$subsys");
+
+ $name = $subsys;
+}
+
+my $fname = "$name-deps.dot";
+print __FILE__.": creating $fname\n";
+open DOTTY, ">$fname";
+print DOTTY generate($INPUT, $only, $name);
+close DOTTY;
+
+1;
diff --git a/source4/build/smb_build/input.pm b/source4/build/smb_build/input.pm
new file mode 100644
index 0000000000..1696a364b2
--- /dev/null
+++ b/source4/build/smb_build/input.pm
@@ -0,0 +1,277 @@
+# Samba Build System
+# - the input checking functions
+#
+# Copyright (C) Stefan (metze) Metzmacher 2004
+# Copyright (C) Jelmer Vernooij 2004
+# Released under the GNU GPL
+
+use strict;
+package smb_build::input;
+use File::Basename;
+
+sub strtrim($)
+{
+ $_ = shift;
+ s/^[\t\n ]*//g;
+ s/[\t\n ]*$//g;
+ return $_;
+}
+
+sub str2array($)
+{
+ $_ = shift;
+ s/^[\t\n ]*//g;
+ s/[\t\n ]*$//g;
+ s/([\t\n ]+)/ /g;
+
+ return () if (length($_)==0);
+ return split /[ \t\n]/;
+}
+
+sub add_libreplace($)
+{
+ my ($part) = @_;
+
+ return if ($part->{NAME} eq "LIBREPLACE");
+ return if ($part->{NAME} eq "LIBREPLACE_HOSTCC");
+ return if ($part->{NAME} eq "REPLACE_READDIR");
+
+ foreach my $n (@{$part->{PRIVATE_DEPENDENCIES}}) {
+ return if ($n eq "LIBREPLACE");
+ return if ($n eq "LIBREPLACE_HOSTCC");
+ }
+ foreach my $n (@{$part->{PUBLIC_DEPENDENCIES}}) {
+ return if ($n eq "LIBREPLACE");
+ return if ($n eq "LIBREPLACE_HOSTCC");
+ }
+
+ if (defined($part->{USE_HOSTCC}) && $part->{USE_HOSTCC} eq "YES") {
+ unshift (@{$part->{PRIVATE_DEPENDENCIES}}, "LIBREPLACE_HOSTCC");
+ } else {
+ unshift (@{$part->{PRIVATE_DEPENDENCIES}}, "LIBREPLACE");
+ }
+}
+
+sub check_subsystem($$$)
+{
+ my ($INPUT, $subsys, $default_ot) = @_;
+ return if ($subsys->{ENABLE} ne "YES");
+
+ unless (defined($subsys->{OUTPUT_TYPE})) { $subsys->{OUTPUT_TYPE} = $default_ot; }
+ unless (defined($subsys->{INIT_FUNCTION_TYPE})) { $subsys->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
+ unless (defined($subsys->{INIT_FUNCTION_SENTINEL})) { $subsys->{INIT_FUNCTION_SENTINEL} = "NULL"; }
+}
+
+sub check_module($$$)
+{
+ my ($INPUT, $mod, $default_ot) = @_;
+
+ die("Module $mod->{NAME} does not have a SUBSYSTEM set") if not defined($mod->{SUBSYSTEM});
+
+ if (not exists($INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS})) {
+ $INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS} = [];
+ }
+
+ if (!(defined($INPUT->{$mod->{SUBSYSTEM}}))) {
+ die("Unknown subsystem $mod->{SUBSYSTEM} for module $mod->{NAME}");
+ }
+
+ if ($INPUT->{$mod->{SUBSYSTEM}} eq "NO") {
+ warn("Disabling module $mod->{NAME} because subsystem $mod->{SUBSYSTEM} is disabled");
+ $mod->{ENABLE} = "NO";
+ return;
+ }
+
+ return if ($mod->{ENABLE} ne "YES");
+
+ if (exists($INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTION_TYPE})) {
+ $mod->{INIT_FUNCTION_TYPE} = $INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTION_TYPE};
+ } else {
+ $mod->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)";
+ }
+
+ unless (defined($mod->{INIT_FUNCTION_SENTINEL})) { $mod->{INIT_FUNCTION_SENTINEL} = "NULL"; }
+
+ if (not defined($mod->{OUTPUT_TYPE})) {
+ if ((not defined($INPUT->{$mod->{SUBSYSTEM}}->{TYPE})) or
+ $INPUT->{$mod->{SUBSYSTEM}}->{TYPE} eq "EXT_LIB") {
+ $mod->{OUTPUT_TYPE} = undef;
+ } else {
+ $mod->{OUTPUT_TYPE} = $default_ot;
+ }
+ }
+
+ if (grep(/SHARED_LIBRARY/, @{$mod->{OUTPUT_TYPE}})) {
+ my $sane_subsystem = lc($mod->{SUBSYSTEM});
+ $sane_subsystem =~ s/^lib//;
+ $mod->{INSTALLDIR} = "MODULESDIR/$sane_subsystem";
+ push (@{$mod->{PUBLIC_DEPENDENCIES}}, $mod->{SUBSYSTEM});
+ add_libreplace($mod);
+ }
+ if (grep(/MERGED_OBJ/, @{$mod->{OUTPUT_TYPE}})) {
+ push (@{$INPUT->{$mod->{SUBSYSTEM}}{INIT_FUNCTIONS}}, $mod->{INIT_FUNCTION}) if defined($mod->{INIT_FUNCTION});
+ push (@{$INPUT->{$mod->{SUBSYSTEM}}{PRIVATE_DEPENDENCIES}}, $mod->{NAME});
+ }
+}
+
+sub check_library($$$)
+{
+ my ($INPUT, $lib, $default_ot) = @_;
+
+ return if ($lib->{ENABLE} ne "YES");
+
+ unless (defined($lib->{OUTPUT_TYPE})) { $lib->{OUTPUT_TYPE} = $default_ot; }
+
+ unless (defined($lib->{INIT_FUNCTION_TYPE})) { $lib->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
+ unless (defined($lib->{INIT_FUNCTION_SENTINEL})) { $lib->{INIT_FUNCTION_SENTINEL} = "NULL"; }
+ unless (defined($lib->{INSTALLDIR})) { $lib->{INSTALLDIR} = "LIBDIR"; }
+
+ add_libreplace($lib);
+}
+
+sub check_python($$$)
+{
+ my ($INPUT, $python, $default_ot) = @_;
+
+ return if ($INPUT->{LIBPYTHON}{ENABLE} ne "YES");
+
+ $python->{INSTALLDIR} = "PYTHONDIR";
+ unless (defined($python->{CFLAGS})) { $python->{CFLAGS} = []; }
+ my $basename = $python->{NAME};
+ $basename =~ s/^python_//g;
+ unless (defined($python->{LIBRARY_REALNAME})) {
+ $python->{LIBRARY_REALNAME} = "$basename.\$(SHLIBEXT)";
+ }
+ $python->{INIT_FUNCTION} = "{ (char *)\"$basename\", init$basename }";
+ push (@{$python->{CFLAGS}}, "\$(EXT_LIB_PYTHON_CFLAGS)");
+
+ $python->{SUBSYSTEM} = "LIBPYTHON";
+
+ check_module($INPUT, $python, $default_ot);
+}
+
+sub check_binary($$)
+{
+ my ($INPUT, $bin) = @_;
+
+ return if ($bin->{ENABLE} ne "YES");
+
+ ($bin->{BINARY} = (lc $bin->{NAME})) if not defined($bin->{BINARY});
+ unless (defined($bin->{INIT_FUNCTION_SENTINEL})) { $bin->{INIT_FUNCTION_SENTINEL} = "NULL"; }
+ unless (defined($bin->{INIT_FUNCTION_TYPE})) { $bin->{INIT_FUNCTION_TYPE} = "NTSTATUS (*) (void)"; }
+
+ $bin->{OUTPUT_TYPE} = ["BINARY"];
+ add_libreplace($bin);
+}
+
+sub add_implicit($$)
+{
+ my ($INPUT, $n) = @_;
+
+ $INPUT->{$n}->{TYPE} = "MAKE_RULE";
+ $INPUT->{$n}->{NAME} = $n;
+ $INPUT->{$n}->{OUTPUT_TYPE} = undef;
+ $INPUT->{$n}->{LIBS} = ["\$(".uc($n)."_LIBS)"];
+ $INPUT->{$n}->{LDFLAGS} = ["\$(".uc($n)."_LDFLAGS)"];
+ $INPUT->{$n}->{CFLAGS} = ["\$(".uc($n)."_CFLAGS)"];
+ $INPUT->{$n}->{CPPFLAGS} = ["\$(".uc($n)."_CPPFLAGS)"];
+ $INPUT->{$n}->{ENABLE} = "YES";
+}
+
+sub calc_unique_deps($$$$$$$$)
+{
+ sub calc_unique_deps($$$$$$$$);
+ my ($name, $INPUT, $deps, $udeps, $withlibs, $forward, $pubonly, $busy) = @_;
+
+ foreach my $n (@$deps) {
+ add_implicit($INPUT, $n) unless (defined($INPUT->{$n}) and defined($INPUT->{$n}->{TYPE}));
+ my $dep = $INPUT->{$n};
+ if (grep (/^$n$/, @$busy)) {
+ next if (@{$dep->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ");
+ die("Recursive dependency: $n, list: " . join(',', @$busy));
+ }
+ next if (grep /^$n$/, @$udeps);
+
+ push (@{$udeps}, $n) if $forward;
+
+ if (defined ($dep->{OUTPUT_TYPE}) &&
+ ($withlibs or
+ (@{$dep->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ") or
+ (@{$dep->{OUTPUT_TYPE}}[0] eq "STATIC_LIBRARY"))) {
+ push (@$busy, $n);
+ calc_unique_deps($n, $INPUT, $dep->{PUBLIC_DEPENDENCIES}, $udeps, $withlibs, $forward, $pubonly, $busy);
+ calc_unique_deps($n, $INPUT, $dep->{PRIVATE_DEPENDENCIES}, $udeps, $withlibs, $forward, $pubonly, $busy) unless $pubonly;
+ pop (@$busy);
+ }
+
+ unshift (@{$udeps}, $n) unless $forward;
+ }
+}
+
+sub check($$$$$)
+{
+ my ($INPUT, $enabled, $subsys_ot, $lib_ot, $module_ot) = @_;
+
+ foreach my $part (values %$INPUT) {
+ if (defined($enabled->{$part->{NAME}})) {
+ $part->{ENABLE} = $enabled->{$part->{NAME}};
+ next;
+ }
+
+ unless(defined($part->{ENABLE})) {
+ if ($part->{TYPE} eq "EXT_LIB") {
+ $part->{ENABLE} = "NO";
+ } else {
+ $part->{ENABLE} = "YES";
+ }
+ }
+ }
+
+ foreach my $part (values %$INPUT) {
+ $part->{LINK_FLAGS} = [];
+ $part->{FULL_OBJ_LIST} = ["\$($part->{NAME}_OBJ_FILES)"];
+
+ if ($part->{TYPE} eq "SUBSYSTEM") {
+ check_subsystem($INPUT, $part, $subsys_ot);
+ } elsif ($part->{TYPE} eq "MODULE") {
+ check_module($INPUT, $part, $module_ot);
+ } elsif ($part->{TYPE} eq "LIBRARY") {
+ check_library($INPUT, $part, $lib_ot);
+ } elsif ($part->{TYPE} eq "BINARY") {
+ check_binary($INPUT, $part);
+ } elsif ($part->{TYPE} eq "PYTHON") {
+ check_python($INPUT, $part, $module_ot);
+ } elsif ($part->{TYPE} eq "EXT_LIB") {
+ } else {
+ die("Unknown type $part->{TYPE}");
+ }
+ }
+
+ foreach my $part (values %$INPUT) {
+ if (defined($part->{INIT_FUNCTIONS})) {
+ push (@{$part->{LINK_FLAGS}}, "\$(DYNEXP)");
+ }
+ }
+
+ foreach my $part (values %$INPUT) {
+ $part->{UNIQUE_DEPENDENCIES_LINK} = [];
+ calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_LINK}, 0, 0, 0, []);
+ calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_LINK}, 0, 0, 0, []);
+ }
+
+ foreach my $part (values %$INPUT) {
+ $part->{UNIQUE_DEPENDENCIES_COMPILE} = [];
+ calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_COMPILE}, 1, 1, 1, []);
+ calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_COMPILE}, 1, 1, 1, []);
+ }
+
+ foreach my $part (values %$INPUT) {
+ $part->{UNIQUE_DEPENDENCIES_ALL} = [];
+ calc_unique_deps($part->{NAME}, $INPUT, $part->{PUBLIC_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_ALL}, 1, 0, 0, []);
+ calc_unique_deps($part->{NAME}, $INPUT, $part->{PRIVATE_DEPENDENCIES}, $part->{UNIQUE_DEPENDENCIES_ALL}, 1, 0, 0, []);
+ }
+
+ return $INPUT;
+}
+
+1;
diff --git a/source4/build/smb_build/main.pl b/source4/build/smb_build/main.pl
new file mode 100644
index 0000000000..3c84a91a59
--- /dev/null
+++ b/source4/build/smb_build/main.pl
@@ -0,0 +1,104 @@
+# Samba Build System
+# - the main program
+#
+# Copyright (C) Stefan (metze) Metzmacher 2004
+# Copyright (C) Jelmer Vernooij 2005
+# Released under the GNU GPL
+
+use smb_build::makefile;
+use smb_build::input;
+use smb_build::config_mk;
+use smb_build::output;
+use smb_build::summary;
+use smb_build::config;
+use Getopt::Long;
+use strict;
+
+my $output_file = "data.mk";
+
+my $result = GetOptions (
+ 'output=s' => \$output_file);
+
+if (not $result) {
+ exit(1);
+}
+
+my $input_file = shift @ARGV;
+
+my $INPUT = {};
+my $mkfile = smb_build::config_mk::run_config_mk($INPUT, $config::config{srcdir}, $config::config{builddir}, $input_file);
+
+my $subsys_output_type = ["MERGED_OBJ"];
+
+my $library_output_type;
+my $useshared = (defined($ENV{USESHARED})?$ENV{USESHARED}:$config::config{USESHARED});
+
+if ($useshared eq "true") {
+ $library_output_type = ["SHARED_LIBRARY", "MERGED_OBJ"];
+} else {
+ $library_output_type = ["MERGED_OBJ"];
+ push (@$library_output_type, "SHARED_LIBRARY") if
+ ($config::config{BLDSHARED} eq "true")
+}
+
+my $module_output_type;
+if ($useshared eq "true") {
+ $module_output_type = ["SHARED_LIBRARY"];
+} else {
+ $module_output_type = ["MERGED_OBJ"];
+}
+
+my $DEPEND = smb_build::input::check($INPUT, \%config::enabled,
+ $subsys_output_type,
+ $library_output_type,
+ $module_output_type);
+my $OUTPUT = output::create_output($DEPEND, \%config::config);
+my $mkenv = new smb_build::makefile(\%config::config, $mkfile);
+
+my $shared_libs_used = 0;
+foreach my $key (values %$OUTPUT) {
+ next if ($key->{ENABLE} ne "YES");
+ push(@{$mkenv->{all_objs}}, "\$($key->{NAME}_OBJ_FILES)");
+}
+
+foreach my $key (values %$OUTPUT) {
+ next unless defined $key->{OUTPUT_TYPE};
+
+ $mkenv->StaticLibraryPrimitives($key) if grep(/STATIC_LIBRARY/, @{$key->{OUTPUT_TYPE}});
+ $mkenv->MergedObj($key) if grep(/MERGED_OBJ/, @{$key->{OUTPUT_TYPE}});
+ $mkenv->SharedLibraryPrimitives($key) if ($key->{TYPE} eq "LIBRARY") and
+ grep(/SHARED_LIBRARY/, @{$key->{OUTPUT_TYPE}});
+ if ($key->{TYPE} eq "LIBRARY" and
+ ${$key->{OUTPUT_TYPE}}[0] eq "SHARED_LIBRARY") {
+ $shared_libs_used = 1;
+ }
+ if ($key->{TYPE} eq "MODULE" and @{$key->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ" and defined($key->{INIT_FUNCTION})) {
+ $mkenv->output("$key->{SUBSYSTEM}_INIT_FUNCTIONS += $key->{INIT_FUNCTION},\n");
+ }
+ $mkenv->CFlags($key);
+}
+
+foreach my $key (values %$OUTPUT) {
+ next unless defined $key->{OUTPUT_TYPE};
+
+ $mkenv->Integrated($key) if grep(/INTEGRATED/, @{$key->{OUTPUT_TYPE}});
+}
+
+foreach my $key (values %$OUTPUT) {
+ next unless defined $key->{OUTPUT_TYPE};
+ $mkenv->StaticLibrary($key) if grep(/STATIC_LIBRARY/, @{$key->{OUTPUT_TYPE}});
+
+ $mkenv->SharedLibrary($key) if ($key->{TYPE} eq "LIBRARY") and
+ grep(/SHARED_LIBRARY/, @{$key->{OUTPUT_TYPE}});
+ $mkenv->SharedModule($key) if ($key->{TYPE} eq "MODULE" and
+ grep(/SHARED_LIBRARY/, @{$key->{OUTPUT_TYPE}}));
+ $mkenv->PythonModule($key) if ($key->{TYPE} eq "PYTHON");
+ $mkenv->Binary($key) if grep(/BINARY/, @{$key->{OUTPUT_TYPE}});
+ $mkenv->InitFunctions($key) if defined($key->{INIT_FUNCTIONS});
+}
+
+$mkenv->write($output_file);
+
+summary::show($OUTPUT, \%config::config);
+
+1;
diff --git a/source4/build/smb_build/makefile.pm b/source4/build/smb_build/makefile.pm
new file mode 100644
index 0000000000..d9cbca0614
--- /dev/null
+++ b/source4/build/smb_build/makefile.pm
@@ -0,0 +1,281 @@
+# Samba Build System
+# - create output for Makefile
+#
+# Copyright (C) Stefan (metze) Metzmacher 2004
+# Copyright (C) Jelmer Vernooij 2005
+# Released under the GNU GPL
+
+package smb_build::makefile;
+use smb_build::output;
+use File::Basename;
+use strict;
+
+use Cwd 'abs_path';
+
+sub new($$$)
+{
+ my ($myname, $config, $mkfile) = @_;
+ my $self = {};
+
+ bless($self, $myname);
+
+ $self->_set_config($config);
+
+ $self->{output} = "";
+
+ $self->output("################################################\n");
+ $self->output("# Autogenerated by build/smb_build/makefile.pm #\n");
+ $self->output("################################################\n");
+ $self->output("\n");
+ $self->output($mkfile);
+
+ return $self;
+}
+
+sub _set_config($$)
+{
+ my ($self, $config) = @_;
+
+ $self->{config} = $config;
+
+ if (not defined($self->{config}->{srcdir})) {
+ $self->{config}->{srcdir} = '.';
+ }
+
+ if (not defined($self->{config}->{builddir})) {
+ $self->{config}->{builddir} = '.';
+ }
+
+ if ($self->{config}->{prefix} eq "NONE") {
+ $self->{config}->{prefix} = $self->{config}->{ac_default_prefix};
+ }
+
+ if ($self->{config}->{exec_prefix} eq "NONE") {
+ $self->{config}->{exec_prefix} = $self->{config}->{prefix};
+ }
+}
+
+sub output($$)
+{
+ my ($self, $text) = @_;
+
+ $self->{output} .= $text;
+}
+
+sub _prepare_mk_files($)
+{
+ my $self = shift;
+ my @tmp = ();
+
+ foreach (@smb_build::config_mk::parsed_files) {
+ s/ .*$//g;
+ push (@tmp, $_);
+ }
+
+ $self->output("MK_FILES = " . array2oneperline(\@tmp) . "\n");
+}
+
+sub array2oneperline($)
+{
+ my $array = shift;
+ my $output = "";
+
+ foreach (@$array) {
+ next unless defined($_);
+
+ $output .= " \\\n\t\t$_";
+ }
+
+ return $output;
+}
+
+sub _prepare_list($$$)
+{
+ my ($self,$ctx,$var) = @_;
+ my @tmparr = ();
+
+ push(@tmparr, @{$ctx->{$var}}) if defined($ctx->{$var});
+
+ my $tmplist = array2oneperline(\@tmparr);
+ return if ($tmplist eq "");
+
+ $self->output("$ctx->{NAME}_$var =$tmplist\n");
+}
+
+sub PythonModule($$)
+{
+ my ($self,$ctx) = @_;
+
+ $self->_prepare_list($ctx, "FULL_OBJ_LIST");
+ $self->_prepare_list($ctx, "DEPEND_LIST");
+ $self->_prepare_list($ctx, "LINK_FLAGS");
+
+ $self->output("\$(eval \$(call python_c_module_template,$ctx->{LIBRARY_REALNAME},\$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST), \$($ctx->{NAME}\_FULL_OBJ_LIST) \$($ctx->{NAME}_LINK_FLAGS)))\n");
+}
+
+sub SharedModule($$)
+{
+ my ($self,$ctx) = @_;
+
+ my $sane_subsystem = lc($ctx->{SUBSYSTEM});
+ $sane_subsystem =~ s/^lib//;
+
+ $self->output("PLUGINS += $ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}\n");
+ $self->output("\$(eval \$(call shared_module_install_template,$sane_subsystem,$ctx->{LIBRARY_REALNAME}))\n");
+
+ $self->_prepare_list($ctx, "FULL_OBJ_LIST");
+ $self->_prepare_list($ctx, "DEPEND_LIST");
+ $self->_prepare_list($ctx, "LINK_FLAGS");
+
+ if (defined($ctx->{INIT_FUNCTION}) and $ctx->{INIT_FUNCTION_TYPE} =~ /\(\*\)/ and not ($ctx->{INIT_FUNCTION} =~ /\(/)) {
+ $self->output("\$($ctx->{NAME}_OBJ_FILES): CFLAGS+=-D$ctx->{INIT_FUNCTION}=init_module\n");
+ }
+
+ $self->output("\$(eval \$(call shared_module_template,$ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME}, \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST), \$($ctx->{NAME}\_FULL_OBJ_LIST) \$($ctx->{NAME}_LINK_FLAGS)))\n");
+
+
+ if (defined($ctx->{ALIASES})) {
+ $self->output("\$(eval \$(foreach alias,". join(' ', @{$ctx->{ALIASES}}) . ",\$(call shared_module_alias_template,$ctx->{SHAREDDIR}/$ctx->{LIBRARY_REALNAME},$sane_subsystem,\$(alias))))\n");
+ }
+}
+
+sub StaticLibraryPrimitives($$)
+{
+ my ($self,$ctx) = @_;
+
+ $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
+ $self->_prepare_list($ctx, "FULL_OBJ_LIST");
+}
+
+sub SharedLibraryPrimitives($$)
+{
+ my ($self,$ctx) = @_;
+
+ if (not grep(/STATIC_LIBRARY/, @{$ctx->{OUTPUT_TYPE}})) {
+ $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
+ $self->_prepare_list($ctx, "FULL_OBJ_LIST");
+ }
+}
+
+sub SharedLibrary($$)
+{
+ my ($self,$ctx) = @_;
+
+ $self->output("SHARED_LIBS += $ctx->{RESULT_SHARED_LIBRARY}\n");
+
+ $self->_prepare_list($ctx, "DEPEND_LIST");
+ $self->_prepare_list($ctx, "LINK_FLAGS");
+
+ $self->output("\$(eval \$(call shared_library_template,$ctx->{RESULT_SHARED_LIBRARY}, \$($ctx->{NAME}_DEPEND_LIST) \$($ctx->{NAME}_FULL_OBJ_LIST), \$($ctx->{NAME}\_FULL_OBJ_LIST) \$($ctx->{NAME}_LINK_FLAGS),$ctx->{SHAREDDIR}/$ctx->{LIBRARY_SONAME},$ctx->{SHAREDDIR}/$ctx->{LIBRARY_DEBUGNAME}))\n");
+}
+
+sub MergedObj($$)
+{
+ my ($self, $ctx) = @_;
+
+ $self->output("\$(call partial_link_template, $ctx->{OUTPUT}, \$($ctx->{NAME}_OBJ_FILES))\n");
+}
+
+sub InitFunctions($$)
+{
+ my ($self, $ctx) = @_;
+ $self->output("\$($ctx->{NAME}_OBJ_FILES): CFLAGS+=-DSTATIC_$ctx->{NAME}_MODULES=\"\$($ctx->{NAME}_INIT_FUNCTIONS)$ctx->{INIT_FUNCTION_SENTINEL}\"\n");
+}
+
+sub StaticLibrary($$)
+{
+ my ($self,$ctx) = @_;
+
+ $self->output("STATIC_LIBS += $ctx->{RESULT_STATIC_LIBRARY}\n") if ($ctx->{TYPE} eq "LIBRARY");
+ $self->output("$ctx->{NAME}_OUTPUT = $ctx->{OUTPUT}\n");
+ $self->output("$ctx->{RESULT_STATIC_LIBRARY}: \$($ctx->{NAME}_FULL_OBJ_LIST)\n");
+}
+
+sub Binary($$)
+{
+ my ($self,$ctx) = @_;
+
+ unless (defined($ctx->{INSTALLDIR})) {
+ } elsif ($ctx->{INSTALLDIR} eq "SBINDIR") {
+ $self->output("\$(eval \$(call sbinary_install_template,$ctx->{RESULT_BINARY}))\n");
+ } elsif ($ctx->{INSTALLDIR} eq "BINDIR") {
+ $self->output("\$(eval \$(call binary_install_template,$ctx->{RESULT_BINARY}))\n");
+ }
+
+ $self->_prepare_list($ctx, "FULL_OBJ_LIST");
+ $self->_prepare_list($ctx, "DEPEND_LIST");
+ $self->_prepare_list($ctx, "LINK_FLAGS");
+
+ if (defined($ctx->{USE_HOSTCC}) && $ctx->{USE_HOSTCC} eq "YES") {
+$self->output("\$(eval \$(call host_binary_link_template, $ctx->{RESULT_BINARY}, \$($ctx->{NAME}_FULL_OBJ_LIST) \$($ctx->{NAME}_DEPEND_LIST), \$($ctx->{NAME}_LINK_FLAGS)))\n");
+ } else {
+$self->output("\$(eval \$(call binary_link_template, $ctx->{RESULT_BINARY}, \$($ctx->{NAME}_FULL_OBJ_LIST) \$($ctx->{NAME}_DEPEND_LIST), \$($ctx->{NAME}_LINK_FLAGS)))\n");
+ }
+}
+
+sub write($$)
+{
+ my ($self, $file) = @_;
+
+ $self->_prepare_mk_files();
+
+ $self->output("ALL_OBJS = " . array2oneperline($self->{all_objs}) . "\n");
+
+ open(MAKEFILE,">$file") || die ("Can't open $file\n");
+ print MAKEFILE $self->{output};
+ close(MAKEFILE);
+
+ print __FILE__.": creating $file\n";
+}
+
+my $sort_available = eval "use sort 'stable'; return 1;";
+$sort_available = 0 unless defined($sort_available);
+
+sub by_path {
+ return 1 if($a =~ m#^\-I/#);
+ return -1 if($b =~ m#^\-I/#);
+ return 0;
+}
+
+sub CFlags($$)
+{
+ my ($self, $key) = @_;
+
+ my $srcdir = $self->{config}->{srcdir};
+ my $builddir = $self->{config}->{builddir};
+
+ my $src_ne_build = ($srcdir ne $builddir) ? 1 : 0;
+
+ return unless defined ($key->{FINAL_CFLAGS});
+ return unless (@{$key->{FINAL_CFLAGS}} > 0);
+
+ my @sorted_cflags = @{$key->{FINAL_CFLAGS}};
+ if ($sort_available) {
+ @sorted_cflags = sort by_path @{$key->{FINAL_CFLAGS}};
+ }
+
+ # Rewrite CFLAGS so that both the source and the build
+ # directories are in the path.
+ my @cflags = ();
+ foreach my $flag (@sorted_cflags) {
+ if($src_ne_build) {
+ if($flag =~ m#^-I([^/].*$)#) {
+ my $dir = $1;
+ if ($dir =~ /^\$\(/) {
+ push (@cflags, $flag);
+ next;
+ }
+ $dir =~ s#^\$\((?:src|build)dir\)/?##;
+ push(@cflags, "-I$builddir/$dir", "-I$srcdir/$dir");
+ next;
+ }
+ }
+ push(@cflags, $flag);
+ }
+
+ my $cflags = join(' ', @cflags);
+
+ $self->output("\$(patsubst %.ho,%.d,\$($key->{NAME}_OBJ_FILES:.o=.d)) \$($key->{NAME}_OBJ_FILES): CFLAGS+= $cflags\n");
+}
+
+1;
diff --git a/source4/build/smb_build/output.pm b/source4/build/smb_build/output.pm
new file mode 100644
index 0000000000..76c6d3fc8f
--- /dev/null
+++ b/source4/build/smb_build/output.pm
@@ -0,0 +1,172 @@
+# SMB Build System
+# - the output generating functions
+#
+# Copyright (C) Stefan (metze) Metzmacher 2004
+# Copyright (C) Jelmer Vernooij 2004
+# Released under the GNU GPL
+
+package output;
+use strict;
+
+sub generate_shared_library($)
+{
+ my $lib = shift;
+ my $link_name;
+ my $lib_name;
+
+ $lib->{DEPEND_LIST} = [];
+
+ $link_name = lc($lib->{NAME});
+ $lib_name = $link_name;
+
+ if ($lib->{TYPE} eq "LIBRARY") {
+ $link_name = $lib->{NAME};
+ $link_name =~ s/^LIB//;
+ $link_name = lc($link_name);
+ $lib_name = "lib$link_name";
+ }
+
+ if ($lib->{TYPE} eq "PYTHON") {
+ $lib->{SHAREDDIR} = "bin/python";
+ } elsif (defined($lib->{LIBRARY_REALNAME})) {
+ $lib->{BASEDIR} =~ s/^\.\///g;
+ $lib->{SHAREDDIR} = $lib->{BASEDIR};
+ } else {
+ if ($lib->{TYPE} eq "MODULE") {
+ my $sane_subsystem = lc($lib->{SUBSYSTEM});
+ $sane_subsystem =~ s/^lib//;
+ $lib->{SHAREDDIR} = "bin/modules/$sane_subsystem";
+ $lib->{LIBRARY_REALNAME} = $link_name;
+ $lib->{LIBRARY_REALNAME} =~ s/^$sane_subsystem\_//g;
+ $lib->{LIBRARY_REALNAME}.= ".\$(SHLIBEXT)";
+ } else {
+ $lib->{SHAREDDIR} = "bin/shared";
+ $lib->{LIBRARY_REALNAME} = "$lib_name.\$(SHLIBEXT)";
+ }
+ }
+
+ $lib->{LIBRARY_DEBUGNAME} = $lib->{LIBRARY_REALNAME};
+
+ $lib->{LIBRARY_SONAME} = "\$(if \$($lib->{NAME}_SOVERSION),$lib->{LIBRARY_REALNAME}.\$($lib->{NAME}_SOVERSION),$lib->{LIBRARY_REALNAME})";
+ $lib->{LIBRARY_REALNAME} = "\$(if \$($lib->{NAME}_VERSION),$lib->{LIBRARY_REALNAME}.\$($lib->{NAME}_VERSION),$lib->{LIBRARY_REALNAME})";
+
+ $lib->{RESULT_SHARED_LIBRARY} = "$lib->{SHAREDDIR}/$lib->{LIBRARY_REALNAME}";
+ $lib->{OUTPUT_SHARED_LIBRARY} = "-l$link_name";
+ $lib->{TARGET_SHARED_LIBRARY} = "$lib->{SHAREDDIR}/$lib->{LIBRARY_DEBUGNAME}";
+}
+
+sub generate_merged_obj($)
+{
+ my $lib = shift;
+
+ my $link_name = $lib->{NAME};
+ $link_name =~ s/^LIB//;
+
+ $lib->{MERGED_OBJNAME} = lc($link_name).".o";
+ $lib->{RESULT_MERGED_OBJ} = $lib->{OUTPUT_MERGED_OBJ} = "bin/mergedobj/$lib->{MERGED_OBJNAME}";
+ $lib->{TARGET_MERGED_OBJ} = $lib->{RESULT_MERGED_OBJ};
+}
+
+sub generate_static_library($)
+{
+ my $lib = shift;
+ my $link_name;
+
+ $lib->{DEPEND_LIST} = [];
+
+ $link_name = $lib->{NAME};
+ $link_name =~ s/^LIB//;
+
+ $lib->{LIBRARY_NAME} = "lib".lc($link_name).".a";
+
+ $lib->{RESULT_STATIC_LIBRARY} = "bin/static/$lib->{LIBRARY_NAME}";
+ $lib->{TARGET_STATIC_LIBRARY} = $lib->{RESULT_STATIC_LIBRARY};
+ $lib->{STATICDIR} = 'bin/static';
+ $lib->{OUTPUT_STATIC_LIBRARY} = "-l".lc($link_name);
+}
+
+sub generate_binary($)
+{
+ my $bin = shift;
+
+ $bin->{DEPEND_LIST} = [];
+ push(@{$bin->{LINK_FLAGS}}, "\$($bin->{NAME}\_FULL_OBJ_LIST)");
+
+ $bin->{DEBUGDIR} = "bin";
+ $bin->{RESULT_BINARY} = $bin->{OUTPUT_BINARY} = "$bin->{DEBUGDIR}/$bin->{NAME}";
+ $bin->{TARGET_BINARY} = $bin->{RESULT_BINARY};
+ $bin->{BINARY} = $bin->{NAME};
+}
+
+sub merge_array($$)
+{
+ # $dest is a reference to an array
+ # $src is an array
+ my ($dest, $src) = @_;
+
+ return unless defined($src);
+ return unless ($#{$src} >= 0);
+
+ foreach my $line (@{$src}) {
+ next if (grep /^$line$/, @{$$dest});
+ push(@{$$dest}, $line);
+ }
+}
+
+sub create_output($$)
+{
+ my ($depend, $config) = @_;
+ my $part;
+
+ foreach $part (values %{$depend}) {
+ next unless(defined($part->{OUTPUT_TYPE}));
+
+ generate_binary($part) if grep(/BINARY/, @{$part->{OUTPUT_TYPE}});
+ generate_shared_library($part) if grep(/SHARED_LIBRARY/, @{$part->{OUTPUT_TYPE}});
+ generate_static_library($part) if grep(/STATIC_LIBRARY/, @{$part->{OUTPUT_TYPE}});
+ generate_merged_obj($part) if grep(/MERGED_OBJ/, @{$part->{OUTPUT_TYPE}});
+ $part->{OUTPUT} = $part->{"OUTPUT_" . @{$part->{OUTPUT_TYPE}}[0]};
+ $part->{TARGET} = $part->{"TARGET_" . @{$part->{OUTPUT_TYPE}}[0]};
+ }
+
+ foreach $part (values %{$depend}) {
+ next if not defined($part->{OUTPUT_TYPE});
+
+ merge_array(\$part->{FINAL_CFLAGS}, $part->{CPPFLAGS});
+ merge_array(\$part->{FINAL_CFLAGS}, $part->{CFLAGS});
+
+ foreach (@{$part->{UNIQUE_DEPENDENCIES_ALL}}) {
+ my $elem = $depend->{$_};
+ next if $elem == $part;
+
+ merge_array(\$part->{FINAL_CFLAGS}, $elem->{CPPFLAGS});
+ merge_array(\$part->{FINAL_CFLAGS}, $elem->{CFLAGS});
+ }
+
+ # Always import the link options of the unique dependencies
+ foreach (@{$part->{UNIQUE_DEPENDENCIES_LINK}}) {
+ my $elem = $depend->{$_};
+ next if $elem == $part;
+
+ push(@{$part->{LINK_FLAGS}}, @{$elem->{LIBS}}) if defined($elem->{LIBS});
+ push(@{$part->{LINK_FLAGS}}, @{$elem->{LDFLAGS}}) if defined($elem->{LDFLAGS});
+ if (defined($elem->{OUTPUT_TYPE}) and @{$elem->{OUTPUT_TYPE}}[0] eq "MERGED_OBJ") {
+ push (@{$part->{FULL_OBJ_LIST}}, $elem->{TARGET});
+ } else {
+ push(@{$part->{LINK_FLAGS}}, "\$($elem->{NAME}_OUTPUT)") if defined($elem->{OUTPUT});
+ push(@{$part->{DEPEND_LIST}}, $elem->{TARGET}) if (defined($elem->{TARGET}));
+ }
+ }
+ }
+
+ foreach $part (values %{$depend}) {
+ if (defined($part->{STANDARD_VISIBILITY}) and ($part->{STANDARD_VISIBILITY} ne "default") and
+ ($config->{visibility_attribute} eq "yes")) {
+ push(@{$part->{FINAL_CFLAGS}}, "-fvisibility=$part->{STANDARD_VISIBILITY}");
+ }
+ }
+
+ return $depend;
+}
+
+1;
diff --git a/source4/build/smb_build/summary.pm b/source4/build/smb_build/summary.pm
new file mode 100644
index 0000000000..4ea1ad525e
--- /dev/null
+++ b/source4/build/smb_build/summary.pm
@@ -0,0 +1,79 @@
+# Samba Build System
+# - write out summary
+#
+# Copyright (C) Jelmer Vernooij 2006
+# Released under the GNU GPL
+
+package summary;
+use smb_build::config;
+use strict;
+
+sub enabled($)
+{
+ my ($val) = @_;
+
+ return (defined($val) && $val =~ m/yes|true/i);
+}
+
+sub showitem($$$)
+{
+ my ($output,$desc,$items) = @_;
+
+ my @need = ();
+
+ foreach (@$items) {
+ push (@need, $_) if (enabled($config::enable{$_}));
+ }
+
+ print "Support for $desc: ";
+ if ($#need >= 0) {
+ print "no (install " . join(',',@need) . ")\n";
+ } else {
+ print "yes\n";
+ }
+}
+
+sub showisexternal($$$)
+{
+ my ($output, $desc, $name) = @_;
+ print "Using external $desc: ".
+ (($output->{$name}->{TYPE} eq "EXT_LIB")?"yes":"no")."\n";
+}
+
+sub show($$)
+{
+ my ($output,$config) = @_;
+
+ print "Summary:\n\n";
+ showitem($output, "SSL in SWAT and LDAP", ["GNUTLS"]);
+ showitem($output, "threads in smbd (see --with-pthread)", ["PTHREAD"]);
+ showitem($output, "intelligent command line editing", ["READLINE"]);
+ showitem($output, "changing process titles (see --with-setproctitle)", ["SETPROCTITLE"]);
+ showitem($output, "using extended attributes", ["XATTR"]);
+ showitem($output, "using libblkid", ["BLKID"]);
+ showitem($output, "using iconv", ["ICONV"]);
+ showitem($output, "using pam", ["PAM"]);
+ showitem($output, "python bindings", ["LIBPYTHON"]);
+ showisexternal($output, "popt", "LIBPOPT");
+ showisexternal($output, "talloc", "LIBTALLOC");
+ showisexternal($output, "tdb", "LIBTDB");
+ showisexternal($output, "ldb", "LIBLDB");
+ print "Developer mode: ".(enabled($config->{developer})?"yes":"no")."\n";
+ print "Automatic dependencies: ".
+ (enabled($config->{automatic_dependencies})
+ ? "yes" : "no (install GNU make >= 3.81 and see --enable-automatic-dependencies)") .
+ "\n";
+
+ print "Building shared libraries: " .
+ (enabled($config->{BLDSHARED})
+ ? "yes" : "no (not supported on this system)") .
+ "\n";
+ print "Using shared libraries internally: " .
+ (enabled($config->{USESHARED})
+ ? "yes" : "no (specify --enable-dso)") .
+ "\n";
+
+ print "\n";
+}
+
+1;