The following set of subtle and not-so-subtle rearrangements of
the BusyBox Makefile and surrounding fluff addresses bug #1100.
Some of it is (IMHO) clean and well thought out (with thanks
to Chris, whose insight into Makefile psychology helped a lot).
Other parts are last-minute hackery to make it work.  Please,
test it and let me know what needs to be fixed.  My testing shows
it can successfully build both in-place and given a BB_SRC_DIR
that is an absolute path.

     - Larry


diff -urN /home/ldoolitt/cvs/busybox/Makefile busybox-mf/Makefile
--- /home/ldoolitt/cvs/busybox/Makefile	Thu Feb  1 20:05:01 2001
+++ busybox-mf/Makefile	Mon Feb  5 13:53:00 2001
@@ -72,7 +72,7 @@
 # If you have a "pristine" source directory, point BB_SRC_DIR to it.
 # Experimental and incomplete; tell the mailing list
 # <busybox@opensource.lineo.com> if you do or don't like it so far.
-BB_SRC_DIR = .
+BB_SRC_DIR =
 
 # If you are running a cross compiler, you may want to set this
 # to something more interesting, like "powerpc-linux-".
@@ -96,7 +96,7 @@
 #--------------------------------------------------------
 
 # use '-Os' optimization if available, else use -O2
