Module Name:    src
Committed By:   apb
Date:           Sun Sep 27 18:08:24 UTC 2009

Modified Files:
        src: BUILDING build.sh
        src/doc: BUILDING.mdoc

Log Message:
* Use a more robust method of creating the top level object directory.
  Use getmakevar to expand MAKEOBJDIRPREFIX or MAKEOBJDIR, or (if
  neither of those variables is set) use a non-recursive "make obj" in
  the top level source directory.

* Do not let TOP_objdir default to ${TOP}.  It's now set only by the
  -M or -O command line options, or after using getmakevar to expand
  MAKEOBJDIRPREFIX or MAKEOBJDIR.

* Make try_set_TOOLDIR handle MAKEOBJDIRPERFIX passed from the
  environment.  It runs too early to use getmakevar, so it will not work
  if the value contains embedded '${...}' variable references.

* Use '$TOOLDIR' (with a literal '$') instead of 'nonexistent' in
  a message when rebuilding make when TOOLDIR is not yet known.


To generate a diff of this commit:
cvs rdiff -u -r1.87 -r1.88 src/BUILDING
cvs rdiff -u -r1.211 -r1.212 src/build.sh
cvs rdiff -u -r1.76 -r1.77 src/doc/BUILDING.mdoc

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/BUILDING
diff -u src/BUILDING:1.87 src/BUILDING:1.88
--- src/BUILDING:1.87	Sun Sep 27 17:28:38 2009
+++ src/BUILDING	Sun Sep 27 18:08:24 2009
@@ -117,14 +117,19 @@
                        usefully be set inside a Makefile, including mk.conf or
                        ${MAKECONF}.
 
-     MAKEOBJDIRPREFIX  Top level directory of the object directory tree.  If
-                       specified, must be an absolute path.  If this is
-                       defined, ${MAKEOBJDIRPREFIX}/${.CURDIR} is used as the
-                       .OBJDIR for the current directory.  The current direc-
-                       tory may be read only.  MAKEOBJDIRPREFIX can be pro-
-                       vided only in the environment or via the -M flag of
-                       build.sh; it cannot usefully be set inside a Makefile,
-                       including mk.conf or ${MAKECONF}.
+     MAKEOBJDIRPREFIX  Top level directory of the object directory tree.  The
+                       value is subjected to variable expansion by make(1).
+                       build.sh will create the ${MAKEOBJDIRPREFIX} directory
+                       if necessary, but if make(1) is used without build.sh,
+                       then rules in <bsd.obj.mk> will abort the build if the
+                       ${MAKEOBJDIRPREFIX} directory does not exist.  If the
+                       value is defined and valid, then ${MAKEOBJDIRPRE-
+                       FIX}/${.CURDIR} is used as the .OBJDIR for the current
+                       directory.  The current directory may be read only.
+                       MAKEOBJDIRPREFIX can be provided only in the environ-
+                       ment or via the -M flag of build.sh; it cannot usefully
+                       be set inside a Makefile, including mk.conf or
+                       ${MAKECONF}.
 
    "make" variables
      Several variables control the behavior of NetBSD builds.  Unless other-
@@ -754,14 +759,22 @@
                ber of CPUs) and (2 * the number of CPUs) are recommended.  Use
                lower values on machines with limited memory or I/O bandwidth.
 
-     -M obj    Set MAKEOBJDIRPREFIX to obj.  For instance, if the source
-               directory is /usr/src, a setting of ``-M /usr/obj'' will place
-               build-time files under /usr/obj/usr/src/bin,
-               /usr/obj/usr/src/lib, /usr/obj/usr/src/usr.bin, and so forth.
-               If a relative path is specified, it will be converted to an
-               absolute path before being used.  Unsets MAKEOBJDIR.  See ``-O
+     -M obj    Set MAKEOBJDIRPREFIX to obj.  Unsets MAKEOBJDIR.  See ``-O
                -obj'' for more information.
 
+               For instance, if the source directory is /usr/src, a setting of
+               ``-M /usr/obj'' will place build-time files under
+               /usr/obj/usr/src/bin, /usr/obj/usr/src/lib,
+               /usr/obj/usr/src/usr.bin, and so forth.
+
+               If a relative path is specified, it will be converted to an
+               absolute path before being used.  build.sh imposes the restric-
+               tion that the argument to the -M option must not begin with a
+               ``$'' (dollar sign) character; otherwise it would be too diffi-
+               cult to determine whether the value is an absolute or a rela-
+               tive path.  If the directory does not already exist, build.sh
+               will create it.
+
      -m mach   Set the value of MACHINE to mach, except in some special cases
                listed below.  This will also override any value of
                MACHINE_ARCH in the process environment with a value deduced
@@ -796,11 +809,18 @@
                -n''.
 
      -O obj    Create an appropriate transform macro for MAKEOBJDIR that will
