[PATCH][SAMBA4] allow separate source and build directories

James Peach jpeach at samba.org
Wed Mar 28 20:32:46 GMT 2007


Hi all,

Attached is my patch to allow separate build and source directories  
for building Samba 4 updated to the Samba4 build system of a few days  
ago. Note that this changes only the build, not the test suite.

The use case for this is a build script along the lines of this:

#! /bin/bash

DSTROOT==~/tmp/samba4
SRCROOT=$(pwd)

rm -rf $DSTROOT
mkdir -p $DSTROOT

./autogen.sh && cd $DSTROOT && $SRCROOT/configure && make


-------------- next part --------------
Index: SAMBA_4_0/source/configure.ac
===================================================================
--- SAMBA_4_0/source/configure.ac	(revision 21966)
+++ SAMBA_4_0/source/configure.ac	(working copy)
@@ -78,6 +78,10 @@
 
 AC_SUBST(ac_default_prefix)
 
+for d in build/smb_build bin include ; do
+    test -d ${builddir}/$d || AS_MKDIR_P(${builddir}/$d)
+done
+
 echo "configure: creating build/smb_build/config.pm"
 cat >build/smb_build/config.pm<<CEOF
 # config.pm - Autogenerate by configure. DO NOT EDIT!
@@ -107,15 +111,30 @@
 CEOF
 
 AC_OUTPUT_COMMANDS(
-[test "x$ac_abs_srcdir" != "x$ac_abs_builddir" && 
- (cd $builddir; 
-	test -d heimdal || cp -r $srcdir/heimdal $builddir/
-	test -d heimdal_build || cp -r $srcdir/heimdal_build $builddir/
-	test -d build || samba_builddir="$builddir" samba_srcdir="$srcdir" $PERL $srcdir/script/buildtree.pl
-	test -f $builddir/include/smb.h || cp $srcdir/include/smb.h $builddir/include
+[
+test "x$ac_abs_srcdir" != "x$ac_abs_builddir" && (
+	cd $builddir;
+	# NOTE: We *must* use -R so we don't follow symlinks (at least on BSD
+	# systems).
+	test -d heimdal || cp -R $srcdir/heimdal $builddir/
+	test -d heimdal_build || cp -R $srcdir/heimdal_build $builddir/
+	test -d build || builddir="$builddir" \
+			srcdir="$srcdir" \
+			$PERL ${srcdir}/script/buildtree.pl
  )
-$PERL -I${builddir} -I${srcdir} -I${srcdir}/build ${srcdir}/build/smb_build/main.pl || exit $?],[
-PERL="$PERL";export PERL;export srcdir; export builddir;
+
+$PERL -I${builddir} -I${builddir}/build \
+    -I${srcdir} -I${srcdir}/build \
+    ${srcdir}/build/smb_build/main.pl || exit $?
+],
+[
+srcdir="$srcdir"
+builddir="$builddir"
+PERL="$PERL"
+
+export PERL
+export srcdir
+export builddir
 ])
 AC_OUTPUT
 
Index: SAMBA_4_0/source/lib/ldb/include/includes.h
===================================================================
--- SAMBA_4_0/source/lib/ldb/include/includes.h	(revision 21966)
+++ SAMBA_4_0/source/lib/ldb/include/includes.h	(working copy)
@@ -25,7 +25,7 @@
 #include "system/filesys.h"
 #include "system/network.h"
 #include "system/time.h"
-#include "talloc.h"
+#include "talloc/talloc.h"
 #include "ldb.h"
 #include "ldb_errors.h"
 #include "ldb_private.h"
Index: SAMBA_4_0/source/lib/registry/config.mk
===================================================================
--- SAMBA_4_0/source/lib/registry/config.mk	(revision 21966)
+++ SAMBA_4_0/source/lib/registry/config.mk	(working copy)
@@ -20,7 +20,7 @@
 $(srcdir)/lib/registry/reg_backend_nt4.c: lib/registry/tdr_regf.c
 lib/registry/tdr_regf.h: lib/registry/tdr_regf.c
 lib/registry/tdr_regf.c: $(srcdir)/lib/registry/regf.idl
-	@CPP="$(CPP)" $(PERL) $(srcdir)/pidl/pidl $(PIDL_ARGS) \
+	@CPP="$(CPP)" srcdir="$(srcdir)" $(PERL) $(srcdir)/pidl/pidl $(PIDL_ARGS) \
 		--header --outputdir=lib/registry \
 		--tdr-parser -- $(srcdir)/lib/registry/regf.idl
 
Index: SAMBA_4_0/source/lib/replace/samba.m4
===================================================================
--- SAMBA_4_0/source/lib/replace/samba.m4	(revision 21966)
+++ SAMBA_4_0/source/lib/replace/samba.m4	(working copy)
@@ -3,8 +3,16 @@
 SMB_EXT_LIB(LIBREPLACE_EXT, [${LIBDL}])
 SMB_ENABLE(LIBREPLACE_EXT)
 
+# remove leading ./
 LIBREPLACE_DIR=`echo ${libreplacedir} |sed -e 's/^\.\///g'`
 
+# remove leading srcdir .. we are looking for the relative
+# path within the samba source tree or wherever libreplace is.
+# We need to make sure the object is not forced to end up in
+# the source directory because we might be using a separate
+# build directory.
+LIBREPLACE_DIR=`echo ${LIBREPLACE_DIR} | sed -e "s|^$srcdir/||g"`
+
 LIBREPLACE_OBJS=""
 for obj in ${LIBREPLACEOBJ}; do
 	LIBREPLACE_OBJS="${LIBREPLACE_OBJS} ${LIBREPLACE_DIR}/${obj}"
Index: SAMBA_4_0/source/pidl/lib/Parse/Pidl/Samba4.pm
===================================================================
--- SAMBA_4_0/source/pidl/lib/Parse/Pidl/Samba4.pm	(revision 21966)
+++ SAMBA_4_0/source/pidl/lib/Parse/Pidl/Samba4.pm	(working copy)
@@ -18,8 +18,10 @@
 
 sub is_intree()
 {
-	return 4 if (-f "kdc/kdc.c");
-	return 3 if (-f "include/smb.h");
+	my $srcdir = $ENV{srcdir};
+	$srcdir = $srcdir ? "$srcdir/" : "";
+	return 4 if (-f "${srcdir}kdc/kdc.c");
+	return 3 if (-f "${srcdir}include/smb.h");
 	return 0;
 }
 
Index: SAMBA_4_0/source/main.mk
===================================================================
--- SAMBA_4_0/source/main.mk	(revision 21966)
+++ SAMBA_4_0/source/main.mk	(working copy)
@@ -283,7 +283,11 @@
 
 check:: test
 
-SELFTEST = $(srcdir)/script/tests/selftest.pl --prefix=${selftest_prefix} --builddir=$(builddir) --srcdir=$(srcdir) --expected-failures=samba4-knownfail --skip=samba4-skip $(TEST_OPTIONS) 
+SELFTEST = $(srcdir)/script/tests/selftest.pl --prefix=${selftest_prefix} \
+    --builddir=$(builddir) --srcdir=$(srcdir) \
+    --expected-failures=$(srcdir)/samba4-knownfail \
+    --skip=$(srcdir)/samba4-skip \
+    $(TEST_OPTIONS) 
 
 test: all libraries
 	$(SELFTEST) $(DEFAULT_TEST_OPTIONS) $(TESTS) --immediate
@@ -373,23 +377,27 @@
 # if it also exists. So better use $* which is foo/bar
 # and append .c manually to get foo/bar.c
 #
+# But if srcdir != builddir, $* does not contain the filename
+# that was found be traversing VPATH. So we are back to $<.
+#	-- jpeach
+#
 
 # Run a static analysis checker
 CHECK = $(CC_CHECKER) `$(PERL) $(srcdir)/script/cflags.pl $@` \
-    $(CFLAGS) $(PICFLAG) -c $*.c -o $@
+    $(CFLAGS) $(PICFLAG) -c $< -o $@
 
 # Run the configured compiler
 COMPILE = $(CC) `$(PERL) $(srcdir)/script/cflags.pl $@` \
-    $(CFLAGS) $(PICFLAG) -c $*.c -o $@
+    $(CFLAGS) $(PICFLAG) -c $< -o $@
 
 # Run the compiler for the build host
 HCOMPILE = $(HOSTCC) `$(PERL) $(srcdir)/script/cflags.pl $@` \
-    $(HOSTCC_CFLAGS) -c $*.c -o $@
+    $(HOSTCC_CFLAGS) -c $< -o $@
 
 # Precompile headers
 PCHCOMPILE = @$(CC) -Ilib/replace \
     `$(PERL) $(srcdir)/script/cflags.pl $@` \
-    $(CFLAGS) $(PICFLAG) -c $*.c -o $@
+    $(CFLAGS) $(PICFLAG) -c $< -o $@
 
 .c.o:
 	@if test -n "$(CC_CHECKER)"; then \
Index: SAMBA_4_0/source/build/m4/check_ld.m4
===================================================================
--- SAMBA_4_0/source/build/m4/check_ld.m4	(revision 21966)
+++ SAMBA_4_0/source/build/m4/check_ld.m4	(working copy)
@@ -36,6 +36,17 @@
 SONAMEFLAG=""
 PICFLAG=""
 
+# allow for --with-hostld=gcc
+AC_ARG_WITH(hostld,[  --with-hostld=linker    choose host linker],
+[HOSTLD=$withval],
+[
+if test z"$cross_compiling" = "yes"; then
+	HOSTLD='$(HOSTCC)'
+else
+	HOSTLD='$(LD)'
+fi
+])
+
 AC_MSG_CHECKING([ability to build shared libraries])
 
 # and these are for particular systems
@@ -144,6 +155,8 @@
 AC_MSG_CHECKING([LDFLAGS])
 AC_MSG_RESULT([$LDFLAGS])
 
+AC_SUBST(HOSTLD)
+
 AC_MSG_CHECKING([STLD])
 AC_MSG_RESULT([$STLD])
 AC_MSG_CHECKING([STLD_FLAGS])
Index: SAMBA_4_0/source/build/smb_build/config_mk.pm
===================================================================
--- SAMBA_4_0/source/build/smb_build/config_mk.pm	(revision 21966)
+++ SAMBA_4_0/source/build/smb_build/config_mk.pm	(working copy)
@@ -114,6 +114,64 @@
 
 @parsed_files = ();
 
+sub _read_config_file
+{
+	use File::Basename;
+	use Cwd;
+
+	my $srcdir = shift;
+	my $builddir = shift;
+	my $filename = shift;
+	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);
+		}
+		$basedir =~ s!^($builddir|$srcdir)[/]!!;
+		return ($filename, $basedir, @lines);
+	}
+
+	chdir $cwd;
+	return;
+}
+
 ###########################################################
 # The parsing function which parses the file
 #
