THIS IS NOT AN OFFICIAL PATCH.
IF YOU APPLY IT, YOUR SYSTEM IS TAINTED.

Apply by doing:
	cd /usr/src
	patch -p0 < bsddistmake.patch

And then rebuild and install make:
	cd usr.bin/make
	make obj
	make depend
	make 
	make install

? usr.bin/make/condhashconsts.h
? usr.bin/make/generate
? usr.bin/make/make
? usr.bin/make/make.1.manlint
? usr.bin/make/nodehashconsts.h
? usr.bin/make/varhashconsts.h
Index: usr.bin/make/defines.h
===================================================================
RCS file: /cvs/src/usr.bin/make/defines.h,v
retrieving revision 1.9
diff -u -p -r1.9 defines.h
--- usr.bin/make/defines.h	19 Jul 2010 19:46:44 -0000	1.9
+++ usr.bin/make/defines.h	8 Mar 2012 11:58:59 -0000
@@ -91,6 +91,7 @@ extern int debug;
 #define DEBUG_JOBBANNER	0x1000
 #define DEBUG_PARALLEL	0x2000
 #define DEBUG_NAME_MATCHING	0x4000
+#define DEBUG_DIST	0x8000
 
 #define CONCAT(a,b)	a##b
 
Index: usr.bin/make/engine.c
===================================================================
RCS file: /cvs/src/usr.bin/make/engine.c,v
retrieving revision 1.28
diff -u -p -r1.28 engine.c
--- usr.bin/make/engine.c	25 Apr 2010 13:59:53 -0000	1.28
+++ usr.bin/make/engine.c	8 Mar 2012 11:58:59 -0000
@@ -33,7 +33,7 @@
  * SUCH DAMAGE.
  */
 
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/wait.h>
 #include <assert.h>
 #include <limits.h>
@@ -70,8 +70,8 @@ static void setup_signal(int, psighandle
 static void setup_meta(void);
 static char **recheck_command_for_shell(char **);
 
-static int setup_and_run_command(char *, GNode *, int);
-static void run_command(const char *, bool);
+static int setup_and_run_command(char *, GNode *);
+static void run_command(const char *, const struct host *, bool);
 static int run_prepared_gnode(GNode *);
 static void handle_compat_interrupts(GNode *);
 
@@ -547,44 +547,61 @@ recheck_command_for_shell(char **av)
 }
 
 static void