-               place the built object files under obj.  For instance, a set-
-               ting of ``-O /usr/obj'' will place build-time files under
-               /usr/obj/bin, /usr/obj/lib, /usr/obj/usr.bin, and so forth.  If
-               a relative path is specified, it will be converted to an abso-
-               lute path before being used.  Unsets MAKEOBJDIRPREFIX.
+               place the built object files under obj.  Unsets
+               MAKEOBJDIRPREFIX.
+
+               For instance, a setting of ``-O /usr/obj'' will place build-
+               time files under /usr/obj/bin, /usr/obj/lib, /usr/obj/usr.bin,
+               and so forth.
+
+               If a relative path is specified, it will be converted to an
+               absolute path before being used.  build.sh imposes the restric-
+               tion that the argument to the -O option must not contain a
+               ``$'' (dollar sign) character.  If the directory does not
+               already exist, build.sh will create it.
 
                In normal use, exactly one of the -M or -O options should be
                specified.  If neither -M nor -O is specified, then a default

Index: src/build.sh
diff -u src/build.sh:1.211 src/build.sh:1.212
--- src/build.sh:1.211	Sun Sep 27 17:55:53 2009
+++ src/build.sh	Sun Sep 27 18:08:24 2009
@@ -1,5 +1,5 @@
 #! /usr/bin/env sh
-#	$NetBSD: build.sh,v 1.211 2009/09/27 17:55:53 apb Exp $
+#	$NetBSD: build.sh,v 1.212 2009/09/27 18:08:24 apb Exp $
 #
 # Copyright (c) 2001-2009 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -255,19 +255,6 @@
 	#
 	setmakeenv NETBSDSRCDIR "${TOP}"
 
-	# Determine top-level obj directory.
-	# Defaults to the top-level source directory.
-	# If $MAKEOBJDIRPREFIX is set in the environment, use it.
-	# We can't check $MAKEOBJDIR since that may be a make(1)
-	# expression that we can't evaluate at this time.
-	#
-	TOP_objdir="${TOP}"
-	if [ -n "${MAKEOBJDIRPREFIX}" ]; then
-		TOP_objdir="${MAKEOBJDIRPREFIX}${TOP}"
-	elif [ -n "${MAKEOBJDIR}" ]; then
-		warning "Can't parse \$(MAKEOBJDIR) \"$MAKEOBJDIR\" to determine top objdir"
-	fi
-
 	# Find the version of NetBSD
 	#
 	DISTRIBVER="$(${HOST_SH} ${TOP}/sys/conf/osrelease.sh)"
@@ -696,7 +683,16 @@
 
 		-M)
 			eval ${optargcmd}; resolvepath OPTARG
-			TOP_objdir="${OPTARG}${TOP}"
+			case "${OPTARG}" in
+			\$*)	usage "-M argument must not begin with '$'"
+				;;
+			*\$*)	# can use resolvepath, but can't set TOP_objdir
+				resolvepath OPTARG
+				;;
+			*)	resolvepath OPTARG
+				TOP_objdir="${OPTARG}${TOP}"
+				;;
+			esac
 			unsetmakeenv MAKEOBJDIR
 			setmakeenv MAKEOBJDIRPREFIX "${OPTARG}"
 			;;
@@ -725,8 +721,14 @@
 			;;
 
 		-O)
-			eval ${optargcmd}; resolvepath OPTARG
-			TOP_objdir="${OPTARG}"
+			eval ${optargcmd}
+			case "${OPTARG}" in
+			*\$*)	usage "-O argument must not contain '$'"
+				;;
+			*)	resolvepath OPTARG
+				TOP_objdir="${OPTARG}"
+				;;
+			esac
 			unsetmakeenv MAKEOBJDIRPREFIX
 			setmakeenv MAKEOBJDIR "\${.CURDIR:C,^$TOP,$OPTARG,}"
 			;;
@@ -925,7 +927,8 @@
 # * If a copy of make was found above, try to use it with
 #   nobomb_getmakevar to find the correct value for TOOLDIR;
 # * If all else fails, leave TOOLDIR unset.  Our caller is expected to