@@ -131,46 +189,28 @@
 	my $section = "GLOBAL";
 	my $makefile = "";
 
-	my $parsing_file = $filename;
-	my $retry_parsing_file = undef;
 	my $basedir;
 
-	$ENV{samba_builddir} = $builddir;
-	$ENV{samba_srcdir} = $srcdir;
+	my $parsing_file;
+	my @lines;
 
-	if (($srcdir ne ".") or ($builddir ne ".")) {
-		$parsing_file = $builddir."/".$filename;
-		$retry_parsing_file = $srcdir."/".$filename;
-	}
+	$ENV{builddir} = $builddir;
+	$ENV{srcdir} = $srcdir;
 
-	if (open(CONFIG_MK, $parsing_file)) {
-		$retry_parsing_file = undef;
-	} else {
-		die("Can't open $parsing_file") unless defined($retry_parsing_file);
-	}
+	($parsing_file, $basedir, @lines) =
+	    _read_config_file($srcdir, $builddir, $filename);
 
-	if (defined($retry_parsing_file)) {
-		if (open(CONFIG_MK, $parsing_file)) {
-			$parsing_file = $retry_parsing_file;
-			$retry_parsing_file = undef;
-		} else {
-			die("Can't open neither '$parsing_file' nor '$retry_parsing_file'\n");
-		}
-	}
+	die ("$0: can't open '$filename'")
+		unless ($parsing_file and $basedir and @lines);
 
