diff --git a/Makefile.in b/Makefile.in
index 00238b1..cbec844 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -244,6 +244,10 @@ app-objs:	dirs $(APP_OBJS)
 
 
 
+$(APP_SRCS):	srcs.tag
+
+$(COMMON_SRCS):	srcs.tag
+
 $(APP_OBJS):	$(ALL_HEADERS) host.tag tree.tag
 
 $(SHARED_OBJS):	$(ALL_HEADERS) host.tag tree.tag
@@ -300,6 +304,7 @@ distclean:	clean
 
 clean:		clean-implib
 		rm -f tree.tag
+		rm -f srcs.tag
 		rm -f dirs.tag
 		rm -f host.tag
 		rm -f host.tmp
diff --git a/sofort/core/_infer/infer_modern.mk b/sofort/core/_infer/infer_modern.mk
index e7db2a6..aaf3361 100644
--- a/sofort/core/_infer/infer_modern.mk
+++ b/sofort/core/_infer/infer_modern.mk
@@ -17,3 +17,6 @@ lib/%$(OS_ARCHIVE_EXT):
 		mkdir -p lib
 		rm -f $@
 		$(AR) rcs $@ $^
+
+srcs.tag:
+		touch $@
diff --git a/sofort/core/_infer/infer_posix.mk b/sofort/core/_infer/infer_posix.mk
index 3938325..ae990e8 100644
--- a/sofort/core/_infer/infer_posix.mk
+++ b/sofort/core/_infer/infer_posix.mk
@@ -17,3 +17,11 @@ $(STATIC_LIB):
 		mkdir -p lib
 		rm -f $@
 		$(AR) rcs $@ $(STATIC_OBJS)
+
+srcs.tag:	tree.tag
+
+srcs.tag:
+	$(PROJECT_DIR)/sofort/tools/srctree.sh \
+		--srctree=$(SOURCE_DIR) --      \
+		$(COMMON_SRCS) $(APP_SRCS)
+	touch $@
diff --git a/sofort/tools/srctree.sh b/sofort/tools/srctree.sh
new file mode 100755
index 0000000..90a1d89
--- /dev/null
+++ b/sofort/tools/srctree.sh
@@ -0,0 +1,83 @@
+#!/bin/sh
+
+# srctree.sh: support for out-of-tree builds in posix make mode.
+# this file is covered by COPYING.SOFORT.
+
+set -eu
+
+usage()
+{
+cat << EOF >&2
+
+Usage:
+  --help              show this HELP message
+  --srctree=SRCTREE   set source directory
+
+EOF
+exit 1
+}
+
+
+# one
+workdir=$(pwd -P)
+srctree=
+argloop=
+
+
+for arg ; do
+	case "$arg" in
+		--help)
+			usage
+			;;
+
+		--srctree=*)
+			srctree=${arg#*=}
+			;;
+
+		--)
+			argloop='done'
+			;;
+
+		*)
+			if [ -z "$argloop" ]; then
+				printf 'Invalid option: %s\n' "$arg" >&2
+				usage
+			fi
+			;;
+	esac
+done
+
+
+# two
+if [ -z "$srctree" ] ; then
+	usage
+fi
+
+cd -- "$srctree"
+srctree=$(pwd -P)
+cd -- "$workdir"
+
+if [ "$srctree" = "$workdir" ]; then
+	exit 0
+fi
+
+
+# three
+for arg ; do
+	case "$arg" in
+		--srctree=*)
+			;;
+
+		--)
+			;;
+
+		*)
+			stat "$arg" > /dev/null 2>&1 \
+				|| ln -s -- "$srctree/$arg" "$arg"
+			;;
+	esac
+done
+
+
+# all done
+exit 0