-#   be able to cope with this.
+#   be able to cope with this.  (For example, rebuildmake() handles it
+#   by building nbmake in a temporary directory.)
 #
 try_set_TOOLDIR()
 {
@@ -946,19 +949,28 @@
 	#
 	# In the usual case (without interference from environment
 	# variables or /etc/mk.conf), <bsd.own.mk> should set TOOLDIR to
-	# "${TOP_objdir}/tooldir.${host_ostype}".  However, in practice
-	# we might have the wrong value of TOP_objdir, so we also try
-	# some other possibilities.
+	# "${_SRC_TOP_OBJ_}/tooldir.${host_ostype}".
+	#
+	# In practice it's difficult to figure out the correct value
+	# for _SRC_TOP_OBJ_.  In the easiest case, when the -M or -O
+	# options were passed to build.sh, then ${TOP_objdir} will be
+	# the correct value.  We also try a few other possibilities, but
+	# we do not replicate all the logic of <bsd.obj.mk>.
 	#
 	local possible_TOP_OBJ
 	local possible_TOOLDIR
-	for possible_TOP_OBJ in "${TOP_objdir}" "${TOP}" "${TOP}/obj" \
+	for possible_TOP_OBJ in \
+		"${TOP_objdir}" \
+		"${MAKEOBJDIRPREFIX:+${MAKEOBJDIRPREFIX}${TOP}}" \
+		"${TOP}" \
+		"${TOP}/obj" \
 		"${TOP}/obj.${MACHINE}"
 	do
+		[ -n "${possible_TOP_OBJ}" ] || continue
 		possible_TOOLDIR="${possible_TOP_OBJ}/tooldir.${host_ostype}"
 		guess_make="${possible_TOOLDIR}/bin/${toolprefix}make"
 		if [ -x "${guess_make}" ]; then
-			break;
+			break
 		else
 			unset guess_make
 		fi
@@ -988,8 +1000,8 @@
 	# binary, if TOOLDIR is pre-set or if try_set_TOOLDIR can set it.
 	#
 	try_set_TOOLDIR
-	make="${TOOLDIR-nonexistent}/bin/${toolprefix}make"
-	if [ -x "${make}" ]; then
+	make="${TOOLDIR:-\$TOOLDIR}/bin/${toolprefix}make"
+	if [ -n "$TOOLDIR" ] && [ -x "${make}" ]; then
 		for f in usr.bin/make/*.[ch] usr.bin/make/lst.lib/*.[ch]; do
 			if [ "${f}" -nt "${make}" ]; then
 				statusmsg "${make} outdated (older than ${f}), needs building."
@@ -1051,45 +1063,39 @@
 	MKUPDATE=$(getmakevar MKUPDATE)
 
 	if [ "${MKOBJDIRS}" != "no" ]; then
-		# Try to create the top level object directory before
-		# running "make obj", otherwise <bsd.own.mk> will not
-		# set the correct value for _SRC_TOP_OBJ_.
+		# Create the top-level object directory.
 		#
-		# If either -M or -O was specified, then we have the
-		# directory name already.
+		# "make obj NOSUBDIR=" can handle most cases, but it
+		# can't handle the case where MAKEOBJDIRPREFIX is set
+		# while the corresponding directory does not exist
+		# (rules in <bsd.obj.mk> would abort the build).  We
+		# therefore have to handle the MAKEOBJDIRPREFIX case
+		# without invoking "make obj".  The MAKEOBJDIR case
+		# could be handled either way, but we choose to handle
+		# it similarly to MAKEOBJDIRPREFIX.
 		#
-		# If neither -M nor -O was specified, then try to get
-		# the directory name from bsd.obj.mk's __usrobjdir
-		# variable, which is set using complex rules.  This
-		# works only if TOP = /usr/src.
-		#
-		top_obj_dir="${TOP_objdir}"
-		if [ -z "${top_obj_dir}" ]; then
-			if [ "$TOP" = "/usr/src" ]; then
-				top_obj_dir="$(getmakevar __usrobjdir)"
-			# else __usrobjdir is not actually used
-			fi
-
+		if [ -n "${TOP_obj}" ]; then
+			# It must have been set by the "-M" or "-O"
+			# command line options, so there's no need to
+			# use getmakevar
+			:
+		elif [ -n "$MAKEOBJDIRPREFIX" ]; then
+			TOP_obj="$(getmakevar MAKEOBJDIRPREFIX)${TOP}"
+		elif [ -n "$MAKEOBJDIR" ]; then
+			TOP_obj="$(getmakevar MAKEOBJDIR)"
+		fi
+		if [ -n "$TOP_obj" ]; then
+			${runcmd} mkdir -p "${TOP_obj}" ||
+			    bomb "Can't create top level object directory" \
+					"${TOP_obj}"
+		else
+			${runcmd} "${make}" -m ${TOP}/share/mk obj NOSUBDIR= ||
+			    bomb "Can't create top level object directory" \
+					"using make obj"
 		fi
-		case "$top_obj_dir" in
-		*/*)
-			${runcmd} mkdir -p "${top_obj_dir}" \
-			|| bomb "Can't create object" \
-				"directory ${top_obj_dir}"
-			;;
-		*)
-			# We don't know what the top level object
-			# directory should be, so we can't create it.
-			# A nonexistant directory might cause an error
-			# when we "make obj" later, but we ignore it for
-			# now.
-			;;
-		esac
 