-        if ($parsing_file =~ /\|$/) { 
-	        $basedir = $builddir;
-	} else {
-	        $basedir = dirname($filename);
-		push (@parsed_files, $parsing_file);
-	}
-	
-	my @lines = <CONFIG_MK>;
-	close(CONFIG_MK);
-
 	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++;
 
@@ -230,6 +270,8 @@
 		die("$parsing_file:$linenum: Bad line while parsing $parsing_file");
 	}
 
+	$makefile .= "# }END $parsing_file\n";
+
 	foreach my $section (keys %{$result}) {
 		my ($type, $name) = split(/::/, $section, 2);
 
Index: SAMBA_4_0/source/build/smb_build/makefile.pm
===================================================================
--- SAMBA_4_0/source/build/smb_build/makefile.pm	(revision 21966)
+++ SAMBA_4_0/source/build/smb_build/makefile.pm	(working copy)
@@ -71,11 +71,13 @@
 prefix = $self->{config}->{prefix}
 exec_prefix = $self->{config}->{exec_prefix}
 selftest_prefix = $self->{config}->{selftest_prefix}
+
+builddir = $self->{config}->{builddir}
 srcdir = $self->{config}->{srcdir}
-VPATH = \$(srcdir):heimdal_build:heimdal/lib/asn1:heimdal/lib/krb5:heimdal/lib/gssapi:heimdal/lib/hdb:heimdal/lib/roken:heimdal/lib/des
-builddir = $self->{config}->{builddir}
 datarootdir = $self->{config}->{datarootdir}
 
+VPATH = \$(builddir):\$(srcdir):heimdal_build:heimdal/lib/asn1:heimdal/lib/krb5:heimdal/lib/gssapi:heimdal/lib/hdb:heimdal/lib/roken:heimdal/lib/des
+
 BASEDIR = $self->{config}->{prefix}
 BINDIR = $self->{config}->{bindir}
 SBINDIR = $self->{config}->{sbindir}
@@ -141,6 +143,9 @@
 LD=$self->{config}->{LD} 
 LDFLAGS=$self->{config}->{LDFLAGS} -L$libdir
 
+HOSTLD=$self->{config}->{HOSTLD}
+# It's possible that we ought to have HOSTLD_LDFLAGS as well
+
 STLD=$self->{config}->{STLD}
 STLD_FLAGS=$self->{config}->{STLD_FLAGS}
 
@@ -326,12 +331,13 @@
 	$self->_prepare_list($ctx, "FULL_OBJ_LIST");
 
 	push(@{$self->{all_objs}}, "\$($ctx->{TYPE}_$ctx->{NAME}_FULL_OBJ_LIST)");
-		
+
 	$self->output(<< "__EOD__"
 #
 $ctx->{TARGET_STATIC_LIBRARY}: \$($ctx->{TYPE}_$ctx->{NAME}_FULL_OBJ_LIST)
 	\@echo Linking \$@
 	\@rm -f \$@
+	\@mkdir -p $ctx->{STATICDIR}
 	\@\$(STLD) \$(STLD_FLAGS) \$@ \$($ctx->{TYPE}_$ctx->{NAME}_FULL_OBJ_LIST)
 
 __EOD__
@@ -384,14 +390,25 @@
 	$self->_prepare_list($ctx, "DEPEND_LIST");
 	$self->_prepare_list($ctx, "LINK_FLAGS");
 
-$self->output(<< "__EOD__"
+	$self->output(<< "__EOD__"
 $installdir/$ctx->{BINARY}: \$($ctx->{TYPE}_$ctx->{NAME}_DEPEND_LIST) \$($ctx->{TYPE}_$ctx->{NAME}_FULL_OBJ_LIST)
 	\@echo Linking \$\@
+__EOD__
+	);
+
+	if ($ctx->{"USE_HOSTCC"} =~ m/yes/i) {
+		$self->output(<< "__EOD__"
+	\@\$(HOSTLD) \$(LDFLAGS) -o \$\@ \$(INSTALL_LINK_FLAGS) \\
+		\$\($ctx->{TYPE}_$ctx->{NAME}_LINK_FLAGS)
+__EOD__
+		);
+	} else {
+		$self->output(<< "__EOD__"
 	\@\$(LD) \$(LDFLAGS) -o \$\@ \$(INSTALL_LINK_FLAGS) \\
 		\$\($ctx->{TYPE}_$ctx->{NAME}_LINK_FLAGS) 
-
 __EOD__
-);
+		);
+	}
 }
 
 sub Manpage($$)
Index: SAMBA_4_0/source/build/smb_build/cflags.pm
===================================================================
--- SAMBA_4_0/source/build/smb_build/cflags.pm	(revision 21966)
+++ SAMBA_4_0/source/build/smb_build/cflags.pm	(working copy)
@@ -6,9 +6,12 @@
 package cflags;
 use strict;
 
-sub create_cflags($$)
+sub create_cflags($$$$)
 {
-	my ($CTX, $file) = @_;
+	my $CTX = shift;
+	my $srcdir = shift;
+	my $builddir = shift;
+	my $file = shift;
 
 	open(CFLAGS_TXT,">$file") || die ("Can't open `$file'\n");
 
@@ -18,7 +21,18 @@
 		next unless defined ($key->{FINAL_CFLAGS});
 		next unless ($#{$key->{FINAL_CFLAGS}} >= 0);
 
-		my $cflags = join(' ', @{$key->{FINAL_CFLAGS}});
+		# Rewrite CFLAGS so that both the source and the build
+		# directories are in the path.
+		my $cflags = "";
+		foreach my $flag (@{$key->{FINAL_CFLAGS}}) {
+			my $dir;
+			if (($dir) = ($flag =~ /^-I([^\/].*)$/)) {
+				$cflags .= " -I$builddir/$dir";
+				$cflags .= " -I$srcdir/$dir";
+			} else {
+				$cflags .= " $flag";
+			}
+		}
 
 		foreach (@{$key->{OBJ_LIST}}) {
 			my $ofile = $_;
Index: SAMBA_4_0/source/build/smb_build/output.pm
===================================================================
--- SAMBA_4_0/source/build/smb_build/output.pm	(revision 21966)
+++ SAMBA_4_0/source/build/smb_build/output.pm	(working copy)
@@ -90,6 +90,7 @@
 
 	if (defined($lib->{OBJ_FILES})) {
 		$lib->{TARGET_STATIC_LIBRARY} = "bin/static/$lib->{LIBRARY_NAME}";
+		$lib->{STATICDIR} = 'bin/static';
 	} else {
 		$lib->{TARGET_STATIC_LIBRARY} = "";
 	}
Index: SAMBA_4_0/source/build/smb_build/main.pl
===================================================================
--- SAMBA_4_0/source/build/smb_build/main.pl	(revision 21966)
+++ SAMBA_4_0/source/build/smb_build/main.pl	(working copy)
@@ -71,8 +71,10 @@
 $mkenv->write("Makefile");
 header::create_smb_build_h($OUTPUT, "include/build.h");
 
-cflags::create_cflags($OUTPUT, "extra_cflags.txt");
+cflags::create_cflags($OUTPUT, $config::config{srcdir},
+		    $config::config{builddir}, "extra_cflags.txt");
 
+
 summary::show($OUTPUT, \%config::config);
 
 1;
Index: SAMBA_4_0/source/script/buildtree.pl
===================================================================
--- SAMBA_4_0/source/script/buildtree.pl	(revision 21966)
+++ SAMBA_4_0/source/script/buildtree.pl	(working copy)
@@ -15,8 +15,8 @@
 *name   = *File::Find::name;
 *dir    = *File::Find::dir;
 *prune  = *File::Find::prune;
-my $builddir = abs_path($ENV{samba_builddir});
-my $srcdir = abs_path($ENV{samba_srcdir});
+my $builddir = abs_path($ENV{builddir});
+my $srcdir = abs_path($ENV{srcdir});
 sub wanted;
 
 
-------------- next part --------------

--
James Peach | jpeach at samba.org



More information about the samba-technical mailing list