-run_command(const char *cmd, bool errCheck)
+run_command(const char *cmd, const struct host *host, bool errCheck)
 {
 	const char *p;
-	char *shargv[4];
+	char *shargv[12];
 	char **todo;
 
-	shargv[0] = _PATH_BSHELL;
-
-	shargv[1] = errCheck ? "-ec" : "-c";
-	shargv[2] = (char *)cmd;
-	shargv[3] = NULL;
+	if (NULL == host) {
+		shargv[0] = _PATH_BSHELL;
+		shargv[1] = errCheck ? "-ec" : "-c";
+		shargv[2] = (char *)cmd;
+		shargv[3] = NULL;
+	} else {
+		shargv[0] = "ssh";
+		shargv[1] = "-q";
+		shargv[2] = "-o";
+		shargv[3] = "ControlMaster=no";
+		shargv[4] = "-o";
+		shargv[5] = "BatchMode=yes";
+		shargv[6] = host->name;
+		shargv[7] = "cd";
+		shargv[8] = host->path;
+		shargv[9] = "&&";
+		shargv[10] = (char *)cmd;
+		shargv[11] = NULL;
+	}
 
 	todo = shargv;
 
-
-	/* Search for meta characters in the command. If there are no meta
-	 * characters, there's no need to execute a shell to execute the
-	 * command.  */
-	for (p = cmd; !meta[(unsigned char)*p]; p++)
-		continue;
-	if (*p == '\0') {
-		char *bp;
-		char **av;
-		int argc;
-		/* No meta-characters, so probably no need to exec a shell.
-		 * Break the command into words to form an argument vector
-		 * we can execute.  */
-		av = brk_string(cmd, &argc, &bp);
-		av = recheck_command_for_shell(av);
-		if (av != NULL)
-			todo = av;
+	if (NULL == host) {
+		/* Search for meta characters in the command. If there are no meta
+		 * characters, there's no need to execute a shell to execute the
+		 * command.  */
+		for (p = cmd; !meta[(unsigned char)*p]; p++)
+			continue;
+		if (*p == '\0') {
+			char *bp;
+			char **av;
+			int argc;
+			/* No meta-characters, so probably no need to exec a shell.
+			 * Break the command into words to form an argument vector
+			 * we can execute.  */
+			av = brk_string(cmd, &argc, &bp);
+			av = recheck_command_for_shell(av);
+			if (av != NULL)
+				todo = av;
+		}
 	}
+
 	execvp(todo[0], todo);
 
 	if (errno == ENOENT)
 		fprintf(stderr, "%s: not found\n", todo[0]);
 	else
 		perror(todo[0]);
+
 	_exit(1);
 }
 
@@ -602,7 +619,7 @@ run_command(const char *cmd, bool errChe
  *-----------------------------------------------------------------------
  */
 static int
-setup_and_run_command(char *cmd, GNode *gn, int dont_fork)
+setup_and_run_command(char *cmd, GNode *gn)
 {
 	bool silent;	/* Don't print command */
 	bool doExecute;	/* Execute the command */
@@ -646,22 +663,13 @@ setup_and_run_command(char *cmd, GNode *
 	if (!doExecute)
 		return 1;
 
-	/* if we're running in parallel mode, we try not to fork the last
-	 * command, since it's exit status will be just fine... unless
-	 * errCheck is not set, in which case we must deal with the
-	 * status ourselves.
-	 */
-	if (dont_fork && errCheck)
-		run_command(cmd, errCheck);
-		/*NOTREACHED*/
-
 	/* Fork and execute the single command. If the fork fails, we abort.  */
 	switch (cpid = fork()) {
 	case -1:
 		Fatal("Could not fork");
 		/*NOTREACHED*/
 	case 0:
-		run_command(cmd, errCheck);
+		run_command(cmd, gn->host, errCheck);
 		/*NOTREACHED*/
 	default:
 		break;
@@ -751,6 +759,7 @@ run_gnode(GNode *gn)
 {
 	if (gn != NULL && (gn->type & OP_DUMMY) == 0) {
 		expand_commands(gn);
+		gn->host = NULL;
 		return run_prepared_gnode(gn);
 	} else {
 		return NOSUCHNODE;
@@ -764,7 +773,7 @@ run_prepared_gnode(GNode *gn)
 
 	gn->built_status = MADE;
 	while ((cmd = Lst_DeQueue(&gn->expanded)) != NULL) {
-		if (setup_and_run_command(cmd, gn, 0) == 0)
+		if (setup_and_run_command(cmd, gn) == 0)
 			break;
 		free(cmd);
 	}
@@ -778,12 +787,51 @@ void
 run_gnode_parallel(GNode *gn)
 {
 	char *cmd;
+	char buf[(PATH_MAX * 2) + MAXHOSTNAMELEN];
+	LstNode ln;
+	GNode *pn;
+	int rc;
+	size_t sz;
 
 	gn->built_status = MADE;
+
+	if (NULL != gn->host && 
+			NULL != (ln = Lst_First(&gn->children))) {
+		cmd = estrdup("scp -oControlMaster=no -BCq");
+		sz = strlen(cmd) + 1;
+		for ( ; ln != NULL; ln = Lst_Adv(ln)) {
+			pn = Lst_Datum(ln);
+			sz += strlen(pn->path) + 1;
+			cmd = erealloc(cmd, sz);
+			strlcat(cmd, " ", sz);
+			strlcat(cmd, pn->path, sz);
+			if (DEBUG(DIST))
+				printf("Copying dependency "
+					"%s to %s:%s\n", pn->path, 
+					gn->host->name,
+					gn->host->path);
+		}
+		sz += strlen(gn->host->name) + 
+			strlen(gn->host->path) + 2;
+		cmd = erealloc(cmd, sz);
+		strlcat(cmd, " ", sz);
+		strlcat(cmd, gn->host->name, sz);
+		strlcat(cmd, ":", sz);
+		strlcat(cmd, gn->host->path, sz);
+		if ((rc = system(cmd)) < 0)
+			Punt("Cannot connect to %s: %s", 
+				gn->host->name,
+				strerror(errno));
+		else if (0 != rc)
+			Punt("Cannot copy dependecies to %s:%s",
+				gn->host->name,
+				gn->host->path);
+		free(cmd);
+	}
+
 	/* XXX don't bother freeing cmd, we're dead anyways ! */
 	while ((cmd = Lst_DeQueue(&gn->expanded)) != NULL) {
-		if (setup_and_run_command(cmd, gn,
-		    Lst_IsEmpty(&gn->expanded)) == 0)
+		if (setup_and_run_command(cmd, gn) == 0)
 			break;
 	}
 	/* Normally, we don't reach this point, unless the last command
@@ -791,6 +839,27 @@ run_gnode_parallel(GNode *gn)
 	 */
 	switch(gn->built_status) {
 	case MADE:
+		if (NULL != gn->host) {
+			if (DEBUG(DIST))
+				printf("Retrieving target "
+					"%s from %s:%s\n", gn->path, 
+					gn->host->name,
+					gn->host->path);
+			snprintf(buf, sizeof(buf), 
+					"scp -oControlMaster=no %s:%s/%s %s", 
+					gn->host->name, 
+					gn->host->path,
+					gn->path, gn->path);
+			if ((rc = system(buf)) < 0)
+				Punt("Cannot connect to %s: %s", 
+					gn->host->name,
+					strerror(errno));
+			else if (0 != rc)
+				Punt("Cannot retrieve %s from %s:%s",
+					pn->path,
+					gn->host->name,
+					gn->host->path);
+		}
 		exit(0);
 	case ERROR:
 		exit(1);
Index: usr.bin/make/extern.h
===================================================================
RCS file: /cvs/src/usr.bin/make/extern.h,v
retrieving revision 1.43
diff -u -p -r1.43 extern.h
--- usr.bin/make/extern.h	19 Jul 2010 19:46:44 -0000	1.43
+++ usr.bin/make/extern.h	8 Mar 2012 11:58:59 -0000
@@ -40,6 +40,7 @@
  *	from: @(#)nonints.h	8.3 (Berkeley) 3/19/94
  */
 
+extern bool	distMake;	/* True if distributable targets */
 extern bool	compatMake;	/* True if we are make compatible */
 extern bool	ignoreErrors;	/* True if should ignore all errors */
 extern bool	beSilent;	/* True if should print no commands */
Index: usr.bin/make/generate.c
===================================================================
RCS file: /cvs/src/usr.bin/make/generate.c,v
retrieving revision 1.12
diff -u -p -r1.12 generate.c
--- usr.bin/make/generate.c	19 Jul 2010 19:46:44 -0000	1.12
+++ usr.bin/make/generate.c	8 Mar 2012 11:58:59 -0000
@@ -116,6 +116,7 @@ char *table_nodes[] = {
 	M(NODE_BEGIN),
 	M(NODE_END),
 	M(NODE_INTERRUPT),
+	M(NODE_DIST),
 	NULL
 };
 
Index: usr.bin/make/gnode.h
===================================================================
RCS file: /cvs/src/usr.bin/make/gnode.h,v
retrieving revision 1.17
diff -u -p -r1.17 gnode.h
--- usr.bin/make/gnode.h	19 Jul 2010 19:46:44 -0000	1.17
+++ usr.bin/make/gnode.h	8 Mar 2012 11:58:59 -0000
@@ -84,9 +84,19 @@ struct Suff_;
 #define SPECIAL_SOURCE		128U
 #define SPECIAL_TARGETSOURCE	(SPECIAL_TARGET|SPECIAL_SOURCE)
 
+struct host {
+	char *path;
+	char *name;
+	int flags;
+#define	HOST_NEW 1 /* new host (has no staging directory) */
+	size_t nJobs;
+	size_t maxJobs;
+};
+
 struct GNode_ {
     unsigned int special_op;	/* special op to apply */
     unsigned char special;/* type of special node */
+    struct host *host; /* executing host */
     char must_make;	/* true if this target needs to be remade */
     char childMade;	/* true if one of this target's children was
 			 * made */
@@ -203,6 +213,7 @@ struct GNode_ {
 				     * commands for a target */
 #define OP_DEPS_FOUND	0x00800000  /* Already processed by Suff_FindDeps */
 #define OP_RESOLVED	0x01000000  /* We looked harder already */
+#define	OP_DIST		0x02000000
 
 /*
  * OP_NOP will return true if the node with the given type was not the
Index: usr.bin/make/job.c
===================================================================
RCS file: /cvs/src/usr.bin/make/job.c,v
retrieving revision 1.120
diff -u -p -r1.120 job.c
--- usr.bin/make/job.c	19 Jul 2010 19:46:44 -0000	1.120
+++ usr.bin/make/job.c	8 Mar 2012 11:58:59 -0000
@@ -69,8 +69,9 @@
  *	Job_Wait		Wait for all running jobs to finish.
  */
 
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/wait.h>
+#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -134,6 +135,9 @@ struct job_pipe {
 	size_t pos;
 };
 
+static struct host *hosts;
+static size_t hostsz;
+
 typedef struct Job_ {
     pid_t 	pid;	    /* The child's process ID */
     GNode	*node;	    /* The target the child is making */
@@ -199,6 +203,8 @@ static Job *prepare_job(GNode *, int);
 static void banner(Job *, FILE *);
 static bool Job_Full(void);
 
+static void hosts_init(size_t);
+
 /***
  ***  Input/output from jobs
  ***/
@@ -621,17 +627,38 @@ prepare_pipe(struct job_pipe *p, int *fd
 static void
 JobExec(Job *job)
 {
+	char buf[PATH_MAX + MAXHOSTNAMELEN];
 	pid_t cpid; 	/* ID of new child */
 	struct job_pid *p;
 	int fds[4];
 	int *fdout = fds;
 	int *fderr = fds+2;
-	int i;
+	int i, min, rc;
 
 	banner(job, stdout);
 
 	setup_engine(1);
 
+	/* 
+	 * If we're doing a distributed make, select minimally-loaded
+	 * host that still has slots.  If no host is available, fall
+	 * back to the localhost.
+	 */
+
+	job->node->host = NULL;
+
+	if (distMake && OP_DIST & job->node->type && hostsz > 0) {
+		for (min = i = 0; i < (int)hostsz; i++)
+			if (hosts[i].nJobs == hosts[i].maxJobs)
+				continue;
+			else if (hosts[i].nJobs < hosts[min].nJobs)
+				min = i;
+		if (hosts[min].nJobs < hosts[min].maxJobs) {
+			job->node->host = &hosts[min];
+			job->node->host->nJobs++;
+		}
+	} 
+
 	/* Create the pipe by which we'll get the shell's output.
 	 */
 	if (pipe(fdout) == -1)
@@ -671,6 +698,31 @@ JobExec(Job *job)
 
 		setup_all_signals(SigHandler, SIG_DFL);
 		unblock_signals();
+
+		/* create the staging directory */
+		if (job->node->host && 
+				HOST_NEW & job->node->host->flags) {
+			if (DEBUG(DIST))
+				printf("Creating staging "
+					"directory %s on %s\n",
+					job->node->host->path,
+					job->node->host->name);
+			snprintf(buf, sizeof(buf), 
+					"ssh -q "
+					"-oControlMaster=no "
+					"-oBatchMode=yes "
+					"%s mkdir -p %s", 
+					job->node->host->name,
+					job->node->host->path);
+			if ((rc = system(buf)) < 0)
+				Punt("Cannot connect to %s: %s", 
+					job->node->host->name,
+					strerror(errno));
+			else if (0 != rc) 
+				Punt("Cannot mkdir_p(%s) on %s",
+					job->node->host->path,
+					job->node->host->name);
+		}
 		/* this exits directly */
 		run_gnode_parallel(job->node);
 		/*NOTREACHED*/
@@ -986,6 +1038,11 @@ remove_job(LstNode ln, int status)
 	if (job->flags & JOB_IS_EXPENSIVE)
 		expensive_job = false;
 	process_job_status(job, status);
+	if (NULL != job->node->host) {
+		job->node->host->nJobs--;
+		if (HOST_NEW & job->node->host->flags) 
+			job->node->host->flags &= ~HOST_NEW;
+	}
 }
 
 /*-
@@ -1112,6 +1169,71 @@ unblock_signals()
 	sigprocmask(SIG_SETMASK, &oset, NULL);
 }
 
+static void
+hosts_init(size_t maxJobs)
+{
+	char hname[MAXHOSTNAMELEN];
+	char buf[PATH_MAX];
+	char *cp, *np;
+	const char *ep;
+	size_t len, sz;
+	FILE *f;
+
+	f = NULL;
+	assert(distMake);
+
+	if (-1 == gethostname(hname, MAXHOSTNAMELEN))
+		goto fail;
+	if (NULL == getenv("HOME")) 
+		goto fail;
+	snprintf(buf, sizeof(buf), 
+		"%s/.makehosts", getenv("HOME"));
+	if (NULL == (f = fopen(buf, "r"))) 
+		goto fail;
+	snprintf(buf, sizeof(buf), 
+		"/tmp/make-%s-%d", hname, time(NULL));
+
+	while (NULL != (cp = fgetln(f, &len))) {
+		if ('\n' != cp[len - 1]) 
+			goto fail;
+		cp[len - 1] = '\0';
+		while (isspace((unsigned char)*cp))
+			cp++;
+		if ('#' == *cp)
+			continue;
+		np = cp;
+		while ('\0' != *np && ! isspace((unsigned char)*np))
+			np++;
+		*np++ = '\0';
+		sz = strtonum(np, 0, UINT_MAX, &ep);
+		if (NULL != ep)
+			goto fail;
+		hosts = emult_realloc
+			(hosts, hostsz + 1, sizeof(struct host));
+		hosts[hostsz].name = estrdup(cp);
+		hosts[hostsz].path = estrdup(buf);
+		hosts[hostsz].maxJobs = sz;
+		hosts[hostsz].nJobs = 0;
+		hosts[hostsz].flags = HOST_NEW;
+		if (DEBUG(DIST))
+			printf("Using build host %s (%zu jobs).\n",
+					hosts[hostsz].name,
+					hosts[hostsz].maxJobs);
+		hostsz++;
+
+	}
+	fclose(f);
+	return;
+fail:
+	if (NULL != f)
+		fclose(f);
+	distMake = false;
+	if (DEBUG(DIST)) { 
+		fprintf(stderr, "Failed reading build host file.\n");
+		fprintf(stderr, "Disabling distributed builds.\n");
+	}
+}
+
 /*-
  *-----------------------------------------------------------------------
  * Job_Init --
@@ -1124,6 +1246,10 @@ unblock_signals()
 void
 Job_Init(int maxproc)
 {
+
+	if (distMake)
+		hosts_init(maxproc);
+
 	Static_Lst_Init(&runningJobs);
 	Static_Lst_Init(&errorsList);
 	maxJobs = maxproc;
@@ -1268,6 +1394,14 @@ Job_Finish(void)
 void
 Job_End(void)
 {
+	size_t i;
+
+	for (i = 0; i < hostsz; i++) {
+		free(hosts[i].name);
+		free(hosts[i].path);
+	}
+	free(hosts);
+	hosts = NULL;
 }
 #endif
 
Index: usr.bin/make/main.c
===================================================================
RCS file: /cvs/src/usr.bin/make/main.c,v
retrieving revision 1.95
diff -u -p -r1.95 main.c
--- usr.bin/make/main.c	19 Jul 2010 19:46:44 -0000	1.95
+++ usr.bin/make/main.c	8 Mar 2012 11:58:59 -0000
@@ -94,6 +94,7 @@ bool 		queryFlag;	/* -q flag */
 bool 		touchFlag;	/* -t flag */
 bool 		ignoreErrors;	/* -i flag */
 bool 		beSilent;	/* -s flag */
+bool		distMake;
 
 struct dirs {
 	char *current;
@@ -242,6 +243,9 @@ MainParseArgs(int argc, char **argv)
 				case 'd':
 					debug |= DEBUG_DIR;
 					break;
+				case 'D':
+					debug |= DEBUG_DIST;
+					break;
 				case 'f':
 					debug |= DEBUG_FOR;
 					break;
@@ -687,6 +691,7 @@ main(int argc, char **argv)
 	Static_Lst_Init(&varstoprint);
 	Static_Lst_Init(&targs);
 
+	distMake = false;		/* By default, don't distribute. */
 	beSilent = false;		/* Print commands as executed */
 	ignoreErrors = false;		/* Pay attention to non-zero returns */
 	noExecute = false;		/* Execute all commands */
Index: usr.bin/make/node_int.h
===================================================================
RCS file: /cvs/src/usr.bin/make/node_int.h,v
retrieving revision 1.2
diff -u -p -r1.2 node_int.h
--- usr.bin/make/node_int.h	19 Jul 2010 19:30:37 -0000	1.2
+++ usr.bin/make/node_int.h	8 Mar 2012 11:58:59 -0000
@@ -55,6 +55,7 @@
 #define NODE_SUFFIXES	".SUFFIXES"
 #define NODE_USE	".USE"
 #define NODE_WAIT	".WAIT"
+#define NODE_DIST	".DIST"
 
 #define NODE_BEGIN	".BEGIN"
 #define NODE_END	".END"
Index: usr.bin/make/parse.c
===================================================================
RCS file: /cvs/src/usr.bin/make/parse.c,v
retrieving revision 1.100
diff -u -p -r1.100 parse.c
--- usr.bin/make/parse.c	26 Dec 2010 13:09:22 -0000	1.100
+++ usr.bin/make/parse.c	8 Mar 2012 11:58:59 -0000
@@ -194,6 +194,7 @@ static void dump_targets(void);
 #define SPECIAL_WAIT		29U
 #define SPECIAL_NOPATH		30U
 #define SPECIAL_ERROR		31U
+#define SPECIAL_DIST		32U
 
 
 #define P(k) k, sizeof(k), K_##k
@@ -205,6 +206,7 @@ static struct {
 	unsigned int type;
 	unsigned int special_op;
 } specials[] = {
+    { P(NODE_DIST),	SPECIAL_DIST | SPECIAL_TARGETSOURCE,	OP_DIST, },
     { P(NODE_EXEC),	SPECIAL_EXEC | SPECIAL_TARGETSOURCE,	OP_EXEC, },
     { P(NODE_IGNORE),	SPECIAL_IGNORE | SPECIAL_TARGETSOURCE, 	OP_IGNORE, },
     { P(NODE_INCLUDES),	SPECIAL_INCLUDES | SPECIAL_TARGET,	0, },
@@ -408,6 +410,12 @@ ParseDoSrc(
 			waiting++;
 			return;
 		}
+	}
+
+	if (SPECIAL_DIST == specType && ! distMake) {
+		if (DEBUG(DIST))
+			printf("Enabling distributed build.\n");
+		distMake = true;
 	}
 
 	switch (specType) {