-		# make obj in tools to ensure that the objdir for the top-level
-		# of the source tree and for "tools" is available, in case the
-		# default TOOLDIR setting from <bsd.own.mk> is used, or the
-		# build.sh default DESTDIR and RELEASEDIR is to be used.
+		# make obj in tools to ensure that the objdir for "tools"
+		# is available.
 		#
 		${runcmd} cd tools
 		${runcmd} "${make}" -m ${TOP}/share/mk obj NOSUBDIR= ||
@@ -1098,6 +1104,7 @@
 	fi
 
 	# Find TOOLDIR, DESTDIR, RELEASEDIR, and RELEASEMACHINEDIR.
+	# This must be done after creating the top-level object directory.
 	#
 	TOOLDIR=$(getmakevar TOOLDIR)
 	statusmsg "TOOLDIR path:     ${TOOLDIR}"
@@ -1237,7 +1244,7 @@
 	eval cat <<EOF ${makewrapout}
 #! ${HOST_SH}
 # Set proper variables to allow easy "make" building of a NetBSD subtree.
-# Generated from:  \$NetBSD: build.sh,v 1.211 2009/09/27 17:55:53 apb Exp $
+# Generated from:  \$NetBSD: build.sh,v 1.212 2009/09/27 18:08:24 apb Exp $
 # with these arguments: ${_args}
 #
 

Index: src/doc/BUILDING.mdoc
diff -u src/doc/BUILDING.mdoc:1.76 src/doc/BUILDING.mdoc:1.77
--- src/doc/BUILDING.mdoc:1.76	Sun Sep 27 17:28:38 2009
+++ src/doc/BUILDING.mdoc	Sun Sep 27 18:08:24 2009
@@ -1,4 +1,4 @@
-.\"	$NetBSD: BUILDING.mdoc,v 1.76 2009/09/27 17:28:38 apb Exp $
+.\"	$NetBSD: BUILDING.mdoc,v 1.77 2009/09/27 18:08:24 apb Exp $
 .\"
 .\" Copyright (c) 2001-2008 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -243,8 +243,21 @@
 .
 .It Sy MAKEOBJDIRPREFIX
 Top level directory of the object directory tree.
-If specified, must be an absolute path.
-If this is defined,
+The value is subjected to variable expansion by
+.Xr make 1 .
+.Sy build.sh
+will create the
+${MAKEOBJDIRPREFIX}
+directory if necessary, but if
+.Xr make 1
+is used without
+.Sy build.sh ,
+then rules in
+.Aq bsd.obj.mk
+will abort the build if the
+${MAKEOBJDIRPREFIX}
+directory does not exist.
+If the value is defined and valid, then
 ${MAKEOBJDIRPREFIX}/${.CURDIR}
 is used as the
 .Sy .OBJDIR
@@ -1430,6 +1443,12 @@
 .Sy MAKEOBJDIRPREFIX
 to
 .Ar obj .
+Unsets
+.Sy MAKEOBJDIR .
+See
+.Dq Fl O obj
+for more information.
+.Pp
 For instance, if the source directory is
 .Pa /usr/src ,
 a setting of
@@ -1439,13 +1458,20 @@
 .Pa /usr/obj/usr/src/lib ,
 .Pa /usr/obj/usr/src/usr.bin ,
 and so forth.
+.Pp
 If a relative path is specified, it will be converted to an
 absolute path before being used.
-Unsets
-.Sy MAKEOBJDIR .
-See
-.Dq Fl O obj
-for more information.
+.Sy build.sh
+imposes the restriction that the argument to the
+.Fl M
+option must not begin with a
+.Dq \&$
+(dollar sign)
+character; otherwise it would be too difficult
+to determine whether the value is an absolute or a relative path.
+If the directory does not already exist,
+.Sy build.sh
+will create it.
 .
 .It Fl m Ar mach
 Set the value of
@@ -1509,6 +1535,9 @@
 .Sy MAKEOBJDIR
 that will place the built object files under
 .Ar obj .
+Unsets
+.Sy MAKEOBJDIRPREFIX .
+.Pp
 For instance, a setting of
 .Dq Fl O Pa /usr/obj
 will place build-time files under
@@ -1516,10 +1545,19 @@
 .Pa /usr/obj/lib ,
 .Pa /usr/obj/usr.bin ,
 and so forth.
+.Pp
 If a relative path is specified, it will be converted to an
 absolute path before being used.
-Unsets
-.Sy MAKEOBJDIRPREFIX .
+.Sy build.sh
+imposes the restriction that the argument to the
+.Fl O
+option must not contain a
+.Dq \&$
+(dollar sign)
+character.
+If the directory does not already exist,
+.Sy build.sh
+will create it.
 .Pp
 In normal use, exactly one of the
 .Fl M

Reply via email to