about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in211
-rw-r--r--doc/index.md6
-rw-r--r--mk/clean.mk87
-rw-r--r--mk/crates.mk105
-rw-r--r--mk/docs.mk35
-rw-r--r--mk/host.mk180
-rw-r--r--mk/install.mk131
-rw-r--r--mk/rt.mk318
-rw-r--r--mk/rustllvm.mk3
-rw-r--r--mk/target.mk270
-rw-r--r--mk/tests.mk112
-rw-r--r--mk/tools.mk142
-rw-r--r--src/libextra/lib.rs1
-rw-r--r--src/libflate/lib.rs (renamed from src/libextra/flate.rs)8
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/metadata/loader.rs2
-rw-r--r--src/librustc/middle/trans/base.rs2
-rw-r--r--src/librustdoc/html/markdown.rs4
18 files changed, 569 insertions, 1049 deletions
diff --git a/Makefile.in b/Makefile.in
index 101034f346e..aef766a2968 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -222,72 +222,27 @@ GENERATED :=
 
 
 ######################################################################
-# Crates
+# Cleaning out old crates
 ######################################################################
 
-define DEF_LIBS
-
-CFG_RUNTIME_$(1) :=$(call CFG_STATIC_LIB_NAME_$(1),rustrt)
-CFG_RUSTLLVM_$(1) :=$(call CFG_STATIC_LIB_NAME_$(1),rustllvm)
-CFG_STDLIB_$(1) :=$(call CFG_LIB_NAME_$(1),std)
-CFG_EXTRALIB_$(1) :=$(call CFG_LIB_NAME_$(1),extra)
-CFG_LIBRUSTC_$(1) :=$(call CFG_LIB_NAME_$(1),rustc)
-CFG_LIBSYNTAX_$(1) :=$(call CFG_LIB_NAME_$(1),syntax)
-CFG_LIBRUSTPKG_$(1) :=$(call CFG_LIB_NAME_$(1),rustpkg)
-CFG_LIBRUSTDOC_$(1) :=$(call CFG_LIB_NAME_$(1),rustdoc)
-CFG_LIBRUSTUV_$(1) :=$(call CFG_LIB_NAME_$(1),rustuv)
-CFG_LIBGREEN_$(1) :=$(call CFG_LIB_NAME_$(1),green)
-CFG_LIBNATIVE_$(1) :=$(call CFG_LIB_NAME_$(1),native)
-
-EXTRALIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),extra)
-STDLIB_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),std)
-LIBRUSTC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustc)
-LIBSYNTAX_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),syntax)
-LIBRUSTPKG_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustpkg)
-LIBRUSTDOC_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustdoc)
-LIBRUSTUV_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),rustuv)
-LIBGREEN_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),green)
-LIBNATIVE_GLOB_$(1) :=$(call CFG_LIB_GLOB_$(1),native)
-EXTRALIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),extra)
-STDLIB_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),std)
-LIBRUSTC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustc)
-LIBSYNTAX_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),syntax)
-LIBRUSTPKG_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustpkg)
-LIBRUSTDOC_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustdoc)
-LIBRUSTUV_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),rustuv)
-LIBGREEN_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),green)
-LIBNATIVE_DSYM_GLOB_$(1) :=$(call CFG_LIB_DSYM_GLOB_$(1),native)
-
-EXTRALIB_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,extra)
-STDLIB_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,std)
-LIBRUSTUV_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,rustuv)
-LIBSYNTAX_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,syntax)
-LIBRUSTC_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,rustc)
-LIBNATIVE_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,native)
-LIBGREEN_RGLOB_$(1) :=$(call CFG_RLIB_GLOB,green)
-
-endef
-
 # $(1) is the path for directory to match against
 # $(2) is the glob to use in the match
-# $(3) is filename (usually the target being created) to filter out from match
-#      (i.e. filename is not out-of-date artifact from prior Rust version/build)
 #
 # Note that a common bug is to accidentally construct the glob denoted
 # by $(2) with a space character prefix, which invalidates the
 # construction $(1)$(2).
-define CHECK_FOR_OLD_GLOB_MATCHES_EXCEPT
-  $(Q)MATCHES="$(filter-out %$(3),$(wildcard $(1)/$(2)))"; if [ -n "$$MATCHES" ] ; then echo "warning: there are previous" \'$(2)\' "libraries:" $$MATCHES; fi
+define CHECK_FOR_OLD_GLOB_MATCHES
+  $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then echo "warning: there are previous" \'$(notdir $(2))\' "libraries:" $$MATCHES; fi
 endef
 
 # Same interface as above, but deletes rather than just listing the files.
 ifdef VERBOSE
-define REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT
-  $(Q)MATCHES="$(filter-out %$(3),$(wildcard $(1)/$(2)))"; if [ -n "$$MATCHES" ] ; then echo "warning: removing previous" \'$(2)\' "libraries:" $$MATCHES; rm $$MATCHES ; fi
+define REMOVE_ALL_OLD_GLOB_MATCHES
+  $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then echo "warning: removing previous" \'$(notdir $(1))\' "libraries:" $$MATCHES; rm $$MATCHES ; fi
 endef
 else
-define REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT
-  $(Q)MATCHES="$(filter-out %$(3),$(wildcard $(1)/$(2)))"; if [ -n "$$MATCHES" ] ; then rm $$MATCHES ; fi
+define REMOVE_ALL_OLD_GLOB_MATCHES
+  $(Q)MATCHES="$(wildcard $(1))"; if [ -n "$$MATCHES" ] ; then rm $$MATCHES ; fi
 endef
 endif
 
@@ -298,72 +253,15 @@ endif
 # soon. (This is in contrast to the macros above, which are meant to
 # be run at the outset of a command list in a rule.)
 ifdef VERBOSE
-define LIST_ALL_OLD_GLOB_MATCHES_EXCEPT
-  @echo "info: now are following matches for" '$(2)' "libraries:"
-  @( cd $(1) && ( ls $(2) 2>/dev/null || true ) | grep -v $(3) || true )
+define LIST_ALL_OLD_GLOB_MATCHES
+  @echo "info: now are following matches for" '$(notdir $(1))' "libraries:"
+  @( ls $(1) 2>/dev/null || true )
 endef
 else
-define LIST_ALL_OLD_GLOB_MATCHES_EXCEPT
+define LIST_ALL_OLD_GLOB_MATCHES
 endef
 endif
 
