Subject: Please try: patch for the buildtree target
To: None <current-users@NetBSD.ORG>
From: Greg Hudson <ghudson@mit.edu>
List: current-users
Date: 12/20/1995 03:01:21
The conclusion I drew from the preceeding conversation is that no one
really disliked my proposed build scheme.  A few people brought up
union mounts and symlink farms as alternatives, but acknowledged that
they aren't always adequate solutions (symlink farms don't adapt to
changes to the source tree; union mounts are buggy and can't always be
shared across machines).  A couple of people also suggested having obj
links point to a /usr/obj which is different on each build machine;
this approach obviously has limitations as well (e.g. non-root users
without write access to the source tree can't determine where the
build tree will be).

So I've regenerated the fairly minimal changes necessary to support my
buildtree scheme.  The changes don't break obj links.  I've tried them
on a build of /usr/src/usr.sbin, and they work fine there.  As I
mentioned before, a few Makefiles will break if you use a
buildtree--the subdirectories of usr.bin/tn3270 need to use ${TREEDIR}
instead of ${.CURDIR} when running make to find the object directories
for the other parts of the tree.

I would appreciate it if some people could look over the following
patch to bsd.subdir.mk, try it out, see if they like how it feels, and
tell me (in private email, please) if they like it or if they think
anything is wrong with it.  If I get one or two positive responses and
no serious objections within a week or so, I'll commit this change as
well as the corresponding changes to the tn3270 Makefiles and any
other Makefiles with the same problem.

(Note that this change will require people to update /usr/share/mk to
build usr.bin/tn3270.)

To use the patch, apply it to share/mk/bsd.subdir.mk and do a "make
install" in share/mk.  To generate a build tree, cd into /usr/src (or
some subdirectory of it), and do:

	make buildtree BUILDDIR=/my/build/dir

Then you should be able to cd into /my/build/dir (or any subdirectory
of it) and do a make.  For kicks, try nuking an arbitrary subdirectory
under /my/build/dir and notice that a "make" still succeeds.  Also
note that a simple "make buildtree" works inside the build directory,
although it should never really be necessary.

*** 1.3	1995/12/20 05:51:18
--- bsd.subdir.mk	1995/12/20 06:54:30
***************
*** 5,10 ****
--- 5,12 ----
  .MAIN: all
  .endif
  
+ TREEDIR?=${.CURDIR}
+ 
  _SUBDIRUSE: .USE
  .if defined(SUBDIR)
  	@for entry in ${SUBDIR}; do \
***************
*** 13,38 ****
  		else \
  			_newdir_="$${entry}"; \
  		fi; \
! 		if test X"${_THISDIR_}" = X""; then \
  			_nextdir_="$${_newdir_}"; \
  		else \
  			_nextdir_="$${_THISDIR_}/$${_newdir_}"; \
  		fi; \
  		echo "===> $${_nextdir_}"; \
! 		cd ${.CURDIR}/$${_newdir_}; \
  		${MAKE} _THISDIR_="$${_nextdir_}" \
  		    ${.TARGET:S/realinstall/install/:S/.depend/depend/}); \
  	done
  
  ${SUBDIR}::
! 	@set -e; if test -d ${.CURDIR}/${.TARGET}.${MACHINE}; then \
  		_newdir_=${.TARGET}.${MACHINE}; \
  	else \
  		_newdir_=${.TARGET}; \
  	fi; \
  	echo "===> $${_newdir_}"; \
! 	cd ${.CURDIR}/$${_newdir_}; \
  	${MAKE} _THISDIR_="$${_newdir_}" all
  .endif
  
  .if !target(install)
--- 15,66 ----
  		else \
  			_newdir_="$${entry}"; \
  		fi; \
! 		if test -z "${_THISDIR_}"; then \
  			_nextdir_="$${_newdir_}"; \
  		else \
  			_nextdir_="$${_THISDIR_}/$${_newdir_}"; \
  		fi; \
+ 		if test -d "${.CURDIR}/$${_newdir_}" -a \
+ 		    ! -d "${TREEDIR}/$${_newdir_}"; then \
+ 			echo "$${_newdir_} missing, making build tree:"; \
+ 			echo "===> $${_nextdir_}"; \
+ 			(cd ${.CURDIR}/$${_newdir_}; \
+ 			${MAKE} _THISDIR_="$${_nextdir_}" \
+ 			    BUILDDIR="${TREEDIR}/$${_newdir_}" buildtree); \
+ 			echo "Continuing with build."; \
+ 		fi; \
  		echo "===> $${_nextdir_}"; \
! 		cd ${TREEDIR}/$${_newdir_}; \
  		${MAKE} _THISDIR_="$${_nextdir_}" \
+ 		    BUILDDIR="${BUILDDIR}/$${_newdir_}" \
  		    ${.TARGET:S/realinstall/install/:S/.depend/depend/}); \
  	done
  
  ${SUBDIR}::
! 	@set -e; if test -d ${TREEDIR}/${.TARGET}.${MACHINE}; then \
  		_newdir_=${.TARGET}.${MACHINE}; \
  	else \
  		_newdir_=${.TARGET}; \
  	fi; \
  	echo "===> $${_newdir_}"; \
! 	cd ${TREEDIR}/$${_newdir_}; \
  	${MAKE} _THISDIR_="$${_newdir_}" all
+ .endif
+ 
+ .if !defined(BUILDDIR)
+ buildtree:
+ 	@echo "You must define BUILDDIR to use the buildtree target."
+ 	@exit 1
+ .else
+ buildtree: _SUBDIRUSE
+ 	@mkdir -p ${BUILDDIR}
+ 	@rm -f ${BUILDDIR}/Makefile
+ 	@echo ".CURDIR=${.CURDIR}" > ${BUILDDIR}/Makefile
+ 	@echo "BUILDDIR=${BUILDDIR}" >> ${BUILDDIR}/Makefile
+ 	@echo "TREEDIR=${BUILDDIR}" >> ${BUILDDIR}/Makefile
+ 	@echo ".include \"${.CURDIR}/Makefile\"" >> ${BUILDDIR}/Makefile
+ 	@echo ".PATH: ${.CURDIR}" >> ${BUILDDIR}/Makefile
+ 	@echo "Build directory ${BUILDDIR} created."
  .endif
  
  .if !target(install)