-OPTIMIZATION = $(shell if $(CC) -Os -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
+OPTIMIZATION := $(shell if $(CC) -Os -S -o /dev/null -xc /dev/null >/dev/null 2>&1; \
     then echo "-Os"; else echo "-O2" ; fi)
 
 WARNINGS = -Wall
@@ -141,22 +141,57 @@
 endif
 
 # Additional complications due to support for pristine source dir.
-# Config.h in the build directory should take precedence over the
-# copy in BB_SRC_DIR, both during the compilation phase and the
+# Include files in the build directory should take precedence over
+# the copy in BB_SRC_DIR, both during the compilation phase and the
 # shell script that finds the list of object files.
-#
 # Work in progress by <ldoolitt@recycle.lbl.gov>.
-# If it gets in your way, set DISABLE_VPATH=yes
-ifeq ($(strip $(DISABLE_VPATH)),yes)
-    CONFIG_H = Config.h
-else
-    VPATH = .:$(BB_SRC_DIR)
-    CONFIG_LIST = $(addsuffix /Config.h,$(subst :, ,$(VPATH)))
-    CONFIG_H    = $(word 1,$(shell ls -f -1 $(CONFIG_LIST) 2>/dev/null))
-    CFLAGS += -I- $(patsubst %,-I%,$(subst :, ,$(VPATH)))
-endif
+#
+ifneq ($(strip $(BB_SRC_DIR)),)
+    VPATH += :$(BB_SRC_DIR)
+    REL_BB_SRC_DIR := $(filter-out /% ~%,$(BB_SRC_DIR))
+    ABS_BB_SRC_DIR := $(filter     /% ~%,$(BB_SRC_DIR))
+    NEXTLEVEL_BASE := $(strip $(addprefix ../,$(REL_BB_SRC_DIR)) $(ABS_BB_SRC_DIR))
+    # I give up; maybe someone else can do this manipulation with
+    # instrinsic make commands, but I resort to shell/awk.
+    NEXTLEVEL_VPATH := $(shell echo $(VPATH) | awk \
+     'BEGIN{RS=":";ORS=":"} \
+      {sub("\n","");if (substr($$0,1,1)=="/"||substr($$0,1,1)=="~"||length($$0)==0) print $$0; else print "../" $0}')
+endif
+ifneq ($(strip $(VPATH)),)
+    CFLAGS += -I- -I. $(patsubst %,-I%,$(subst :, ,$(VPATH)))
+endif
+
+# We need to set APPLET_SOURCES to something like
+#   $(shell busybox.sh Config.h)
+# but in a manner that works with VPATH and BB_SRC_DIR.
+# Possible ways to approach this:
+#
+#   1. Explicitly search through .:$(VPATH) for busybox.sh and config.h,
+#      then $(shell $(BUSYBOX_SH) $(CONFIG_H) $(BB_SRC_DIR))
+#
+#   2. Explicity search through .:$(VPATH) for slist.mk,
+#      then $(shell $(MAKE) -f $(SLIST_MK) VPATH=$(VPATH) BB_SRC_DIR=$(BB_SRC_DIR))
+#
+#   3. Create slist.mk in this directory, with commands embedded in
+#      a $(shell ...) command, and $(MAKE) it immediately.
+#
+#   4. Use a real rule within this makefile to create a file that sets 
+#      APPLET_SOURCE_LIST, then -include that file.  Has complications
+#      with the first trip through the makefile (before processing the
+#      -include) trying to do too much.
+#
+# Here comes option 3, my personal judgement as the "least of evils" solution:
+#
+APPLET_SOURCES = $(shell \
+   echo -e 'all: busybox.sh Config.h\n\t@ $$(SHELL) $$^ $$(BB_SRC_DIR)' >slist.mk; \
+   make -f slist.mk VPATH=$(VPATH) BB_SRC_DIR=$(BB_SRC_DIR) \
+)
+
+# applet_source_list: busybox.sh Config.h
+#	(echo -n "APPLET_SOURCES := "; $(SHELL) $^ $(BB_SRC_DIR)) > $@
 
-OBJECTS   = $(shell $(BB_SRC_DIR)/busybox.sh $(CONFIG_H) $(BB_SRC_DIR)) busybox.o messages.o usage.o utility.o
+
+OBJECTS   = $(APPLET_SOURCES:.c=.o) busybox.o messages.o usage.o utility.o
 CFLAGS    += $(CROSS_CFLAGS)
 CFLAGS    += -DBB_VER='"$(VERSION)"'
 CFLAGS    += -DBB_BT='"$(BUILDTIME)"'
@@ -190,12 +225,12 @@
 	@echo BusyBox Documentation
 	@echo
 	-mkdir -p docs
-	-pod2text $(BB_SRC_DIR)/docs/busybox.pod > docs/BusyBox.txt
+	-pod2text $< > $@
 
 docs/BusyBox.1: docs/busybox.pod
 	- mkdir -p docs
 	- pod2man --center=BusyBox --release="version $(VERSION)" \
-		$(BB_SRC_DIR)/docs/busybox.pod > docs/BusyBox.1
+		$< > $@
 
 docs/BusyBox.html: docs/busybox.lineo.com/BusyBox.html
 	-@ rm -f docs/BusyBox.html
@@ -203,7 +238,7 @@
 
 docs/busybox.lineo.com/BusyBox.html: docs/busybox.pod
 	-@ mkdir -p docs/busybox.lineo.com
-	-  pod2html --noindex $(BB_SRC_DIR)/docs/busybox.pod > \
+	-  pod2html --noindex $< > \
 	    docs/busybox.lineo.com/BusyBox.html
 	-@ rm -f pod2html*
 
@@ -240,11 +275,20 @@
 	$(CC) $(LDFLAGS) -o $@ $^ $(LIBRARIES)
 	$(STRIP)
 
-$(PWD_LIB):
-	$(MAKE) -eC pwd_grp
-
-busybox.links: Config.h applets.h
-	- $(BB_SRC_DIR)/busybox.mkll $(CONFIG_H) $(BB_SRC_DIR)/applets.h >$@
+# This didn't have _any_ dependencies before.
+# Won't $(PWD_LIB) go stale if someone touches the source?
+# XXX still broken for user-selected VPATH, and relative BB_SRC_DIR.
+#
+$(PWD_LIB): pwd_grp/Makefile
+	mkdir -p pwd_grp
+	@echo $(patsubst pwd_grp/%,%,$<)
+	$(MAKE) -f $(patsubst pwd_grp/%,%,$<) -eC pwd_grp VPATH=$(BB_SRC_DIR)/pwd_grp
+
+# Without VPATH, rule expands to "/bin/sh busybox.mkll Config.h applets.h"
+# but with VPATH, some or all of those file names are resolved to the
+# directories in which they live.
+busybox.links: busybox.mkll Config.h applets.h
+	- $(SHELL) $^ >$@
 
 nfsmount.o cmdedit.o: %.o: %.h
 $(OBJECTS): %.o: %.c Config.h busybox.h applets.h Makefile
@@ -252,7 +296,7 @@
 utility.o: loop.h
 
 loop.h: mk_loop_h.sh
-	@ sh $<
+	@ $(SHELL) $< > $@
 
 test tests:
 	cd tests && $(MAKE) all
@@ -266,23 +310,23 @@
 	    docs/busybox.pdf docs/busybox.lineo.com/busybox.html
 	- rm -f multibuild.log Config.h.orig
 	- rm -rf docs/busybox _install
-	- rm -f busybox.links loop.h *~ *.o core
+	- rm -f busybox.links loop.h *~ *.o slist.mk core
 
 distclean: clean
 	- rm -f busybox
 	- cd tests && $(MAKE) distclean
 
-install: busybox busybox.links
-	$(BB_SRC_DIR)/install.sh $(PREFIX)
+install: install.sh busybox busybox.links
+	$(SHELL) $< $(PREFIX)
 
-install-hardlinks: busybox busybox.links
-	$(BB_SRC_DIR)/install.sh $(PREFIX) --hardlinks
+install-hardlinks: install.sh busybox busybox.links
+	$(SHELL) $< $(PREFIX) --hardlinks
 
 debug_pristine:
 	@ echo VPATH=\"$(VPATH)\"
-	@ echo CONFIG_LIST=\"$(CONFIG_LIST)\"
-	@ echo CONFIG_H=\"$(CONFIG_H)\"
 	@ echo OBJECTS=\"$(OBJECTS)\"
+	@ echo NEXTLEVEL_BASE=\"$(NEXTLEVEL_BASE)\"
+	@ echo NEXTLEVEL_VPATH=\"$(NEXTLEVEL_VPATH)\"
 
 dist release: distclean doc
 	cd ..;					\
diff -urN /home/ldoolitt/cvs/busybox/busybox.sh busybox-mf/busybox.sh
--- /home/ldoolitt/cvs/busybox/busybox.sh	Tue Dec 26 08:36:10 2000
+++ busybox-mf/busybox.sh	Mon Feb  5 09:43:06 2001
@@ -7,7 +7,7 @@
 `
 test "${RAW}" != "" ||  exit
 cd ${2:-.}
-# I added in the extra "ls" so only source files that
-# actually exist will show up in the compile list.
-ls -1 $RAW 2>/dev/null | sed -e 's/\.c$/\.o/g'
+# By running $RAW through "ls", we avoid listing
+# source files that don't exist.
+ls $RAW 2>/dev/null | tr '\n' ' '
 
diff -urN /home/ldoolitt/cvs/busybox/mk_loop_h.sh busybox-mf/mk_loop_h.sh
--- /home/ldoolitt/cvs/busybox/mk_loop_h.sh	Wed Sep 20 19:04:51 2000
+++ busybox-mf/mk_loop_h.sh	Mon Feb  5 10:38:19 2001
@@ -2,8 +2,7 @@
 #
 # Figure out (i) the type of dev_t (ii) the defines for loop stuff
 #
-
-rm -f loop.h
+# Output of this script is normally redirected to "loop.h".
 
 # Since 1.3.79 there is an include file <asm/posix_types.h>
 # that defines __kernel_dev_t.
@@ -12,23 +11,27 @@
 # avoids namespace pollution.  Otherwise we guess that __kernel_dev_t
 # is an unsigned short (which is true on i386, but false on alpha).
 
+# BUG: This test is actually broken if your gcc is not configured to
+# search /usr/include, as may well happen with cross-compilers.
+# It would be better to ask $(CC) if these files can be found.
+
 if [ -f /usr/include/linux/posix_types.h ]; then
-   echo '#include <linux/posix_types.h>' >> loop.h
-   echo '#undef dev_t' >> loop.h
-   echo '#define dev_t __kernel_dev_t' >> loop.h
+   echo '#include <linux/posix_types.h>'
+   echo '#undef dev_t'
+   echo '#define dev_t __kernel_dev_t'
 else
-   echo '#undef dev_t' >> loop.h
-   echo '#define dev_t unsigned short' >> loop.h
+   echo '#undef dev_t'
+   echo '#define dev_t unsigned short'
 fi
 
 # Next we have to find the loop stuff itself.
 # First try kernel source, then a private version.
 
 if [ -f /usr/include/linux/loop.h ]; then
-   echo '#include <linux/loop.h>' >> loop.h
+   echo '#include <linux/loop.h>'
 else
-   echo '#include "real_loop.h"' >> loop.h
+   echo '#include "real_loop.h"'
 fi
 
-echo '#undef dev_t' >> loop.h
+echo '#undef dev_t'
 
diff -urN /home/ldoolitt/cvs/busybox/pwd_grp/Makefile busybox-mf/pwd_grp/Makefile
--- /home/ldoolitt/cvs/busybox/pwd_grp/Makefile	Sat Jan 27 01:33:39 2001
+++ busybox-mf/pwd_grp/Makefile	Mon Feb  5 13:44:57 2001
@@ -29,6 +29,11 @@
 COBJS=$(patsubst %.c,%.o, $(CSRC))
 OBJS=$(COBJS)
 
+# Minor hack until I find a better way
+ifneq ($(strip $(BB_SRC_DIR)),)
+   override CFLAGS += -I$(BB_SRC_DIR)/pwd_grp
+endif
+
 all: $(OBJS) $(LIBPWD)
 
 $(LIBPWD): ar-target
@@ -37,7 +42,6 @@
 	$(AR) $(ARFLAGS) $(LIBPWD) $(OBJS)
 
 $(COBJS):
-	$(CC) $(CFLAGS) $< -c $*.c -o $*.o
 
 $(OBJ): Makefile
 