-$(foreach target,$(CFG_TARGET),\
-  $(eval $(call DEF_LIBS,$(target))))
-
-######################################################################
-# Standard library variables
-######################################################################
-
-STDLIB_CRATE := $(S)src/libstd/lib.rs
-STDLIB_INPUTS := $(wildcard $(addprefix $(S)src/libstd/,        \
-                                           *.rs */*.rs */*/*rs */*/*/*rs))
-
-######################################################################
-# Extra library variables
-######################################################################
-
-EXTRALIB_CRATE := $(S)src/libextra/lib.rs
-EXTRALIB_INPUTS := $(wildcard $(addprefix $(S)src/libextra/,          \
-                                          *.rs */*.rs))
-
-######################################################################
-# Rust UV library variables
-######################################################################
-
-LIBRUSTUV_CRATE := $(S)src/librustuv/lib.rs
-LIBRUSTUV_INPUTS := $(wildcard $(addprefix $(S)src/librustuv/,          \
-                                          *.rs */*.rs))
-
-######################################################################
-# Green threading library variables
-######################################################################
-
-LIBGREEN_CRATE := $(S)src/libgreen/lib.rs
-LIBGREEN_INPUTS := $(wildcard $(addprefix $(S)src/libgreen/,          \
-                                          *.rs */*.rs))
-
-######################################################################
-# Native threading library variables
-######################################################################
-
-LIBNATIVE_CRATE := $(S)src/libnative/lib.rs
-LIBNATIVE_INPUTS := $(wildcard $(addprefix $(S)src/libnative/,          \
-                                          *.rs */*.rs))
-
-######################################################################
-# rustc crate variables
-######################################################################
-
-COMPILER_CRATE := $(S)src/librustc/lib.rs
-COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/librustc/,      \
-                           *.rs */*.rs */*/*.rs */*/*/*.rs))
-
-LIBSYNTAX_CRATE := $(S)src/libsyntax/lib.rs
-LIBSYNTAX_INPUTS := $(wildcard $(addprefix $(S)src/libsyntax/, \
-                           *.rs */*.rs */*/*.rs */*/*/*.rs))
-
-DRIVER_CRATE := $(S)src/driver/driver.rs
-
 ######################################################################
 # LLVM macros
 ######################################################################
@@ -425,13 +323,11 @@ export CFG_LIBDIR_RELATIVE
 export CFG_DISABLE_INJECT_STD_VERSION
 
 ######################################################################
-# Subprograms
-######################################################################
-
-######################################################################
 # Per-stage targets and runner
 ######################################################################
 
+include $(CFG_SRC_DIR)mk/crates.mk
+
 define SREQ
 # $(1) is the stage number
 # $(2) is the target triple
@@ -447,84 +343,37 @@ TROOT$(1)_T_$(2)_H_$(3) = $$(HLIB$(1)_H_$(3))/$$(CFG_RUSTLIBDIR)/$(2)
 TBIN$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/bin
 TLIB$(1)_T_$(2)_H_$(3) = $$(TROOT$(1)_T_$(2)_H_$(3))/lib
 
-# The name of the standard and extra libraries used by rustc
-HSTDLIB_DEFAULT$(1)_H_$(3) = \
-  $$(HLIB$(1)_H_$(3))/$(CFG_STDLIB_$(3))
-TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
-  $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2))
-
-HEXTRALIB_DEFAULT$(1)_H_$(3) = \
-  $$(HLIB$(1)_H_$(3))/$(CFG_EXTRALIB_$(3))
-TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3) = \
-  $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))
-
-HLIBRUSTC_DEFAULT$(1)_H_$(3) = \
-  $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTC_$(3))
-TLIBRUSTC_DEFAULT$(1)_T_$(2)_H_$(3) = \
-  $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2))
-
-HLIBRUSTUV_DEFAULT$(1)_H_$(3) = \
-  $$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTUV_$(3))
-TLIBRUSTUV_DEFAULT$(1)_T_$(2)_H_$(3) = \
-  $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2))
-
-HLIBGREEN_DEFAULT$(1)_H_$(3) = \
-  $$(HLIB$(1)_H_$(3))/$(CFG_LIBGREEN_$(3))
-TLIBGREEN_DEFAULT$(1)_T_$(2)_H_$(3) = \
-  $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBGREEN_$(2))
-
-HLIBNATIVE_DEFAULT$(1)_H_$(3) = \
-  $$(HLIB$(1)_H_$(3))/$(CFG_LIBNATIVE_$(3))
-TLIBNATIVE_DEFAULT$(1)_T_$(2)_H_$(3) = \
-  $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBNATIVE_$(2))
-
 # Preqrequisites for using the stageN compiler
 ifeq ($(1),0)
 HSREQ$(1)_H_$(3) = $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3))
 else
 HSREQ$(1)_H_$(3) = \
 	$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
-	$$(HSTDLIB_DEFAULT$(1)_H_$(3)) \
-	$$(HEXTRALIB_DEFAULT$(1)_H_$(3)) \
-	$$(HLIBSYNTAX_DEFAULT$(1)_H_$(3)) \
-	$$(HLIBRUSTC_DEFAULT$(1)_H_$(3)) \
-	$$(HLIBRUSTUV_DEFAULT$(1)_H_$(3)) \
-	$$(HLIBGREEN_DEFAULT$(1)_H_$(3)) \
-	$$(HLIBNATIVE_DEFAULT$(1)_H_$(3)) \
+	$$(HLIB$(1)_H_$(3))/stamp.rustc \
+	$$(foreach dep,$$(RUST_DEPS_rustc),$$(HLIB$(1)_H_$(3))/stamp.$$(dep)) \
 	$$(MKFILE_DEPS)
 endif
 
 # Prerequisites for using the stageN compiler to build target artifacts
 TSREQ$(1)_T_$(2)_H_$(3) = \
 	$$(HSREQ$(1)_H_$(3)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2)) \
 	$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
 
-# Prerequisites for a working stageN compiler and libraries, for a specific target
+# Prerequisites for a working stageN compiler and libraries, for a specific
+# target
 SREQ$(1)_T_$(2)_H_$(3) = \
 	$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBGREEN_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBNATIVE_$(2))
+	$$(foreach dep,$$(TARGET_CRATES),\
+	    $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep))
 
-# Prerequisites for a working stageN compiler and libraries, for a specific target
+# Prerequisites for a working stageN compiler and complete set of target
+# libraries
 CSREQ$(1)_T_$(2)_H_$(3) = \
 	$$(TSREQ$(1)_T_$(2)_H_$(3)) \
 	$$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(3)) \
 	$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
-	$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTPKG_$(3)) \
-	$$(HLIB$(1)_H_$(3))/$(CFG_LIBRUSTDOC_$(3)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))  \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2))  \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBGREEN_$(2)) \
-	$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBNATIVE_$(2))
+	$$(foreach dep,$$(CRATES),$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \
+	$$(foreach dep,$$(HOST_CRATES),$$(HLIB$(1)_H_$(3))/stamp.$$(dep))
 
 ifeq ($(1),0)
 # Don't run the the stage0 compiler under valgrind - that ship has sailed
@@ -562,15 +411,15 @@ endif
 STAGE$(1)_T_$(2)_H_$(3) := 						\
 	$$(Q)$$(RPATH_VAR$(1)_T_$(2)_H_$(3))                            \
 		$$(call CFG_RUN_TARG_$(3),$(1),				\
-		$$(CFG_VALGRIND_COMPILE$(1)) 			\
+		$$(CFG_VALGRIND_COMPILE$(1))				\
 		$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3))			\
 		--cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3))			\
 		$$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \
                 $$(RUSTC_FLAGS_$(2))
 
-PERF_STAGE$(1)_T_$(2)_H_$(3) := 				\
+PERF_STAGE$(1)_T_$(2)_H_$(3) :=						\
 	$$(Q)$$(call CFG_RUN_TARG_$(3),$(1),				\
-		$$(CFG_PERF_TOOL) 						\
+		$$(CFG_PERF_TOOL) 					\
 		$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3))			\
 		--cfg $$(CFGFLAG$(1)_T_$(2)_H_$(3))			\
 		$$(CFG_RUSTC_FLAGS) $$(EXTRAFLAGS_STAGE$(1)) --target=$(2)) \
@@ -594,13 +443,12 @@ define DEF_RUSTC_STAGE_TARGET
 # $(2) == stage
 
 rustc-stage$(2)-H-$(1):							\
-	$$(foreach target,$$(CFG_TARGET),	\
-		$$(SREQ$(2)_T_$$(target)_H_$(1)))
+	$$(foreach target,$$(CFG_TARGET),$$(SREQ$(2)_T_$$(target)_H_$(1)))
 
 endef
 
-$(foreach host,$(CFG_HOST),							\
- $(eval $(foreach stage,1 2 3,									\
+$(foreach host,$(CFG_HOST),						\
+ $(eval $(foreach stage,1 2 3,						\
   $(eval $(call DEF_RUSTC_STAGE_TARGET,$(host),$(stage))))))
 
 rustc-stage1: rustc-stage1-H-$(CFG_BUILD)
@@ -701,7 +549,6 @@ include $(CFG_SRC_DIR)mk/target.mk
 include $(CFG_SRC_DIR)mk/host.mk
 include $(CFG_SRC_DIR)mk/stage0.mk
 include $(CFG_SRC_DIR)mk/rustllvm.mk
-include $(CFG_SRC_DIR)mk/tools.mk
 include $(CFG_SRC_DIR)mk/docs.mk
 include $(CFG_SRC_DIR)mk/llvm.mk
 
diff --git a/doc/index.md b/doc/index.md
index 53ad4217145..16c6db3859c 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -37,6 +37,8 @@ li {list-style-type: none; }
 * [The Rust parser, `libsyntax`](syntax/index.html)
 * [The Rust compiler, `librustc`](rustc/index.html)
 
+* [The `flate` compression library](flate/index.html)
+
 # Tooling
 
 * [The `rustdoc` manual](rustdoc.html)
@@ -47,11 +49,11 @@ li {list-style-type: none; }
 * [Language FAQ](complement-lang-faq.html)
 * [Project FAQ](complement-project-faq.html)
 * [Usage FAQ](complement-usage-faq.html)
-* [Code cheatsheet](complement-cheatsheet.html) - "How do I do X?"  
+* [Code cheatsheet](complement-cheatsheet.html) - "How do I do X?"
 * [How to submit a bug report](complement-bugreport.html)
 
 # External resources
 
-* The Rust [IRC channel](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) - `#rust` on irc.mozilla.org  
+* The Rust [IRC channel](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust) - `#rust` on irc.mozilla.org
 * The Rust community on [Reddit](http://reddit.com/r/rust)
 * The Rust [wiki](http://github.com/mozilla/rust/wiki)
diff --git a/mk/clean.mk b/mk/clean.mk
index 14998cfbb22..27c779f107d 100644
--- a/mk/clean.mk
+++ b/mk/clean.mk
@@ -63,6 +63,7 @@ clean-generic-$(2)-$(1):
          -name '*.[odasS]' -o \
          -name '*.so' -o      \
          -name '*.dylib' -o   \
+         -name 'stamp.*' -o   \
          -name '*.lib' -o     \
          -name '*.dll' -o     \
          -name '*.def' -o     \
@@ -78,37 +79,16 @@ $(foreach targ, $(CFG_TARGET), $(eval $(call CLEAN_GENERIC,$(targ),T)))
 
 define CLEAN_HOST_STAGE_N
 
-clean$(1)_H_$(2):
-	$(Q)rm -f $$(HBIN$(1)_H_$(2))/rustc$(X_$(2))
-	$(Q)rm -f $$(HBIN$(1)_H_$(2))/rustpkg$(X_$(2))
-	$(Q)rm -f $$(HBIN$(1)_H_$(2))/serializer$(X_$(2))
-	$(Q)rm -f $$(HBIN$(1)_H_$(2))/rustdoc$(X_$(2))
-	$(Q)rm -f $$(HBIN$(1)_H_$(2))/rust$(X_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTPKG_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTDOC_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUNTIME_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_STDLIB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_EXTRALIB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTUV_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBNATIVE_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBGREEN_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBRUSTC_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_LIBSYNTAX_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(STDLIB_RGLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(EXTRALIB_RGLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTUV_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTUV_RGLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBNATIVE_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBNATIVE_RGLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBGREEN_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBGREEN_RGLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTC_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBSYNTAX_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTPKG_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(LIBRUSTDOC_GLOB_$(2))
-	$(Q)rm -f $$(HLIB$(1)_H_$(2))/$(CFG_RUSTLLVM_$(2))
+clean$(1)_H_$(2):							    \
+	    $$(foreach crate,$$(CRATES),clean$(1)_H_$(2)-lib-$$(crate))	    \
+	    $$(foreach tool,$$(TOOLS),clean$(1)_H_$(2)-tool-$$(tool))
+
+clean$(1)_H_$(2)-tool-%:
+	$$(Q)rm -f $$(HBIN$(1)_H_$(2))/$$*$$(X_$(2))
+
+clean$(1)_H_$(2)-lib-%:
+	$$(Q)rm -f $$(HLIB$(1)_H_$(2))/$$(call CFG_LIB_GLOB_$(2),$$*)
+	$$(Q)rm -f $$(HLIB$(1)_H_$(2))/$$(call CFG_RLIB_GLOB,$$*)
 
 endef
 
@@ -118,42 +98,19 @@ $(foreach host, $(CFG_HOST), \
 
 define CLEAN_TARGET_STAGE_N
 
-clean$(1)_T_$(2)_H_$(3):
-	$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustc$(X_$(2))
-	$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$(X_$(2))
-	$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/serializer$(X_$(2))
-	$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rustdoc$(X_$(2))
-	$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/rust$(X_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTPKG_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTDOC_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBGREEN_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBNATIVE_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(STDLIB_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(EXTRALIB_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTUV_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTUV_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBNATIVE_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBNATIVE_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBGREEN_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBGREEN_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTC_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBSYNTAX_RGLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTPKG_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(LIBRUSTDOC_GLOB_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(2))
-	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
+clean$(1)_T_$(2)_H_$(3):						       \
+	    $$(foreach crate,$$(CRATES),clean$(1)_T_$(2)_H_$(3)-lib-$$(crate))  \
+	    $$(foreach tool,$$(TOOLS),clean$(1)_T_$(2)_H_$(3)-tool-$$(tool))
+	$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a
 	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/librun_pass_stage* # For unix
 	$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/run_pass_stage* # For windows
+
+clean$(1)_T_$(2)_H_$(3)-tool-%:
+	$$(Q)rm -f $$(TBIN$(1)_T_$(2)_H_$(3))/$$*$$(X_$(2))
+
+clean$(1)_T_$(2)_H_$(3)-lib-%:
+	$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$$(call CFG_LIB_GLOB_$(2),$$*)
+	$$(Q)rm -f $$(TLIB$(1)_T_$(2)_H_$(3))/$$(call CFG_RLIB_GLOB,$$*)
 endef
 
 $(foreach host, $(CFG_HOST), \
diff --git a/mk/crates.mk b/mk/crates.mk
new file mode 100644
index 00000000000..dc374549dad
--- /dev/null
+++ b/mk/crates.mk
@@ -0,0 +1,105 @@
+# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+################################################################################
+# Rust's standard distribution of crates and tools
+#
+# The crates outlined below are the standard distribution of libraries provided
+# in a rust installation. These rules are meant to abstract over the
+# dependencies (both native and rust) of crates and basically generate all the
+# necessary makefile rules necessary to build everything.
+#
+# Here's an explanation of the variables below
+#
+#   TARGET_CRATES
+#	This list of crates will be built for all targets, including
+#	cross-compiled targets
+#
+#   HOST_CRATES
+#	This list of crates will be compiled for only host targets. Note that
+#	this set is explicitly *not* a subset of TARGET_CRATES, but rather it is
+#	a disjoint set. Nothing in the TARGET_CRATES set can depend on crates in
+#	the HOST_CRATES set, but the HOST_CRATES set can depend on target
+#	crates.
+#
+#   TOOLS
+#	A list of all tools which will be built as part of the compilation
+#	process. It is currently assumed that most tools are built through
+#	src/driver/driver.rs with a particular configuration (there's a
+#	corresponding library providing the implementation)
+#
+#   DEPS_<crate>
+#	These lists are the dependencies of the <crate> that is to be built.
+#	Rust dependencies are listed bare (i.e. std, extra, green) and native
+#	dependencies have a "native:" prefix (i.e. native:sundown). All deps
+#	will be built before the crate itself is built.
+#
+#   TOOL_DEPS_<tool>/TOOL_SOURCE_<tool>
+#	Similar to the DEPS variable, this is the library crate dependencies
+#	list for tool as well as the source file for the specified tool
+#
+# You shouldn't need to modify much other than these variables. Crates are
+# automatically generated for all stage/host/target combinations.
+################################################################################
+
+TARGET_CRATES := std extra green rustuv native flate
+HOST_CRATES := syntax rustc rustdoc rustpkg
+CRATES := $(TARGET_CRATES) $(HOST_CRATES)
+TOOLS := compiletest rustpkg rustdoc rustc
+
+DEPS_std := native:rustrt
+DEPS_extra := std
+DEPS_green := std
+DEPS_rustuv := std native:uv native:uv_support
+DEPS_native := std
+DEPS_syntax := std extra
+DEPS_rustc := syntax native:rustllvm flate
+DEPS_rustdoc := rustc native:sundown
+DEPS_rustpkg := rustc
+DEPS_flate := std native:miniz
+
+TOOL_DEPS_compiletest := extra green rustuv
+TOOL_DEPS_rustpkg := rustpkg green rustuv
+TOOL_DEPS_rustdoc := rustdoc green rustuv
+TOOL_DEPS_rustc := rustc green rustuv
+TOOL_SOURCE_compiletest := $(S)src/compiletest/compiletest.rs
+TOOL_SOURCE_rustpkg := $(S)src/driver/driver.rs
+TOOL_SOURCE_rustdoc := $(S)src/driver/driver.rs
+TOOL_SOURCE_rustc := $(S)src/driver/driver.rs
+
+################################################################################
+# You should not need to edit below this line
+################################################################################
+
+DOC_CRATES := $(filter-out rustc, $(filter-out syntax, $(CRATES)))
+
+# This macro creates some simple definitions for each crate being built, just
+# some munging of all of the parameters above.
+#
+# $(1) is the crate to generate variables for
+define RUST_CRATE
+CRATEFILE_$(1) := $$(S)src/lib$(1)/lib.rs
+RSINPUTS_$(1) := $$(wildcard $$(addprefix $(S)src/lib$(1), \
+				*.rs */*.rs */*/*.rs */*/*/*.rs))
+RUST_DEPS_$(1) := $$(filter-out native:%,$$(DEPS_$(1)))
+NATIVE_DEPS_$(1) := $$(patsubst native:%,%,$$(filter native:%,$$(DEPS_$(1))))
+endef
+
+$(foreach crate,$(CRATES),$(eval $(call RUST_CRATE,$(crate))))
+
+# Similar to the macro above for crates, this macro is for tools
+#
+# $(1) is the crate to generate variables for
+define RUST_TOOL
+TOOL_INPUTS_$(1) := $$(wildcard $$(addprefix $(S)$$(dir $$(TOOL_SOURCE_$(1))), \
+				*.rs */*.rs */*/*.rs */*/*/*.rs))
+endef
+
+$(foreach crate,$(TOOLS),$(eval $(call RUST_TOOL,$(crate))))
diff --git a/mk/docs.mk b/mk/docs.mk
index bacf39e1307..2eb12ae47cc 100644
--- a/mk/docs.mk
+++ b/mk/docs.mk
@@ -290,38 +290,27 @@ endif
 RUSTDOC = $(HBIN2_H_$(CFG_BUILD))/rustdoc$(X_$(CFG_BUILD))
 
 # The library documenting macro
+#
 # $(1) - The crate name (std/extra)
-# $(2) - The crate file
-# $(3) - The relevant host build triple (to depend on libstd)
 #
 # Passes --cfg stage2 to rustdoc because it uses the stage2 librustc.
 define libdoc
-doc/$(1)/index.html: $$(RUSTDOC) $$(TLIB2_T_$(3)_H_$(3))/$(CFG_STDLIB_$(3)) \
-		$(foreach name,$(4),$$(TLIB2_T_$(3)_H_$(3))/$$(CFG_$(name)_$(3)))
-	@$$(call E, rustdoc: $$@)
-	$(Q)$(RUSTDOC) --cfg stage2 $(2)
-
-DOCS += doc/$(1)/index.html
-endef
-
-define compiledoc
-doc/$(1)/index.html: $$(RUSTDOC) $$(TLIB2_T_$(3)_H_$(3))/$(CFG_STDLIB_$(3))
+doc/$(1)/index.html:							    \
+	    $$(CRATEFILE_$(1))						    \
+	    $$(RSINPUTS_$(1))						    \
+	    $$(RUSTDOC)							    \
+	    $$(foreach dep,$$(RUST_DEPS_$(1)),				    \
+		$$(TLIB2_T_$(CFG_BUILD)_H_$(CFG_BUILD))/stamp.$$(dep))
 	@$$(call E, rustdoc: $$@)
-	$(Q)$(RUSTDOC) --cfg stage2 $(2)
-
-CDOCS += doc/$(1)/index.html
+	$$(Q)$$(RUSTDOC) --cfg stage2 $$<
 endef
 
-$(eval $(call libdoc,std,$(STDLIB_CRATE),$(CFG_BUILD)))
-$(eval $(call libdoc,extra,$(EXTRALIB_CRATE),$(CFG_BUILD)))
-$(eval $(call libdoc,native,$(LIBNATIVE_CRATE),$(CFG_BUILD)))
-$(eval $(call libdoc,green,$(LIBGREEN_CRATE),$(CFG_BUILD)))
-$(eval $(call libdoc,rustuv,$(LIBRUSTUV_CRATE),$(CFG_BUILD)))
-$(eval $(call libdoc,rustpkg,$(RUSTPKG_LIB),$(CFG_BUILD),EXTRALIB LIBRUSTC))
+$(foreach crate,$(CRATES),$(eval $(call libdoc,$(crate))))
 
-$(eval $(call compiledoc,rustc,$(COMPILER_CRATE),$(CFG_BUILD)))
-$(eval $(call compiledoc,syntax,$(LIBSYNTAX_CRATE),$(CFG_BUILD)))
+DOCS += $(DOC_CRATES:%=doc/%/index.html)
 
+CDOCS += doc/rustc/index.html
+CDOCS += doc/syntax/index.html
 
 ifdef CFG_DISABLE_DOCS
   $(info cfg: disabling doc build (CFG_DISABLE_DOCS))
diff --git a/mk/host.mk b/mk/host.mk
index 5de12f90bcf..7a3664d897d 100644
--- a/mk/host.mk
+++ b/mk/host.mk
@@ -8,155 +8,75 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
-# CP_HOST_STAGE_N template: arg 1 is the N we're promoting *from*, arg
-# 2 is N+1. Must be invoked to promote target artifacts to host
-# artifacts for stage 1-3 (stage0 host artifacts come from the
-# snapshot).  Arg 3 is the triple we're copying FROM and arg 4 is the
-# triple we're copying TO.
+# Generic rule for copying any target crate to a host crate. This rule will also
+# promote any dependent rust crates up to their host locations as well
 #
-# The easiest way to read this template is to assume we're promoting
-# stage1 to stage2 and mentally gloss $(1) as 1, $(2) as 2.
-
-define CP_HOST_STAGE_N
-
-# Host libraries and executables (stage$(2)/bin/rustc and its runtime needs)
-
-# Note: $(3) and $(4) are both the same!
-
-$$(HBIN$(2)_H_$(4))/rustc$$(X_$(4)): \
-	$$(TBIN$(1)_T_$(4)_H_$(3))/rustc$$(X_$(4)) \
-	$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)) \
-	| $$(HBIN$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
-
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \
-	$$(HLIB$(2)_H_$(4))/$(CFG_LIBSYNTAX_$(4)) \
+# $(1) - the stage to copy from
+# $(2) - the stage to copy to
+# $(3) - the host triple
+# $(4) - the target triple (same as $(3))
+# $(5) - the name of the crate being processed
+define CP_HOST_STAGE_N_CRATE
+
+$$(HLIB$(2)_H_$(4))/stamp.$(5):					\
+	$$(TLIB$(1)_T_$(3)_H_$(4))/stamp.$(5)			\
+	$$(RUST_DEPS_$(5):%=$$(HLIB$(2)_H_$(4))/stamp.%)	\
 	| $$(HLIB$(2)_H_$(4))/
-
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(4)),$$(notdir $$@))
+	@$$(call E, cp: $$(@D)/lib$(5))
+	$$(call REMOVE_ALL_OLD_GLOB_MATCHES,\
+	    $$(dir $$@)$$(call CFG_LIB_GLOB_$(3),$(5)))
 	$$(Q)cp $$< $$@
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTC_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTC_DSYM_GLOB_$(4))) \
+	$$(Q)cp -R $$(TLIB$(1)_T_$(3)_H_$(4))/$$(call CFG_LIB_GLOB_$(3),$(5)) \
 	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(4)),$$(notdir $$@))
+	$$(call LIST_ALL_OLD_GLOB_MATCHES,\
+	    $$(dir $$@)$$(call CFG_LIB_GLOB_$(3),$(5)))
 
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBSYNTAX_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBSYNTAX_$(4)) \
-	$$(HSTDLIB_DEFAULT$(2)_H_$(4)) \
-	$$(HEXTRALIB_DEFAULT$(2)_H_$(4)) \
-	$$(HLIBRUSTUV_DEFAULT$(2)_H_$(4)) \
-	$$(HLIBGREEN_DEFAULT$(2)_H_$(4)) \
-	$$(HLIBNATIVE_DEFAULT$(2)_H_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_GLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBSYNTAX_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBSYNTAX_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_GLOB_$(4)),$$(notdir $$@))
+endef
 
-$$(HLIB$(2)_H_$(4))/$(CFG_RUNTIME_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_RUNTIME_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
+# Same as the above macro, but for tools instead of crates
+define CP_HOST_STAGE_N_TOOL
 
-$$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_STDLIB_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(4)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-# Subtle: We do not let the shell expand $$(STDLIB_DSYM_GLOB) directly rather
-# we use Make's $$(wildcard) facility. The reason is that, on mac, when using
-# USE_SNAPSHOT_STDLIB, we copy the std.dylib file out of the snapshot.
-# In that case, there is no .dSYM file.  Annoyingly, bash then refuses to expand
-# glob, and cp reports an error because libstd-*.dylib.dsym does not exist.
-# Make instead expands the glob to nothing, which gives us the correct behavior.
-# (Copy .dsym file if it exists, but do nothing otherwise)
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_RGLOB_$(4))) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(4)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(4)),$$(notdir $$@))
-
-$$(HLIB$(2)_H_$(4))/$(CFG_EXTRALIB_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_EXTRALIB_$(4)) \
-	$$(HSTDLIB_DEFAULT$(2)_H_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
+$$(HBIN$(2)_H_$(4))/$(5)$$(X_$(3)): \
+	$$(TBIN$(1)_T_$(3)_H_$(4))/$(5)$$(X_$(3)) \
+	$$(TOOL_DEPS_$(5):%=$$(HLIB$(2)_H_$(4))/stamp.%) \
+	| $$(HBIN$(2)_H_$(4))/
 	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(4)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(4)),$$(notdir $$@))
 	$$(Q)cp $$< $$@
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_RGLOB_$(4))) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(EXTRALIB_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(4)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(4)),$$(notdir $$@))
 
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTUV_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTUV_$(4)) \
-	$$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(4)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTUV_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTUV_RGLOB_$(4))) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTUV_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(4)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(4)),$$(notdir $$@))
+endef
 
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBGREEN_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBGREEN_$(4)) \
-	$$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_GLOB_$(4)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_RGLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBGREEN_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBGREEN_RGLOB_$(4))) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBGREEN_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_GLOB_$(4)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_RGLOB_$(4)),$$(notdir $$@))
 
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBNATIVE_$(4)): \
-	$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBNATIVE_$(4)) \
-	$$(HLIB$(2)_H_$(4))/$(CFG_STDLIB_$(4)) \
-	| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_GLOB_$(4)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_RGLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBNATIVE_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBNATIVE_RGLOB_$(4))) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBNATIVE_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_GLOB_$(4)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_RGLOB_$(4)),$$(notdir $$@))
+# Miscellaneous rules for just making a few directories.
+#
+# $(1) - the stage to copy from
+# $(2) - the stage to copy to
+# $(3) - the target triple
+# $(4) - the host triple (same as $(3))
+define CP_HOST_STAGE_N
 
 $$(HBIN$(2)_H_$(4))/:
-	mkdir -p $$@
+	@mkdir -p $$@
 
 ifneq ($(CFG_LIBDIR_RELATIVE),bin)
 $$(HLIB$(2)_H_$(4))/:
-	mkdir -p $$@
+	@mkdir -p $$@
 endif
 
 endef
 
-$(foreach t,$(CFG_HOST),					\
-	$(eval $(call CP_HOST_STAGE_N,0,1,$(t),$(t)))	\
-	$(eval $(call CP_HOST_STAGE_N,1,2,$(t),$(t)))	\
+$(foreach t,$(CFG_HOST),						    \
+	$(eval $(call CP_HOST_STAGE_N,0,1,$(t),$(t)))			    \
+	$(eval $(call CP_HOST_STAGE_N,1,2,$(t),$(t)))			    \
 	$(eval $(call CP_HOST_STAGE_N,2,3,$(t),$(t))))
+
+$(foreach crate,$(CRATES),						    \
+ $(foreach t,$(CFG_HOST),						    \
+  $(eval $(call CP_HOST_STAGE_N_CRATE,0,1,$(t),$(t),$(crate)))		    \
+  $(eval $(call CP_HOST_STAGE_N_CRATE,1,2,$(t),$(t),$(crate)))		    \
+  $(eval $(call CP_HOST_STAGE_N_CRATE,2,3,$(t),$(t),$(crate)))))
+
+$(foreach tool,$(TOOLS),						    \
+ $(foreach t,$(CFG_HOST),						    \
+  $(eval $(call CP_HOST_STAGE_N_TOOL,0,1,$(t),$(t),$(tool)))		    \
+  $(eval $(call CP_HOST_STAGE_N_TOOL,1,2,$(t),$(t),$(tool)))		    \
+  $(eval $(call CP_HOST_STAGE_N_TOOL,2,3,$(t),$(t),$(tool)))))
diff --git a/mk/install.mk b/mk/install.mk
index f275f6fd9ff..33f170f4f97 100644
--- a/mk/install.mk
+++ b/mk/install.mk
@@ -65,6 +65,8 @@ PREFIX_ROOT = $(CFG_PREFIX)
 PREFIX_BIN = $(PREFIX_ROOT)/bin
 PREFIX_LIB = $(CFG_LIBDIR)
 
+INSTALL_TOOLS := $(filter-out compiletest, $(TOOLS))
+
 define INSTALL_PREPARE_N
   # $(1) is the target triple
   # $(2) is the host triple
@@ -86,43 +88,35 @@ $(foreach target,$(CFG_TARGET), \
 define INSTALL_TARGET_N
 install-target-$(1)-host-$(2): LIB_SOURCE_DIR=$$(TL$(1)$(2))
 install-target-$(1)-host-$(2): LIB_DESTIN_DIR=$$(PTL$(1)$(2))
-install-target-$(1)-host-$(2): $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2)) $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
+install-target-$(1)-host-$(2):						\
+	    $$(TSREQ$$(ISTAGE)_T_$(1)_H_$(2))				\
+	    $$(SREQ$$(ISTAGE)_T_$(1)_H_$(2))
 	$$(Q)$$(call MK_INSTALL_DIR,$$(PTL$(1)$(2)))
-	$$(Q)$$(call INSTALL_LIB,$$(STDLIB_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(STDLIB_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(EXTRALIB_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(EXTRALIB_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTUV_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTUV_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBGREEN_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBGREEN_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBNATIVE_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBNATIVE_RGLOB_$(1)))
+	$$(Q)$$(foreach crate,$$(TARGET_CRATES),\
+		$$(call INSTALL_LIB,$$(call CFG_LIB_GLOB_$(1),$$(crate)));
+		$$(call INSTALL_LIB,$$(call CFG_RLIB_GLOB,$$(crate)));)
 	$$(Q)$$(call INSTALL_LIB,libmorestack.a)
 
+install-target-$(1)-host-$(2)-prep:
+
+install-target-$(1)-host-$(2)-morestack:
+
+install-target-$(1)-host-$(2)-lib-%:
+install-target-$(1)-host-$(2)-rlib-%:
+
 endef
 
 define INSTALL_HOST_N
+
 install-target-$(1)-host-$(2): LIB_SOURCE_DIR=$$(TL$(1)$(2))
 install-target-$(1)-host-$(2): LIB_DESTIN_DIR=$$(PTL$(1)$(2))
 install-target-$(1)-host-$(2): $$(CSREQ$$(ISTAGE)_T_$(1)_H_$(2))
 	$$(Q)$$(call MK_INSTALL_DIR,$$(PTL$(1)$(2)))
-	$$(Q)$$(call INSTALL_LIB,$$(STDLIB_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(STDLIB_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(EXTRALIB_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(EXTRALIB_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTUV_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTUV_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBGREEN_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBGREEN_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBNATIVE_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBNATIVE_RGLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTC_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBSYNTAX_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTPKG_GLOB_$(1)))
-	$$(Q)$$(call INSTALL_LIB,$$(LIBRUSTDOC_GLOB_$(1)))
+	$$(Q)$$(foreach crate,$$(CRATES),\
+	    $$(call INSTALL_LIB,$$(call CFG_LIB_GLOB_$(1),$$(crate)));)
+	$$(Q)$$(foreach crate,$$(TARGET_CRATES),\
+	    $$(call INSTALL_LIB,$$(call CFG_RLIB_GLOB,$$(crate)));)
 	$$(Q)$$(call INSTALL_LIB,libmorestack.a)
-
 endef
 
 $(foreach target,$(CFG_TARGET), \
@@ -145,26 +139,35 @@ PHB = $(PREFIX_BIN)
 # Shorthand for the prefix bin directory
 PHL = $(PREFIX_LIB)
 
-install-host: LIB_SOURCE_DIR=$(HL)
-install-host: LIB_DESTIN_DIR=$(PHL)
-install-host: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD_)_H_$(CFG_BUILD_))
+install-host%: LIB_SOURCE_DIR=$(HL)
+install-host%: LIB_DESTIN_DIR=$(PHL)
+install-host:								    \
+	    install-host-prep						    \
+	    $(foreach tool,$(INSTALL_TOOLS),install-host-tool-$(tool))
+
+install-host-prep: $(CSREQ$(ISTAGE)_T_$(CFG_BUILD)_H_$(CFG_BUILD))
 	$(Q)$(call MK_INSTALL_DIR,$(PREFIX_BIN))
 	$(Q)$(call MK_INSTALL_DIR,$(PREFIX_LIB))
 	$(Q)$(call MK_INSTALL_DIR,$(CFG_MANDIR)/man1)
-	$(Q)$(call INSTALL,$(HB2),$(PHB),rustc$(X_$(CFG_BUILD)))
-	$(Q)$(call INSTALL,$(HB2),$(PHB),rustpkg$(X_$(CFG_BUILD)))
-	$(Q)$(call INSTALL,$(HB2),$(PHB),rustdoc$(X_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(STDLIB_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(EXTRALIB_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(LIBRUSTUV_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(LIBGREEN_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(LIBRUSTC_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(LIBSYNTAX_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL_LIB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD)))
-	$(Q)$(call INSTALL,$(S)/man,$(CFG_MANDIR)/man1,rustc.1)
-	$(Q)$(call INSTALL,$(S)/man,$(CFG_MANDIR)/man1,rustdoc.1)
-	$(Q)$(call INSTALL,$(S)/man,$(CFG_MANDIR)/man1,rustpkg.1)
+
+define INSTALL_HOST_TOOL
+install-host-tool-$(1):							    \
+	    $$(foreach dep,$$(TOOL_DEPS_$(1)),install-host-lib-$$(dep))	    \
+	    $$(CSREQ$$(ISTAGE)_T_$$(CFG_BUILD)_H_$$(CFG_BUILD))
+	$$(Q)$$(call INSTALL,$$(HB2),$$(PHB),$(1)$$(X_$$(CFG_BUILD)))
+	$$(Q)$$(call INSTALL,$$(S)/man,$$(CFG_MANDIR)/man1,$(1).1)
+endef
+
+$(foreach tool,$(INSTALL_TOOLS),$(eval $(call INSTALL_HOST_TOOL,$(tool))))
+
+define INSTALL_HOST_LIB
+install-host-lib-$(1):							    \
+	    $$(foreach dep,$$(RUST_DEPS_$(1)),install-host-lib-$$(dep))	    \
+	    $$(CSREQ$$(ISTAGE)_T_$$(CFG_BUILD)_H_$$(CFG_BUILD))
+	$$(Q)$$(call INSTALL_LIB,$$(call CFG_LIB_GLOB_$$(CFG_BUILD),$(1)))
+endef
+
+$(foreach lib,$(CRATES),$(eval $(call INSTALL_HOST_LIB,$(lib))))
 
 install-targets: $(INSTALL_TARGET_RULES)
 
@@ -172,33 +175,23 @@ install-targets: $(INSTALL_TARGET_RULES)
 HOST_LIB_FROM_HL_GLOB = \
   $(patsubst $(HL)/%,$(PHL)/%,$(wildcard $(HL)/$(1)))
 
-uninstall:
-	$(Q)rm -f $(PHB)/rustc$(X_$(CFG_BUILD))
-	$(Q)rm -f $(PHB)/rustpkg$(X_$(CFG_BUILD))
-	$(Q)rm -f $(PHB)/rustdoc$(X_$(CFG_BUILD))
-	$(Q)for i in \
-          $(call HOST_LIB_FROM_HL_GLOB,$(STDLIB_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(STDLIB_RGLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(EXTRALIB_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(EXTRALIB_RGLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTUV_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTUV_RGLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBGREEN_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBGREEN_RGLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBNATIVE_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBNATIVE_RGLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTC_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBSYNTAX_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTPKG_GLOB_$(CFG_BUILD))) \
-          $(call HOST_LIB_FROM_HL_GLOB,$(LIBRUSTDOC_GLOB_$(CFG_BUILD))) \
-        ; \
-        do rm -f $$i ; \
-        done
+uninstall: $(foreach tool,$(INSTALL_TOOLS),uninstall-tool-$(tool))
 	$(Q)rm -Rf $(PHL)/$(CFG_RUSTLIBDIR)
-	$(Q)rm -f $(CFG_MANDIR)/man1/rustc.1
-	$(Q)rm -f $(CFG_MANDIR)/man1/rustdoc.1
-	$(Q)rm -f $(CFG_MANDIR)/man1/rusti.1
-	$(Q)rm -f $(CFG_MANDIR)/man1/rustpkg.1
+
+define UNINSTALL_TOOL
+uninstall-tool-$(1): $$(foreach dep,$$(TOOL_DEPS_$(1)),uninstall-lib-$$(dep))
+	$$(Q)rm -f $$(PHB)/$(1)$$(X_$$(CFG_BUILD))
+	$$(Q)rm -f $$(CFG_MANDIR)/man1/$(1).1
+endef
+
+$(foreach tool,$(INSTALL_TOOLS),$(eval $(call UNINSTALL_TOOL,$(tool))))
+
+define UNINSTALL_LIB
+uninstall-lib-$(1): $$(foreach dep,$$(RUST_DEPS_$(1)),uninstall-lib-$$(dep))
+	$$(Q)rm -f $$(call HOST_LIB_FROM_HL_GLOB,$$(call CFG_LIB_GLOB_$$(CFG_BUILD),$(1)))
+endef
+
+$(foreach lib,$(CRATES),$(eval $(call UNINSTALL_LIB,$(lib))))
 
 # target platform specific variables
 # for arm-linux-androidabi
diff --git a/mk/rt.mk b/mk/rt.mk
index 38cc233b933..269491649bb 100644
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -1,35 +1,128 @@
-# This is a procedure to define the targets for building
-# the runtime.
+# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
 #
-# Argument 1 is the target triple.
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+################################################################################
+# Native libraries built as part of the rust build process
 #
-# This is not really the right place to explain this, but
-# for those of you who are not Makefile gurus, let me briefly
-# cover the $ expansion system in use here, because it
-# confused me for a while!  The variable DEF_RUNTIME_TARGETS
-# will be defined once and then expanded with different
-# values substituted for $(1) each time it is called.
-# That resulting text is then eval'd.
+# This portion of the rust build system is meant to keep track of native
+# dependencies and how to build them. It is currently required that all native
+# dependencies are built as static libraries, as slinging around dynamic
+# libraries isn't exactly the most fun thing to do.
 #
-# For most variables, you could use a single $ sign.  The result
-# is that the substitution would occur when the CALL occurs,
-# I believe.  The problem is that the automatic variables $< and $@
-# need to be expanded-per-rule.  Therefore, for those variables at
-# least, you need $$< and $$@ in the variable text.  This way, after
-# the CALL substitution occurs, you will have $< and $@.  This text
-# will then be evaluated, and all will work as you like.
+# This section should need minimal modification to add new libraries. The
+# relevant variables are:
 #
-# Reader beware, this explanantion could be wrong, but it seems to
-# fit the experimental data (i.e., I was able to get the system
-# working under these assumptions).
+#   NATIVE_LIBS
+#	This is a list of all native libraries which are built as part of the
+#	build process. It will build all libraries into RT_OUTPUT_DIR with the
+#	appropriate name of static library as dictated by the target platform
+#
+#   NATIVE_DEPS_<lib>
+#	This is a list of files relative to the src/rt directory which are
+#	needed to build the native library. Each file will be compiled to an
+#	object file, and then all the object files will be assembled into an
+#	archive (static library). The list contains files of any extension
+#
+# If adding a new library, you should update the NATIVE_LIBS list, and then list
+# the required files below it. The list of required files is a list of files
+# that's per-target so you're allowed to conditionally add files based on the
+# target.
+################################################################################
+NATIVE_LIBS := rustrt sundown uv_support morestack miniz
+
+# $(1) is the target triple
+define NATIVE_LIBRARIES
+
+NATIVE_DEPS_sundown_$(1) := sundown/src/autolink.c \
+			sundown/src/buffer.c \
+			sundown/src/stack.c \
+			sundown/src/markdown.c \
+			sundown/html/houdini_href_e.c \
+			sundown/html/houdini_html_e.c \
+			sundown/html/html_smartypants.c \
+			sundown/html/html.c
+NATIVE_DEPS_uv_support_$(1) := rust_uv.c
+NATIVE_DEPS_miniz_$(1) = miniz.c
+NATIVE_DEPS_rustrt_$(1) := rust_builtin.c \
+			rust_android_dummy.c \
+			rust_test_helpers.c \
+			rust_try.ll \
+			arch/$$(HOST_$(1))/_context.S \
+			arch/$$(HOST_$(1))/record_sp.S
+NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S
+
+################################################################################
+# You shouldn't find it that necessary to edit anything below this line.
+################################################################################
+
+# While we're defining the native libraries for each target, we define some
+# common rules used to build files for various targets.
 
-# when we're doing a snapshot build, we intentionally degrade as many
-# features in libuv and the runtime as possible, to ease portability.
+RT_OUTPUT_DIR_$(1) := $(1)/rt
+
+$$(RT_OUTPUT_DIR_$(1))/%.o: rt/%.ll $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD))
+	@mkdir -p $$(@D)
+	@$$(call E, compile: $$@)
+	$$(Q)$$(LLC_$$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) \
+	    -filetype=obj -mtriple=$(1) -relocation-model=pic -o $$@ $$<
+
+$$(RT_OUTPUT_DIR_$(1))/%.o: rt/%.c $$(MKFILE_DEPS)
+	@mkdir -p $$(@D)
+	@$$(call E, compile: $$@)
+	$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
+		-I $$(S)src/rt/sundown/src -I $$(S)src/rt/sundown/html \
+		-I $$(S)src/libuv/include -I $$(S)src/rt \
+                 $$(RUNTIME_CFLAGS_$(1))) $$<
+
+$$(RT_OUTPUT_DIR_$(1))/%.o: rt/%.S $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD))
+	@mkdir -p $$(@D)
+	@$$(call E, compile: $$@)
+	$$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<)
+endef
+
+$(foreach target,$(CFG_TARGET),$(eval $(call NATIVE_LIBRARIES,$(target))))
+
+# A macro for devining how to build third party libraries listed above (based
+# on their dependencies).
+#
+# $(1) is the target
+# $(2) is the lib name
+define THIRD_PARTY_LIB
+
+OBJS_$(2)_$(1) := $$(NATIVE_DEPS_$(2)_$(1):%=$$(RT_OUTPUT_DIR_$(1))/%)
+OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.c=.o)
+OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.cpp=.o)
+OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.ll=.o)
+OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.S=.o)
+NATIVE_$(2)_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$(2))
+$$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
+	@$$(call E, link: $$@)
+	$$(Q)$$(AR_$(1)) rcs $$@ $$^
+
+endef
+
+$(foreach target,$(CFG_TARGET),					    \
+ $(eval $(call RUNTIME_RULES,$(target))))
+$(foreach lib,$(NATIVE_LIBS),					    \
+ $(foreach target,$(CFG_TARGET),				    \
+  $(eval $(call THIRD_PARTY_LIB,$(target),$(lib)))))
 
-SNAP_DEFINES:=
-ifneq ($(strip $(findstring snap,$(MAKECMDGOALS))),)
-	SNAP_DEFINES=-DRUST_SNAPSHOT
-endif
+
+################################################################################
+# Building third-party targets with external build systems
+#
+# The only current member of this section is libuv, but long ago this used to
+# also be occupied by jemalloc. This location is meant for dependencies which
+# have external build systems. It is still assumed that the output of each of
+# these steps is a static library in the correct location.
+################################################################################
 
 define DEF_LIBUV_ARCH_VAR
   LIBUV_ARCH_$(1) = $$(subst i386,ia32,$$(subst x86_64,x64,$$(HOST_$(1))))
@@ -51,128 +144,10 @@ LIBUV_NO_LOAD = run-benchmarks.target.mk run-tests.target.mk \
 
 export PYTHONPATH := $(PYTHONPATH):$(S)src/gyp/pylib
 
-define DEF_RUNTIME_TARGETS
-
-######################################################################
-# Runtime (C++) library variables
-######################################################################
-
-# $(1) is the target triple
-# $(2) is the stage number
-
-RUNTIME_CFLAGS_$(1)_$(2) = -D_RUST_STAGE$(2)
-RUNTIME_CXXFLAGS_$(1)_$(2) = -D_RUST_STAGE$(2)
-
-# XXX: Like with --cfg stage0, pass the defines for stage1 to the stage0
-# build of non-build-triple host compilers
-ifeq ($(2),0)
-ifneq ($(strip $(CFG_BUILD)),$(strip $(1)))
-RUNTIME_CFLAGS_$(1)_$(2) = -D_RUST_STAGE1
-RUNTIME_CXXFLAGS_$(1)_$(2) = -D_RUST_STAGE1
-endif
-endif
-
-RUNTIME_CS_$(1)_$(2) := \
-              rt/rust_builtin.c \
-              rt/miniz.c \
-              rt/rust_android_dummy.c \
-              rt/rust_test_helpers.c
-
-RUNTIME_LL_$(1)_$(2) := \
-			rt/rust_try.ll
-
-# stage0 remove this after the next snapshot
-%.cpp:
-	@touch tmp/foo.o
-
-RUNTIME_S_$(1)_$(2) := rt/arch/$$(HOST_$(1))/_context.S \
-			rt/arch/$$(HOST_$(1))/record_sp.S
-
-RT_BUILD_DIR_$(1)_$(2) := $$(RT_OUTPUT_DIR_$(1))/stage$(2)
-
-RUNTIME_DEF_$(1)_$(2) := $$(RT_OUTPUT_DIR_$(1))/rustrt$$(CFG_DEF_SUFFIX_$(1))
-RUNTIME_INCS_$(1)_$(2) := -I $$(S)src/rt -I $$(S)src/rt/isaac -I $$(S)src/rt/uthash \
-                     -I $$(S)src/rt/arch/$$(HOST_$(1))
-RUNTIME_OBJS_$(1)_$(2) := \
-                     $$(RUNTIME_CS_$(1)_$(2):rt/%.c=$$(RT_BUILD_DIR_$(1)_$(2))/%.o) \
-                     $$(RUNTIME_S_$(1)_$(2):rt/%.S=$$(RT_BUILD_DIR_$(1)_$(2))/%.o) \
-                     $$(RUNTIME_LL_$(1)_$(2):rt/%.ll=$$(RT_BUILD_DIR_$(1)_$(2))/%.o)
-
-ALL_OBJ_FILES += $$(RUNTIME_OBJS_$(1)_$(2))
-
-MORESTACK_OBJS_$(1)_$(2) := $$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/morestack.o
-ALL_OBJ_FILES += $$(MORESTACK_OBJS_$(1)_$(2))
-
-$$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.c $$(MKFILE_DEPS)
-	@$$(call E, compile: $$@)
-	$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, $$(RUNTIME_INCS_$(1)_$(2)) \
-                 $$(SNAP_DEFINES) $$(RUNTIME_CFLAGS_$(1)_$(2))) $$<
-
-$$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.S  $$(MKFILE_DEPS) \
-                     $$(LLVM_CONFIG_$$(CFG_BUILD))
-	@$$(call E, compile: $$@)
-	$$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<)
-
-$$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.ll  $$(MKFILE_DEPS) \
-                     $$(LLVM_CONFIG_$$(CFG_BUILD))
-	@$$(call E, compile: $$@)
-	$$(Q)$(LLC_$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) -filetype=obj -mtriple=$(1) -relocation-model=pic -o $$@ $$<
-
-$$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/libmorestack.a: $$(MORESTACK_OBJS_$(1)_$(2))
-	@$$(call E, link: $$@)
-	$$(Q)$(AR_$(1)) rcs $$@ $$^
-
-$$(RT_BUILD_DIR_$(1)_$(2))/$(CFG_RUNTIME_$(1)): $$(RUNTIME_OBJS_$(1)_$(2)) $$(MKFILE_DEPS)
-	@$$(call E, link: $$@)
-	$$(Q)$(AR_$(1)) rcs $$@ $$(RUNTIME_OBJS_$(1)_$(2))
-
-# These could go in rt.mk or rustllvm.mk, they're needed for both.
-
-# This regexp has a single $$ escaped twice
-$(1)/%.bsd.def:    %.def.in $$(MKFILE_DEPS)
-	@$$(call E, def: $$@)
-	$$(Q)echo "{" > $$@
-	$$(Q)sed 's/.$$$$/&;/' $$< >> $$@
-	$$(Q)echo "};" >> $$@
-
-$(1)/%.linux.def:    %.def.in $$(MKFILE_DEPS)
-	@$$(call E, def: $$@)
-	$$(Q)echo "{" > $$@
-	$$(Q)sed 's/.$$$$/&;/' $$< >> $$@
-	$$(Q)echo "};" >> $$@
-
-$(1)/%.darwin.def:	%.def.in $$(MKFILE_DEPS)
-	@$$(call E, def: $$@)
-	$$(Q)sed 's/^./_&/' $$< > $$@
-
-$(1)/%.android.def:  %.def.in $$(MKFILE_DEPS)
-	@$$(call E, def: $$@)
-	$$(Q)echo "{" > $$@
-	$$(Q)sed 's/.$$$$/&;/' $$< >> $$@
-	$$(Q)echo "};" >> $$@
-
-$(1)/%.mingw32.def:	%.def.in $$(MKFILE_DEPS)
-	@$$(call E, def: $$@)
-	$$(Q)echo LIBRARY $$* > $$@
-	$$(Q)echo EXPORTS >> $$@
-	$$(Q)sed 's/^./    &/' $$< >> $$@
-
-endef
-
-
-######################################################################
-# Runtime third party targets (libuv, jemalloc, etc.)
-#
-# These targets do not need to be built once per stage, so these
-# rules just build them once and then we're done with them.
-######################################################################
-
 define DEF_THIRD_PARTY_TARGETS
 
 # $(1) is the target triple
 
-RT_OUTPUT_DIR_$(1) := $(1)/rt
-
 ifeq ($$(CFG_WINDOWSY_$(1)), 1)
   LIBUV_OSTYPE_$(1) := win
 else ifeq ($(OSTYPE_$(1)), apple-darwin)
@@ -188,7 +163,7 @@ endif
 
 LIBUV_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),uv)
 LIBUV_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libuv
-LIBUV_LIB_$(1) := $$(LIBUV_DIR_$(1))/$$(LIBUV_NAME_$(1))
+LIBUV_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(LIBUV_NAME_$(1))
 
 LIBUV_MAKEFILE_$(1) := $$(CFG_BUILD_DIR)$$(RT_OUTPUT_DIR_$(1))/libuv/Makefile
 
@@ -224,7 +199,7 @@ $$(LIBUV_LIB_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS)
 	$$(Q)cp $$(S)src/libuv/libuv.a $$@
 else
 $$(LIBUV_LIB_$(1)): $$(LIBUV_DIR_$(1))/Release/libuv.a $$(MKFILE_DEPS)
-	$$(Q)ln -f $$< $$@
+	$$(Q)cp $$< $$@
 $$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \
 				    $$(MKFILE_DEPS)
 	$$(Q)$$(MAKE) -C $$(LIBUV_DIR_$(1)) \
@@ -237,60 +212,11 @@ $$(LIBUV_DIR_$(1))/Release/libuv.a: $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) \
 		BUILDTYPE=Release \
 		NO_LOAD="$$(LIBUV_NO_LOAD)" \
 		V=$$(VERBOSE)
-endif
-
-# libuv support functionality (extra C/C++ that we need to use libuv)
 
-UV_SUPPORT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),uv_support)
-UV_SUPPORT_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/uv_support
-UV_SUPPORT_LIB_$(1) := $$(UV_SUPPORT_DIR_$(1))/$$(UV_SUPPORT_NAME_$(1))
-UV_SUPPORT_CS_$(1) := rt/rust_uv.c
-UV_SUPPORT_OBJS_$(1) := $$(UV_SUPPORT_CS_$(1):rt/%.c=$$(UV_SUPPORT_DIR_$(1))/%.o)
-
-$$(UV_SUPPORT_DIR_$(1))/%.o: rt/%.c
-	@$$(call E, compile: $$@)
-	@mkdir -p $$(@D)
-	$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
-		-I $$(S)src/libuv/include \
-                 $$(RUNTIME_CFLAGS_$(1))) $$<
-
-$$(UV_SUPPORT_LIB_$(1)): $$(UV_SUPPORT_OBJS_$(1))
-	@$$(call E, link: $$@)
-	$$(Q)$$(AR_$(1)) rcs $$@ $$^
-
-# sundown markdown library (used by librustdoc)
-
-SUNDOWN_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),sundown)
-SUNDOWN_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/sundown
-SUNDOWN_LIB_$(1) := $$(SUNDOWN_DIR_$(1))/$$(SUNDOWN_NAME_$(1))
-
-SUNDOWN_CS_$(1) := rt/sundown/src/autolink.c \
-			rt/sundown/src/buffer.c \
-			rt/sundown/src/stack.c \
-			rt/sundown/src/markdown.c \
-			rt/sundown/html/houdini_href_e.c \
-			rt/sundown/html/houdini_html_e.c \
-			rt/sundown/html/html_smartypants.c \
-			rt/sundown/html/html.c
-
-SUNDOWN_OBJS_$(1) := $$(SUNDOWN_CS_$(1):rt/%.c=$$(SUNDOWN_DIR_$(1))/%.o)
-
-$$(SUNDOWN_DIR_$(1))/%.o: rt/%.c
-	@$$(call E, compile: $$@)
-	@mkdir -p $$(@D)
-	$$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \
-		-I $$(S)src/rt/sundown/src -I $$(S)src/rt/sundown/html \
-                 $$(RUNTIME_CFLAGS_$(1))) $$<
-
-$$(SUNDOWN_LIB_$(1)): $$(SUNDOWN_OBJS_$(1))
-	@$$(call E, link: $$@)
-	$$(Q)$$(AR_$(1)) rcs $$@ $$^
+endif
 
 endef
 
 # Instantiate template for all stages/targets
 $(foreach target,$(CFG_TARGET), \
      $(eval $(call DEF_THIRD_PARTY_TARGETS,$(target))))
-$(foreach stage,$(STAGES), \
-    $(foreach target,$(CFG_TARGET), \
-	 $(eval $(call DEF_RUNTIME_TARGETS,$(target),$(stage)))))
diff --git a/mk/rustllvm.mk b/mk/rustllvm.mk
index 89b31400d5c..8d7abc020cc 100644
--- a/mk/rustllvm.mk
+++ b/mk/rustllvm.mk
@@ -32,7 +32,8 @@ RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
 RUSTLLVM_OBJS_OBJS_$(1) := $$(RUSTLLVM_OBJS_CS_$(1):rustllvm/%.cpp=$(1)/rustllvm/%.o)
 ALL_OBJ_FILES += $$(RUSTLLVM_OBJS_OBJS_$(1))
 
-$(1)/rustllvm/$(CFG_RUSTLLVM_$(1)): $$(RUSTLLVM_OBJS_OBJS_$(1))
+$$(RT_OUTPUT_DIR_$(1))/$$(call CFG_STATIC_LIB_NAME_$(1),rustllvm): \
+	    $$(RUSTLLVM_OBJS_OBJS_$(1))
 	@$$(call E, link: $$@)
 	$$(Q)$$(AR_$(1)) rcs $$@ $$(RUSTLLVM_OBJS_OBJS_$(1))
 
diff --git a/mk/target.mk b/mk/target.mk
index 5fdc3a34bcb..c4bd082b3a2 100644
--- a/mk/target.mk
+++ b/mk/target.mk
@@ -21,13 +21,104 @@ WFLAGS_ST0 = -W warnings
 WFLAGS_ST1 = -D warnings
 WFLAGS_ST2 = -D warnings
 
-# TARGET_STAGE_N template: This defines how target artifacts are built
-# for all stage/target architecture combinations. The arguments:
+# Macro that generates the full list of dependencies for a crate at a particular
+# stage/target/host tuple.
+#
+# $(1) - stage
+# $(2) - target
+# $(3) - host
+# $(4) crate
+define RUST_CRATE_FULLDEPS
+CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) :=			    \
+		$$(CRATEFILE_$(4))				    \
+		$$(RSINPUTS_$(4))				    \
+		$$(foreach dep,$$(RUST_DEPS_$(4)),		    \
+		  $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep))	    \
+		$$(foreach dep,$$(NATIVE_DEPS_$(4)),		    \
+		  $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep)))
+endef
+
+$(foreach host,$(CFG_HOST),						    \
+ $(foreach target,$(CFG_TARGET),					    \
+  $(foreach stage,$(STAGES),						    \
+   $(foreach crate,$(CRATES),						    \
+    $(eval $(call RUST_CRATE_FULLDEPS,$(stage),$(target),$(host),$(crate)))))))
+
+# RUST_TARGET_STAGE_N template: This defines how target artifacts are built
+# for all stage/target architecture combinations. This is one giant rule which
+# works as follows:
+#
+#   1. The immediate dependencies are the rust source files
+#   2. Each rust crate dependency is listed (based on their stamp files),
+#      as well as all native dependencies (listed in RT_OUTPUT_DIR)
+#   3. The stage (n-1) compiler is required through the TSREQ dependency, along
+#      with the morestack library
+#   4. When actually executing the rule, the first thing we do is to clean out
+#      old libs and rlibs via the REMOVE_ALL_OLD_GLOB_MATCHES macro
+#   5. Finally, we get around to building the actual crate. It's just one
+#      "small" invocation of the previous stage rustc. We use -L to
+#      RT_OUTPUT_DIR so all the native dependencies are picked up.
+#      Additionally, we pass in the llvm dir so rustc can link against it.
+#   6. Some cleanup is done (listing what was just built) if verbose is turned
+#      on.
+#
 # $(1) is the stage
 # $(2) is the target triple
 # $(3) is the host triple
+# $(4) is the crate name
+define RUST_TARGET_STAGE_N
+
+$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): CFG_COMPILER = $(2)
+$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4):				    \
+		$$(CRATEFILE_$(4))				    \
+		$$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4))	    \
+		$$(TSREQ$(1)_T_$(2)_H_$(3))			    \
+		| $$(TLIB$(1)_T_$(2)_H_$(3))/
+	@$$(call E, compile_and_link: $$(@D)/lib$(4))
+	$$(call REMOVE_ALL_OLD_GLOB_MATCHES,\
+	    $$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4)))
+	$$(call REMOVE_ALL_OLD_GLOB_MATCHES,\
+	    $$(dir $$@)$$(call CFG_RLIB_GLOB,$(4)))
+	$$(STAGE$(1)_T_$(2)_H_$(3)) \
+		$$(WFLAGS_ST$(1)) \
+		-L "$$(RT_OUTPUT_DIR_$(2))" \
+		-L "$$(LLVM_LIBDIR_$(2))" \
+		--out-dir $$(@D) $$<
+	@touch $$@
+	$$(call LIST_ALL_OLD_GLOB_MATCHES,\
+	    $$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4)))
+	$$(call LIST_ALL_OLD_GLOB_MATCHES,\
+	    $$(dir $$@)$$(call CFG_RLIB_GLOB,$(4)))
+
+endef
+
+# Macro for building any tool as part of the rust compilation process. Each
+# tool is defined in crates.mk with a list of library dependencies as well as
+# the source file for the tool. Building each tool will also be passed '--cfg
+# <tool>' for usage in driver.rs
+#
+# This build rule is similar to the one found above, just tweaked for
+# locations and things.
+#
+# $(1) - stage
+# $(2) - target triple
+# $(3) - host triple
+# $(4) - name of the tool being built
+define TARGET_TOOL
+
+$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)):			\
+		$$(TOOL_SOURCE_$(4))				\
+		$$(TOOL_INPUTS_$(4))				\
+		$$(foreach dep,$$(TOOL_DEPS_$(4)),		\
+		    $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep))	\
+		$$(TSREQ$(1)_T_$(2)_H_$(3))			\
+		| $$(TBIN$(1)_T_$(4)_H_$(3))/
+	@$$(call E, compile_and_link: $$@)
+	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --cfg $(4)
+
+endef
 
-# Every recipe in TARGET_STAGE_N outputs to $$(TLIB$(1)_T_$(2)_H_$(3),
+# Every recipe in RUST_TARGET_STAGE_N outputs to $$(TLIB$(1)_T_$(2)_H_$(3),
 # a directory that can be cleaned out during the middle of a run of
 # the get-snapshot.py script.  Therefore, every recipe needs to have
 # an order-only dependency either on $(SNAPSHOT_RUSTC_POST_CLEANUP) or
@@ -35,147 +126,11 @@ WFLAGS_ST2 = -D warnings
 # put into the target area until after the get-snapshot.py script has
 # had its chance to clean it out; otherwise the other products will be
 # inadvertantly included in the clean out.
-
 SNAPSHOT_RUSTC_POST_CLEANUP=$(HBIN0_H_$(CFG_BUILD))/rustc$(X_$(CFG_BUILD))
 
-define TARGET_STAGE_N
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \
-		$(2)/rt/stage$(1)/arch/$$(HOST_$(2))/libmorestack.a \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/ \
-		  $(SNAPSHOT_RUSTC_POST_CLEANUP)
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
+define TARGET_HOST_RULES
 
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUNTIME_$(2)): \
-		$(2)/rt/stage$(1)/$(CFG_RUNTIME_$(2)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/ \
-		  $(SNAPSHOT_RUSTC_POST_CLEANUP)
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)): \
-		$$(STDLIB_CRATE) $$(STDLIB_INPUTS) \
-		$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-		--out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(STDLIB_RGLOB_$(2)),$$(notdir $$@))
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_EXTRALIB_$(2)): \
-		$$(EXTRALIB_CRATE) $$(EXTRALIB_INPUTS) \
-	        $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
-		$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-		--out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(EXTRALIB_RGLOB_$(2)),$$(notdir $$@))
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTUV_$(2)): \
-		$$(LIBRUSTUV_CRATE) $$(LIBRUSTUV_INPUTS) \
-	        $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
-		$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-		$$(LIBUV_LIB_$(2)) \
-		$$(UV_SUPPORT_LIB_$(2)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-		-L $$(UV_SUPPORT_DIR_$(2)) \
-		-L $$(dir $$(LIBUV_LIB_$(2))) \
-		--out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTUV_RGLOB_$(2)),$$(notdir $$@))
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBGREEN_$(2)): \
-		$$(LIBGREEN_CRATE) $$(LIBGREEN_INPUTS) \
-	        $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
-		$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-		--out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBGREEN_RGLOB_$(2)),$$(notdir $$@))
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBNATIVE_$(2)): \
-		$$(LIBNATIVE_CRATE) $$(LIBNATIVE_INPUTS) \
-	        $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_STDLIB_$(2)) \
-		$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-		--out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBNATIVE_RGLOB_$(2)),$$(notdir $$@))
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)): \
-                $$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS) \
-		$$(TSREQ$(1)_T_$(2)_H_$(3))			\
-		$$(TSTDLIB_DEFAULT$(1)_T_$(2)_H_$(3))      \
-		$$(TEXTRALIB_DEFAULT$(1)_T_$(2)_H_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) $(BORROWCK) \
-	    --out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBSYNTAX_RGLOB_$(2)),$$(notdir $$@))
-
-# Only build the compiler for host triples
-ifneq ($$(findstring $(2),$$(CFG_HOST)),)
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(3)): \
-		$(2)/rustllvm/$(CFG_RUSTLLVM_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/ \
-		  $(SNAPSHOT_RUSTC_POST_CLEANUP)
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)): CFG_COMPILER = $(2)
-$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)):		\
-		$$(COMPILER_CRATE) $$(COMPILER_INPUTS)		\
-		$(S)src/librustc/lib/llvmdeps.rs		\
-		$$(TSREQ$(1)_T_$(2)_H_$(3)) \
-                $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBSYNTAX_$(3)) \
-                $$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_RUSTLLVM_$(3)) \
-		| $$(TLIB$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(2)),$$(notdir $$@))
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_RGLOB_$(2)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(2)_H_$(3)) $$(WFLAGS_ST$(1)) \
-	    -L "$$(LLVM_LIBDIR_$(2))" \
-	    --out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_GLOB_$(2)),$$(notdir $$@))
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTC_RGLOB_$(2)),$$(notdir $$@))
-
-$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(3)):			\
-		$$(DRIVER_CRATE)				\
-		$$(SREQ$(1)_T_$(2)_H_$(3)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$(CFG_LIBRUSTC_$(3)) \
-		| $$(TBIN$(1)_T_$(2)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) --cfg rustc -o $$@ $$<
-ifdef CFG_ENABLE_PAX_FLAGS
-	@$$(call E, apply PaX flags: $$@)
-	@"$(CFG_PAXCTL)" -cm "$$@"
-endif
-
-endif
+$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc: $(S)src/librustc/lib/llvmdeps.rs
 
 $$(TBIN$(1)_T_$(2)_H_$(3))/:
 	mkdir -p $$@
@@ -183,12 +138,31 @@ $$(TBIN$(1)_T_$(2)_H_$(3))/:
 $$(TLIB$(1)_T_$(2)_H_$(3))/:
 	mkdir -p $$@
 
+$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \
+	    $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),morestack) \
+	    | $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
+	@$$(call E, cp: $$@)
+	$$(Q)cp $$< $$@
 endef
 
-# In principle, each host can build each target:
-$(foreach source,$(CFG_HOST),				\
- $(foreach target,$(CFG_TARGET),			\
-  $(eval $(call TARGET_STAGE_N,0,$(target),$(source)))		\
-  $(eval $(call TARGET_STAGE_N,1,$(target),$(source)))		\
-  $(eval $(call TARGET_STAGE_N,2,$(target),$(source)))		\
-  $(eval $(call TARGET_STAGE_N,3,$(target),$(source)))))
+$(foreach source,$(CFG_HOST),						    \
+ $(foreach target,$(CFG_TARGET),					    \
+  $(eval $(call TARGET_HOST_RULES,0,$(target),$(source)))		    \
+  $(eval $(call TARGET_HOST_RULES,1,$(target),$(source)))		    \
+  $(eval $(call TARGET_HOST_RULES,2,$(target),$(source)))		    \
+  $(eval $(call TARGET_HOST_RULES,3,$(target),$(source)))))
+
+# In principle, each host can build each target for both libs and tools
+$(foreach crate,$(CRATES),						    \
+ $(foreach source,$(CFG_HOST),						    \
+  $(foreach target,$(CFG_TARGET),					    \
+   $(eval $(call RUST_TARGET_STAGE_N,0,$(target),$(source),$(crate)))	    \
+   $(eval $(call RUST_TARGET_STAGE_N,1,$(target),$(source),$(crate)))	    \
+   $(eval $(call RUST_TARGET_STAGE_N,2,$(target),$(source),$(crate)))	    \
+   $(eval $(call RUST_TARGET_STAGE_N,3,$(target),$(source),$(crate))))))
+
+$(foreach host,$(CFG_HOST),						    \
+ $(foreach target,$(CFG_TARGET),					    \
+  $(foreach stage,$(STAGES),						    \
+   $(foreach tool,$(TOOLS),						    \
+    $(eval $(call TARGET_TOOL,$(stage),$(target),$(host),$(tool)))))))
diff --git a/mk/tests.mk b/mk/tests.mk
index 58f9ee2e815..b8d3c126d5a 100644
--- a/mk/tests.mk
+++ b/mk/tests.mk
@@ -14,9 +14,9 @@
 ######################################################################
 
 # The names of crates that must be tested
-TEST_TARGET_CRATES = std extra rustuv green native
-TEST_DOC_CRATES = std extra
-TEST_HOST_CRATES = rustpkg rustc rustdoc syntax
+TEST_TARGET_CRATES = $(TARGET_CRATES)
+TEST_DOC_CRATES = $(DOC_CRATES)
+TEST_HOST_CRATES = $(HOST_CRATES)
 TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
 
 # Markdown files under doc/ that should have their code extracted and run
@@ -341,89 +341,31 @@ define TEST_RUNNER
 # If NO_REBUILD is set then break the dependencies on extra so we can
 # test crates without rebuilding std and extra first
 ifeq ($(NO_REBUILD),)
-STDTESTDEP_$(1)_$(2)_$(3) = $$(SREQ$(1)_T_$(2)_H_$(3)) \
-                            $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_EXTRALIB_$(2)) \
-                            $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTUV_$(2)) \
-                            $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBGREEN_$(2))
+STDTESTDEP_$(1)_$(2)_$(3)_$(4) = $$(SREQ$(1)_T_$(2)_H_$(3)) \
+                            $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.extra \
+                            $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustuv \
+                            $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.green
 else
-STDTESTDEP_$(1)_$(2)_$(3) =
+STDTESTDEP_$(1)_$(2)_$(3)_$(4) =
 endif
 
-$(3)/stage$(1)/test/stdtest-$(2)$$(X_$(2)):			\
-		$$(STDLIB_CRATE) $$(STDLIB_INPUTS)		\
-		$$(STDTESTDEP_$(1)_$(2)_$(3))
+$(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)): CFG_COMPILER = $(2)
+$(3)/stage$(1)/test/$(4)test-$(2)$$(X_$(2)):				\
+		$$(CRATEFILE_$(4))					\
+		$$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4))		\
+		$$(STDTESTDEP_$(1)_$(2)_$(3)_$(4))
 	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
-
-$(3)/stage$(1)/test/extratest-$(2)$$(X_$(2)):			\
-		$$(EXTRALIB_CRATE) $$(EXTRALIB_INPUTS)		\
-		$$(STDTESTDEP_$(1)_$(2)_$(3))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
-
-$(3)/stage$(1)/test/rustuvtest-$(2)$$(X_$(2)):			\
-		$$(LIBRUSTUV_CRATE) $$(LIBRUSTUV_INPUTS)	\
-		$$(STDTESTDEP_$(1)_$(2)_$(3))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test \
-		-L $$(UV_SUPPORT_DIR_$(2)) \
-		-L $$(dir $$(LIBUV_LIB_$(2)))
-
-$(3)/stage$(1)/test/nativetest-$(2)$$(X_$(2)):			\
-		$$(LIBNATIVE_CRATE) $$(LIBNATIVE_INPUTS)	\
-		$$(STDTESTDEP_$(1)_$(2)_$(3))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
-
-$(3)/stage$(1)/test/greentest-$(2)$$(X_$(2)):			\
-		$$(LIBGREEN_CRATE) $$(LIBGREEN_INPUTS)	\
-		$$(STDTESTDEP_$(1)_$(2)_$(3))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
-
-$(3)/stage$(1)/test/syntaxtest-$(2)$$(X_$(2)):			\
-		$$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS)	\
-		$$(STDTESTDEP_$(1)_$(2)_$(3))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
-
-$(3)/stage$(1)/test/rustctest-$(2)$$(X_$(2)): CFG_COMPILER = $(2)
-$(3)/stage$(1)/test/rustctest-$(2)$$(X_$(2)):					\
-		$$(COMPILER_CRATE) $$(COMPILER_INPUTS) \
-		$$(SREQ$(1)_T_$(2)_H_$(3)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUSTLLVM_$(2)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test \
-	    -L "$$(LLVM_LIBDIR_$(2))"
-
-$(3)/stage$(1)/test/rustpkgtest-$(2)$$(X_$(2)):					\
-		$$(RUSTPKG_LIB) $$(RUSTPKG_INPUTS)		\
-		$$(SREQ$(1)_T_$(2)_H_$(3)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
-		$$(HBIN$(1)_H_$(3))/rustpkg$$(X_$(2)) \
-		$$(TBIN$(1)_T_$(2)_H_$(3))/rustpkg$$(X_$(2)) \
-		$$(TBIN$(1)_T_$(2)_H_$(3))/rustc$$(X_$(2))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
-
-$(3)/stage$(1)/test/rustdoctest-$(2)$$(X_$(2)):					\
-		$$(RUSTDOC_LIB) $$(RUSTDOC_INPUTS)		\
-		$$(SREQ$(1)_T_$(2)_H_$(3)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBSYNTAX_$(2)) \
-		$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_LIBRUSTC_$(2)) \
-		$$(SUNDOWN_LIB_$(2))
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test \
-		-L $$(SUNDOWN_DIR_$(2))
+	$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test	\
+		-L "$$(RT_OUTPUT_DIR_$(2))"		\
+		-L "$$(LLVM_LIBDIR_$(2))"
 
 endef
 
 $(foreach host,$(CFG_HOST), \
  $(eval $(foreach target,$(CFG_TARGET), \
   $(eval $(foreach stage,$(STAGES), \
-   $(eval $(call TEST_RUNNER,$(stage),$(target),$(host))))))))
+   $(eval $(foreach crate,$(TEST_CRATES), \
+    $(eval $(call TEST_RUNNER,$(stage),$(target),$(host),$(crate))))))))))
 
 define DEF_TEST_CRATE_RULES
 check-stage$(1)-T-$(2)-H-$(3)-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),$(4))
@@ -629,7 +571,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) :=						\
         --host $(3)                                       \
         --adb-path=$(CFG_ADB)                          \
         --adb-test-dir=$(CFG_ADB_TEST_DIR)                  \
-        --rustcflags "$(RUSTC_FLAGS_$(2)) $$(CTEST_RUSTC_FLAGS)" \
+        --rustcflags "$(RUSTC_FLAGS_$(2)) $$(CTEST_RUSTC_FLAGS) -L $$(RT_OUTPUT_DIR_$(2))" \
         $$(CTEST_TESTARGS)
 
 CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS)
@@ -758,20 +700,18 @@ $(foreach host,$(CFG_HOST), \
    $(foreach docname,$(DOC_TEST_NAMES), \
     $(eval $(call DEF_RUN_DOC_TEST,$(stage),$(target),$(host),$(docname)))))))
 
-CRATE_DOC_LIB-std = $(STDLIB_CRATE)
-CRATE_DOC_LIB-extra = $(EXTRALIB_CRATE)
-
 define DEF_CRATE_DOC_TEST
 
 check-stage$(1)-T-$(2)-H-$(3)-doc-$(4)-exec: $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4))
 
 ifeq ($(2),$$(CFG_BUILD))
-$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)):		\
-	        $$(TEST_SREQ$(1)_T_$(2)_H_$(3))		\
+$$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)):				\
+	        $$(TEST_SREQ$(1)_T_$(2)_H_$(3))				\
+		$$(CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4))		\
 		$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3))
 	@$$(call E, run doc-$(4) [$(2)])
 	$$(Q)$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) --test \
-	    $$(CRATE_DOC_LIB-$(4)) --test-args "$$(TESTARGS)" && touch $$@
+	    $$(CRATEFILE_$(4)) --test-args "$$(TESTARGS)" && touch $$@
 else
 $$(call TEST_OK_FILE,$(1),$(2),$(3),doc-$(4)):
 	touch $$@
@@ -915,14 +855,16 @@ $$(TLIB2_T_$(2)_H_$(3))/$$(FT_LIB): \
 		tmp/$$(FT).rc \
 		$$(SREQ2_T_$(2)_H_$(3))
 	@$$(call E, compile_and_link: $$@)
-	$$(STAGE2_T_$(2)_H_$(3)) --lib -o $$@ $$<
+	$$(STAGE2_T_$(2)_H_$(3)) --lib -o $$@ $$< \
+	  -L "$$(RT_OUTPUT_DIR_$(2))"
 
 $(3)/test/$$(FT_DRIVER)-$(2)$$(X_$(2)): \
 		tmp/$$(FT_DRIVER).rs \
 		$$(TLIB2_T_$(2)_H_$(3))/$$(FT_LIB) \
 		$$(SREQ2_T_$(2)_H_$(3))
 	@$$(call E, compile_and_link: $$@ $$<)
-	$$(STAGE2_T_$(2)_H_$(3)) -o $$@ $$<
+	$$(STAGE2_T_$(2)_H_$(3)) -o $$@ $$< \
+	  -L "$$(RT_OUTPUT_DIR_$(2))"
 
 $(3)/test/$$(FT_DRIVER)-$(2).out: \
 		$(3)/test/$$(FT_DRIVER)-$(2)$$(X_$(2)) \
diff --git a/mk/tools.mk b/mk/tools.mk
deleted file mode 100644
index 5ae33cb7fab..00000000000
--- a/mk/tools.mk
+++ /dev/null
@@ -1,142 +0,0 @@
-# Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-# file at the top-level directory of this distribution and at
-# http://rust-lang.org/COPYRIGHT.
-#
-# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-# option. This file may not be copied, modified, or distributed
-# except according to those terms.
-
-# Rules for non-core tools built with the compiler, both for target
-# and host architectures
-
-# The test runner that runs the cfail/rfail/rpass and bxench tests
-COMPILETEST_CRATE := $(S)src/compiletest/compiletest.rs
-COMPILETEST_INPUTS := $(wildcard $(S)src/compiletest/*.rs)
-
-# Rustpkg, the package manager and build system
-RUSTPKG_LIB := $(S)src/librustpkg/lib.rs
-RUSTPKG_INPUTS := $(wildcard $(S)src/librustpkg/*.rs)
-
-# Rustdoc, the documentation tool
-RUSTDOC_LIB := $(S)src/librustdoc/lib.rs
-RUSTDOC_INPUTS := $(wildcard $(addprefix $(S)src/librustdoc/,        \
-                                           *.rs */*.rs */*/*.rs))
-
-# FIXME: These are only built for the host arch. Eventually we'll
-# have tools that need to built for other targets.
-define TOOLS_STAGE_N_TARGET
-
-$$(TBIN$(1)_T_$(4)_H_$(3))/compiletest$$(X_$(4)):			\
-		$$(COMPILETEST_CRATE) $$(COMPILETEST_INPUTS)	\
-		$$(SREQ$(1)_T_$(4)_H_$(3))			\
-		| $$(TBIN$(1)_T_$(4)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(4)_H_$(3)) -o $$@ $$<
-
-$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4)):		\
-		$$(RUSTPKG_LIB) $$(RUSTPKG_INPUTS)		    \
-		$$(SREQ$(1)_T_$(4)_H_$(3))			\
-		$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \
-		| $$(TLIB$(1)_T_$(4)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTPKG_GLOB_$(4)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) --out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTPKG_GLOB_$(4)),$$(notdir $$@))
-
-$$(TBIN$(1)_T_$(4)_H_$(3))/rustpkg$$(X_$(4)):				\
-		$$(DRIVER_CRATE) 							\
-		$$(TSREQ$(1)_T_$(4)_H_$(3))				\
-		$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4))	\
-		| $$(TBIN$(1)_T_$(4)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustpkg -o $$@ $$<
-
-$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4)):		\
-		$$(RUSTDOC_LIB) $$(RUSTDOC_INPUTS)			\
-		$$(SREQ$(1)_T_$(4)_H_$(3))			\
-		$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTC_$(4)) \
-		$$(SUNDOWN_LIB_$(4)) \
-		| $$(TLIB$(1)_T_$(4)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
-	$$(STAGE$(1)_T_$(4)_H_$(3)) $$(WFLAGS_ST$(1)) \
-		-L $$(SUNDOWN_DIR_$(4)) --out-dir $$(@D) $$< && touch $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
-
-$$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4)):			\
-		$$(DRIVER_CRATE) 							\
-		$$(TSREQ$(1)_T_$(4)_H_$(3))						\
-		$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4))			\
-		| $$(TBIN$(1)_T_$(4)_H_$(3))/
-	@$$(call E, compile_and_link: $$@)
-	$$(STAGE$(1)_T_$(4)_H_$(3)) --cfg rustdoc -o $$@ $$<
-
-endef
-
-define TOOLS_STAGE_N_HOST
-
-$$(HBIN$(2)_H_$(4))/compiletest$$(X_$(4)):				\
-		$$(TBIN$(1)_T_$(4)_H_$(3))/compiletest$$(X_$(4))	\
-		$$(HSREQ$(2)_H_$(4))					\
-		| $$(HBIN$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
-
-
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTPKG_$(4)):				\
-		$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTPKG_$(4))	\
-		$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4))		\
-		$$(HSREQ$(2)_H_$(4))					\
-		| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTPKG_GLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTPKG_GLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTPKG_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTPKG_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-
-$$(HBIN$(2)_H_$(4))/rustpkg$$(X_$(4)):				\
-		$$(TBIN$(1)_T_$(4)_H_$(3))/rustpkg$$(X_$(4))	\
-		$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTPKG_$(4))	\
-		$$(HSREQ$(2)_H_$(4))				\
-		| $$(HBIN$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
-
-$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTDOC_$(4)):					\
-		$$(TLIB$(1)_T_$(4)_H_$(3))/$(CFG_LIBRUSTDOC_$(4))	\
-		$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTC_$(4))			\
-		$$(HSREQ$(2)_H_$(4)) \
-		| $$(HLIB$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(call REMOVE_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp $$< $$@
-	$$(call LIST_ALL_OLD_GLOB_MATCHES_EXCEPT,$$(dir $$@),$(LIBRUSTDOC_GLOB_$(4)),$$(notdir $$@))
-	$$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTDOC_GLOB_$(4)) \
-		$$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(LIBRUSTDOC_DSYM_GLOB_$(4))) \
-	        $$(HLIB$(2)_H_$(4))
-
-$$(HBIN$(2)_H_$(4))/rustdoc$$(X_$(4)):				\
-		$$(TBIN$(1)_T_$(4)_H_$(3))/rustdoc$$(X_$(4))	\
-		$$(HLIB$(2)_H_$(4))/$(CFG_LIBRUSTDOC_$(4))	\
-		$$(HSREQ$(2)_H_$(4))				\
-		| $$(HBIN$(2)_H_$(4))/
-	@$$(call E, cp: $$@)
-	$$(Q)cp $$< $$@
-
-endef
-
-$(foreach host,$(CFG_HOST),				\
-$(foreach target,$(CFG_TARGET),				\
- $(eval $(call TOOLS_STAGE_N_TARGET,0,1,$(host),$(target)))	\
- $(eval $(call TOOLS_STAGE_N_TARGET,1,2,$(host),$(target)))	\
- $(eval $(call TOOLS_STAGE_N_TARGET,2,3,$(host),$(target)))	\
- $(eval $(call TOOLS_STAGE_N_TARGET,3,bogus,$(host),$(target)))))
-
-$(foreach host,$(CFG_HOST),				\
- $(eval $(call TOOLS_STAGE_N_HOST,0,1,$(host),$(host)))	\
- $(eval $(call TOOLS_STAGE_N_HOST,1,2,$(host),$(host)))	\
- $(eval $(call TOOLS_STAGE_N_HOST,2,3,$(host),$(host))))
diff --git a/src/libextra/lib.rs b/src/libextra/lib.rs
index fc0cc045175..5a4fedd2b2a 100644
--- a/src/libextra/lib.rs
+++ b/src/libextra/lib.rs
@@ -82,7 +82,6 @@ pub mod rational;
 pub mod complex;
 pub mod stats;
 pub mod semver;
-pub mod flate;
 pub mod hex;
 pub mod uuid;
 
diff --git a/src/libextra/flate.rs b/src/libflate/lib.rs
index faceb17af47..f746fe4ec32 100644
--- a/src/libextra/flate.rs
+++ b/src/libflate/lib.rs
@@ -14,6 +14,10 @@ Simple compression
 
 */
 
+#[crate_id = "flate#0.10-pre"];
+#[crate_type = "rlib"];
+#[crate_type = "dylib"];
+#[license = "MIT/ASL2"];
 #[allow(missing_doc)];
 
 use std::libc::{c_void, size_t, c_int};
@@ -23,7 +27,7 @@ use std::vec;
 pub mod rustrt {
     use std::libc::{c_int, c_void, size_t};
 
-    #[link(name = "rustrt", kind = "static")]
+    #[link(name = "miniz", kind = "static")]
     extern {
         pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void,
                                           src_buf_len: size_t,
@@ -91,7 +95,7 @@ pub fn inflate_bytes_zlib(bytes: &[u8]) -> ~[u8] {
 
 #[cfg(test)]
 mod tests {
-    use super::*;
+    use super::{inflate_bytes, deflate_bytes};
     use std::rand;
     use std::rand::Rng;
 
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 8aed5623166..86e82dec9e6 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -30,6 +30,7 @@ This API is completely unstable and subject to change.
 #[feature(macro_rules, globs, struct_variant, managed_boxes)];
 
 extern mod extra;
+extern mod flate;
 extern mod syntax;
 
 use back::link;
diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs
index b10b833f286..046184bef58 100644
--- a/src/librustc/metadata/loader.rs
+++ b/src/librustc/metadata/loader.rs
@@ -33,7 +33,7 @@ use std::os::consts::{macos, freebsd, linux, android, win32};
 use std::ptr;
 use std::str;
 use std::vec;
-use extra::flate;
+use flate;
 
 pub enum Os {
     OsMacos,
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index 5b246daa6c5..9744c395b7c 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -2683,7 +2683,7 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_
 }
 
 pub fn write_metadata(cx: &CrateContext, crate: &ast::Crate) -> ~[u8] {
-    use extra::flate;
+    use flate;
 
     if !cx.sess.building_library.get() {
         return ~[]
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 5d0728c8cdf..d53adb78a30 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -16,7 +16,9 @@
 //! functionality through a unit-struct, `Markdown`, which has an implementation
 //! of `fmt::Default`. Example usage:
 //!
-//! ```rust
+//! ```rust,ignore
+//! use rustdoc::html::markdown::Markdown;
+//!
 //! let s = "My *markdown* _text_";
 //! let html = format!("{}", Markdown(s));
 //! // ... something using html