build: separate per-platform build artifacts

Move build per-platform artifacts to be entirely under $CANTRIP_OUT_DIR
and make each platform's sim.mk & sim_sel4test.mk more consistent.

Specific changes:
- add EXT_BUILTINS_{DEBUG, RELEASE} for the constructed builtins bundle
  which is moved to $CANTRIP_OUT_DIR
- move the "tmp" directory used to construct bundles under $CANTRIP_OUT_DIR
- change sel4test out directories to use platform instead of target arch
- use make targets for dependencies instead of pathnames to artifacts
  (this simplifies direct building of artifacts)
- fix minisel targets
- use make shell operations to dredge platforms.camkes for cpio parameters
- cleanup/rewrite rpi3 sim.mk

Tested all {shodan,nexus,rpi3} sim targets (several had bitrot'd).

Shodan & nexus sim_sel4test.mk are now identical; leaving a copy for now.

Bug: 293296515

Change-Id: I29b431555f0a142b753afa2d8bde4a46447f7a41
diff --git a/cantrip_builtins.mk b/cantrip_builtins.mk
index 718ba67..3479e3c 100644
--- a/cantrip_builtins.mk
+++ b/cantrip_builtins.mk
@@ -22,6 +22,9 @@
 CANTRIP_MODEL_DEBUG    :=
 CANTRIP_SCRIPTS        :=
 
+EXT_BUILTINS_DEBUG=$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio
+EXT_BUILTINS_RELEASE=$(CANTRIP_OUT_RELEASE)/ext_builtins.cpio
+
 # TODO(jtgans): should include from platforms/${PLATFORM}/platform.mk
 include $(ROOTDIR)/build/platforms/$(PLATFORM)/cantrip_builtins.mk
 
@@ -38,16 +41,16 @@
 	mkdir -p $@
 	cp $(CANTRIP_APPS_DEBUG) $(CANTRIP_MODEL_DEBUG) ${CANTRIP_SCRIPTS} $@
 
-$(CANTRIP_OUT_RELEASE)/ext_builtins.cpio: $(CANTRIP_OUT_RELEASE)/builtins
+$(EXT_BUILTINS_RELEASE): $(CANTRIP_OUT_RELEASE)/builtins
 	ls -1 $< | $(CPIO) -o -D $< $(BUILTINS_CPIO_OPTS) -O "$@"
 
-$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio: $(CANTRIP_OUT_DEBUG)/builtins
+$(EXT_BUILTINS_DEBUG): $(CANTRIP_OUT_DEBUG)/builtins
 	ls -1 $< | $(CPIO) -o -D $< $(BUILTINS_CPIO_OPTS) -O "$@"
 
 ## Generates cpio archive of Cantrip builtins with debugging suport
-cantrip-builtins-debug: $(CANTRIP_OUT_DEBUG)/ext_builtins.cpio
+cantrip-builtins-debug: $(EXT_BUILTINS_DEBUG)
 ## Generates cpio archive of Cantrip builtins for release
-cantrip-builtins-release: $(CANTRIP_OUT_RELEASE)/ext_builtins.cpio
+cantrip-builtins-release: $(EXT_BUILTINS_RELEASE)
 ## Generates both debug & release cpio archives of Cantrip builtins
 cantrip-builtins: cantrip-builtins-debug cantrip-builtins-release
 
diff --git a/cantrip_sel4test.mk b/cantrip_sel4test.mk
index 4327574..0d1712e 100644
--- a/cantrip_sel4test.mk
+++ b/cantrip_sel4test.mk
@@ -14,7 +14,7 @@
 
 # Location of sel4test sources and binary output files
 SEL4TEST_SRC_DIR  := $(ROOTDIR)/cantrip/projects/sel4test
-SEL4TEST_OUT_DIR := $(OUT)/sel4test/$(CANTRIP_TARGET_ARCH)
+SEL4TEST_OUT_DIR := $(OUT)/sel4test/$(PLATFORM)
 SEL4TEST_OUT_DEBUG := $(SEL4TEST_OUT_DIR)/debug
 SEL4TEST_KERNEL_DEBUG := $(SEL4TEST_OUT_DEBUG)/kernel/kernel.elf
 SEL4TEST_ROOTSERVER_DEBUG := $(SEL4TEST_OUT_DEBUG)/apps/sel4test-driver/sel4test-driver
@@ -82,7 +82,7 @@
 # sel4test build machinery whenever possible.
 
 SEL4TEST_WRAPPER_LIBRARY_DIR := $(SEL4TEST_SRC_DIR)/integrations/sel4-sys-wrapper
-SEL4TEST_WRAPPER_OUT_DIR := $(OUT)/sel4test-wrapper/$(CANTRIP_TARGET_ARCH)
+SEL4TEST_WRAPPER_OUT_DIR := $(OUT)/sel4test-wrapper/$(PLATFORM)
 SEL4TEST_WRAPPER_OUT_DEBUG := $(SEL4TEST_WRAPPER_OUT_DIR)/debug
 SEL4TEST_WRAPPER_ROOTSERVER_DEBUG := $(SEL4TEST_WRAPPER_OUT_DEBUG)/apps/sel4test-driver/sel4test-driver
 
diff --git a/platforms/nexus/platform.mk b/platforms/nexus/platform.mk
index 944a967..e935d8b 100644
--- a/platforms/nexus/platform.mk
+++ b/platforms/nexus/platform.mk
@@ -8,6 +8,9 @@
 include $(ROOTDIR)/build/platforms/nexus/renode.mk
 include $(ROOTDIR)/build/platforms/nexus/matcha_hw.mk
 include $(ROOTDIR)/build/platforms/nexus/tock.mk
+
+
+# Put simulation targets at the end
 include $(ROOTDIR)/build/platforms/nexus/sim.mk
 include $(ROOTDIR)/build/platforms/nexus/sim_sel4test.mk
 
diff --git a/platforms/nexus/sim.mk b/platforms/nexus/sim.mk
index 3f5f174..a339533 100644
--- a/platforms/nexus/sim.mk
+++ b/platforms/nexus/sim.mk
@@ -12,37 +12,49 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# NB: keep tarballs in CANTRIP_OUT_DIR to avoid shodan/nexus collisions
+EXT_FLASH_DEBUG=$(CANTRIP_OUT_DEBUG)/ext_flash.tar
+EXT_FLASH_RELEASE=$(CANTRIP_OUT_RELEASE)/ext_flash.tar
+
+TMP_DEBUG=$(CANTRIP_OUT_DEBUG)/tmp
+TMP_RELEASE=$(CANTRIP_OUT_RELEASE)/tmp
+
 sim_configs:
 	$(RENODE_SIM_GENERATOR_SCRIPT)
 
 clean_sim_configs:
 	@rm -rf $(OUT)/renode_configs
 
+$(TMP_DEBUG):
+	mkdir $(TMP_DEBUG)
+$(TMP_RELEASE):
+	mkdir $(TMP_RELEASE)
+
 # NB: $(CANTRIP_ROOTSERVER_*) is built together with $(CANTRIP_KERNEL_*)
 
-# NB: debug builds are too big to run on Nexus so an ext_flash_debug target is pointless
-$(OUT)/ext_flash_debug.tar: $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_ROOTSERVER_DEBUG) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(CANTRIP_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_ROOTSERVER_DEBUG) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_debug.tar matcha-tock-bundle.bin kernel capdl-loader
+$(EXT_FLASH_DEBUG): $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_ROOTSERVER_DEBUG) | $(TMP_DEBUG)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_DEBUG)/matcha-tock-bundle $(TMP_DEBUG)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_DEBUG) $(TMP_DEBUG)/kernel
+	ln -sf $(CANTRIP_ROOTSERVER_DEBUG) $(TMP_DEBUG)/capdl-loader
+	tar -C $(TMP_DEBUG) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_debug: $(EXT_FLASH_DEBUG)
 
-$(OUT)/ext_flash_release.tar: $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_ROOTSERVER_RELEASE) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_RELEASE) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(CANTRIP_KERNEL_RELEASE) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_ROOTSERVER_RELEASE) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_release.tar matcha-tock-bundle.bin kernel capdl-loader
+$(EXT_FLASH_RELEASE): $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_ROOTSERVER_RELEASE) | $(TMP_RELEASE)
+	cp -f $(MATCHA_BUNDLE_RELEASE) $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_RELEASE)/matcha-tock-bundle $(TMP_RELEASE)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_RELEASE) $(TMP_RELEASE)/kernel
+	ln -sf $(CANTRIP_ROOTSERVER_RELEASE) $(TMP_RELEASE)/capdl-loader
+	tar -C $(TMP_RELEASE) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
 
-# NB: Package the builtins bundle so it can be written to a carveout in
+# NB: Package the builtins bundle so it can be written to a carve out in
 #     in SMC memory; this is temporary until the SEC supports returning
 #     the builtins from flash.
-ext_flash_release: ${OUT}/ext_flash_release.tar $(CANTRIP_OUT_RELEASE)/ext_builtins.cpio
-	ln -sf $(CANTRIP_OUT_RELEASE)/ext_builtins.cpio $(OUT)/tmp/cantrip-builtins
-	tar -C $(OUT)/tmp -rvhf $(OUT)/ext_flash_release.tar cantrip-builtins
+ext_flash_release: $(EXT_FLASH_RELEASE) $(EXT_BUILTINS_RELEASE) | $(TMP_RELEASE)
+	ln -sf $(EXT_BUILTINS_RELEASE) $(TMP_RELEASE)/cantrip-builtins
+	tar -C $(TMP_RELEASE) -rvhf $(EXT_FLASH_RELEASE) cantrip-builtins
 
 # Dredge the platform configuration for the physical address where the
 # cpio archive is expected.
@@ -59,32 +71,37 @@
 ## Launches an end-to-end build of the Shodan system and starts Renode
 #
 # This top-level target triggers the `matcha_tock_release`, `cantrip`, `renode`,
-# and `iree` targets to build the entire system and then finally starts the
-# Renode simulator.
+# `multihart_boot_rom`, and `iree` targets to build the entire system and then
+# finally starts the Renode simulator.
 #
 # This is the default target for the build system, and is generally what you
 # need for day-to-day work on the software side of Shodan.
-simulate: renode multihart_boot_rom $(OUT)/ext_flash_release.tar iree_model_builtins $(CANTRIP_OUT_RELEASE)/ext_builtins.cpio
+simulate: renode multihart_boot_rom ext_flash_release iree_model_builtins cantrip-builtins-release
 	$(RENODE_CMD) -e "\
     \$$repl_file = @sim/config/platforms/nexus.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_release.tar; \
-    \$$cpio = @$(CANTRIP_OUT_RELEASE)/ext_builtins.cpio; \
+    \$$tar = @$(EXT_FLASH_RELEASE); \
+    \$$cpio = @$(EXT_BUILTINS_RELEASE); \
     \$$cpio_load_address = ${CPIO_LOAD_ADDRESS}; \
-    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) start"
+    \$$kernel = @$(CANTRIP_KERNEL_RELEASE); \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
 ## Debug version of the `simulate` target
 #
 # This top-level target does the same job as `simulate`, but instead of
 # unhalting the CPUs and starting the system, this alternate target only unhalts
 # cpu0, and uses the debug build of TockOS from the `matcha_tock_debug` target.
-simulate-debug: renode multihart_boot_rom $(OUT)/ext_flash_debug.tar iree_model_builtins $(CANTRIP_OUT_DEBUG)/ext_builtins.cpio
+#
+# NB: requires editing of platform.camkes for alternate cpio_load_address
+simulate-debug: renode multihart_boot_rom ext_flash_debug iree_model_builtins cantrip-builtins-debug
 	$(RENODE_CMD) -e "\
     \$$repl_file = @sim/config/platforms/nexus-debug.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_debug.tar; \
-    \$$cpio = @$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio; \
+    \$$tar = @$(EXT_FLASH_DEBUG); \
+    \$$cpio = @$(EXT_BUILTINS_DEBUG); \
     \$$cpio_load_address = ${CPIO_LOAD_ADDRESS}; \
-    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) cpu1 CreateSeL4 0xffffffee; start"
+    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) cpu1 CreateSeL4 0xffffffee; start"
 
 ## Debug version of the `simulate` target
 #
@@ -92,49 +109,60 @@
 # unhalting the CPUs and starting the system, this alternate target starts
 # renode with no CPUs unhalted, allowing for GDB to be used for early system
 # start.
-debug-simulation: renode multihart_boot_rom $(OUT)/ext_flash_debug.tar iree_model_builtins $(CANTRIP_OUT_DEBUG)/ext_builtins.cpio
+#
+# NB: requires editing of platform.camkes for alternate cpio_load_address
+debug-simulation: renode multihart_boot_rom ext_flash_debug iree_model_builtins cantrip-builtins-debug
 	$(RENODE_CMD) -e "\
     \$$repl_file = @sim/config/platforms/nexus-debug.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_debug.tar; \
-    \$$cpio = @$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio; \
+    \$$tar = @$(EXT_FLASH_DEBUG); \
+    \$$cpio = @$(EXT_BUILTINS_DEBUG); \
     \$$cpio_load_address = ${CPIO_LOAD_ADDRESS}; \
-    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; start"
+    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; start"
+
+EXT_FLASH_MINISEL_DEBUG=$(CANTRIP_OUT_DEBUG)/ext_flash_minisel.tar
+EXT_FLASH_MINISEL_RELEASE=$(CANTRIP_OUT_RELEASE)/ext_flash_minisel.tar
 
 # Launches Shodan with Minisel as the rootserver for low-level testing purposes.
-# FIXME(@aappleby) - The Minisel bundle renames "minisel.elf" to "capdl-loader"
+# NB: the minisel bundle renames "minisel.elf" to "capdl-loader"
 # because we don't currently have any way to specify the rootserver app other
 # than via filename
-$(OUT)/ext_flash_minisel_debug.tar: $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf | $(OUT)/tmp
-	ln -sf $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	ln -sf $(CANTRIP_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_minisel_debug.tar matcha-tock-bundle kernel capdl-loader
+# TODO(sleffler): the rootserver is built as a byproduct of building the kernel
+$(EXT_FLASH_MINISEL_DEBUG): $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf | $(TMP_DEBUG)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_DEBUG)/matcha-tock-bundle $(TMP_DEBUG)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_DEBUG) $(TMP_DEBUG)/kernel
+	ln -sf $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf $(TMP_DEBUG)/capdl-loader
+	tar -C $(TMP_DEBUG) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_minisel_debug: $(EXT_FLASH_MINISEL_DEBUG)
 
-$(OUT)/ext_flash_minisel_release.tar: $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf | $(OUT)/tmp
-	ln -sf $(MATCHA_BUNDLE_RELEASE) $(OUT)/tmp/matcha-tock-bundle
-	ln -sf $(CANTRIP_KERNEL_RELEASE) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_minisel_release.tar matcha-tock-bundle kernel capdl-loader
+# TODO(sleffler): the rootserver is built as a byproduct of building the kernel
+$(EXT_FLASH_MINISEL_RELEASE): $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf | $(TMP_RELEASE)
+	cp -f $(MATCHA_BUNDLE_RELEASE) $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_RELEASE)/matcha-tock-bundle $(TMP_RELEASE)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_RELEASE) $(TMP_RELEASE)/kernel
+	ln -sf $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf $(TMP_RELEASE)/capdl-loader
+	tar -C $(TMP_RELEASE) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_minisel_release: $(EXT_FLASH_MINISEL_RELEASE)
 
-simulate_minisel: renode $(OUT)/ext_flash_minisel_debug.tar
+simulate_minisel: renode multihart_boot_rom ext_flash_minisel_debug
+	$(RENODE_CMD) -e "\
+    \$$repl_file = @sim/config/platforms/nexus-debug.repl; \
+    \$$tar = @$(EXT_FLASH_MINISEL_DEBUG); \
+    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
+    \$$cpio = @/dev/null; \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
+
+simulate_minisel_release: renode multihart_boot_rom ext_flash_minisel_release
 	$(RENODE_CMD) -e "\
     \$$repl_file = @sim/config/platforms/nexus.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_minisel_debug.tar; \
-    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
-    $(PORT_PRESTART_CMDS) \
-    i @sim/config/shodan.resc; \
-    $(RENODE_PRESTART_CMDS) \
-    start"
-
-simulate_minisel_release: renode $(OUT)/ext_flash_minisel_release.tar
-	$(RENODE_CMD) -e "\
-    \$$repl_file = @sim/config/platforms/nexus.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_minisel_release.tar; \
-    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
-    $(PORT_PRESTART_CMDS) \
-    i @sim/config/shodan.resc; \
-    $(RENODE_PRESTART_CMDS) \
-    start"
+    \$$tar = @$(EXT_FLASH_MINISEL_RELEASE); \
+    \$$kernel = @$(CANTRIP_KERNEL_RELEASE); \
+    \$$cpio = @/dev/null; \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
 .PHONY:: sim_configs clean_sim_configs simulate simulate-debug debug-simulation
diff --git a/platforms/nexus/sim_sel4test.mk b/platforms/nexus/sim_sel4test.mk
index 3cb350f..93a9701 100644
--- a/platforms/nexus/sim_sel4test.mk
+++ b/platforms/nexus/sim_sel4test.mk
@@ -14,51 +14,62 @@
 
 # sel4test simulation support; this is meant to be included from sim.mk
 
+SEL4TEST_TMP=$(SEL4TEST_OUT_DEBUG)/tmp
+${SEL4TEST_TMP}:
+	mkdir $@
+
+SEL4TEST_EXT_FLASH_TAR=$(SEL4TEST_OUT_DEBUG)/ext_flash.tar
+
 # NB: release builds do not have enough memory to run sel4test; they
 #   will fail to build when elfloader looks for a location to load the image
 
-$(SEL4TEST_OUT_DEBUG)/ext_flash.tar: $(MATCHA_BUNDLE_DEBUG) \
-		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_ROOTSERVER_DEBUG) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(SEL4TEST_ROOTSERVER_DEBUG) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+$(SEL4TEST_EXT_FLASH_TAR): $(MATCHA_BUNDLE_DEBUG) \
+		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_ROOTSERVER_DEBUG) | $(SEL4TEST_TMP)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(SEL4TEST_TMP)/matcha-tock-bundle
+	${C_PREFIX}strip $(SEL4TEST_TMP)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(SEL4TEST_TMP)/matcha-tock-bundle ${SEL4TEST_TMP}/matcha-tock-bundle.bin
+	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_TMP)/kernel
+	ln -sf $(SEL4TEST_ROOTSERVER_DEBUG) $(SEL4TEST_TMP)/capdl-loader
+	tar -C $(SEL4TEST_TMP) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
 
 ## Launches the sel4test target with minimal modifications.
-sel4test: renode multihart_boot_rom $(SEL4TEST_OUT_DEBUG)/ext_flash.tar
+sel4test: renode multihart_boot_rom $(SEL4TEST_EXT_FLASH_TAR)
 	$(RENODE_CMD) -e "\
-    \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
-    \$$tar = @$(SEL4TEST_OUT_DEBUG)/ext_flash.tar; \
+    \$$repl_file = @sim/config/platforms/$(PLATFORM)-debug.repl; \
+    \$$tar = @$(SEL4TEST_EXT_FLASH_TAR); \
     \$$kernel = @$(SEL4TEST_KERNEL_DEBUG); \
     \$$cpio = @/dev/null; \
-    $(PORT_PRESTART_CMDS) \
-	  i @sim/config/nexus.resc; $(RENODE_PRESTART_CMDS) start"
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
 # NB: for compatability
 sel4test-debug: sel4test
 
-$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar: $(MATCHA_BUNDLE_DEBUG) \
-		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+SEL4TEST_WRAPPER_TMP=$(SEL4TEST_WRAPPER_OUT_DEBUG)/tmp
+${SEL4TEST_WRAPPER_TMP}:
+	mkdir $@
+
+SEL4TEST_WRAPPER_EXT_FLASH_TAR=$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar
+
+$(SEL4TEST_WRAPPER_EXT_FLASH_TAR): $(MATCHA_BUNDLE_DEBUG) \
+		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) | $(SEL4TEST_WRAPPER_TMP)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(SEL4TEST_WRAPPER_TMP)/matcha-tock-bundle
+	${C_PREFIX}strip $(SEL4TEST_WRAPPER_TMP)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(SEL4TEST_WRAPPER_TMP)/matcha-tock-bundle ${SEL4TEST_WRAPPER_TMP}/matcha-tock-bundle.bin
+	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_WRAPPER_TMP)/kernel
+	ln -sf $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) $(SEL4TEST_WRAPPER_TMP)/capdl-loader
+	tar -C $(SEL4TEST_WRAPPER_TMP) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
 
 ## Launches a version of the sel4test target that uses the sel4-sys Rust
 ## crate wrapped with C shims. The result is run under Renode.
-sel4test+wrapper: renode multihart_boot_rom \
-		$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar
+sel4test+wrapper: renode multihart_boot_rom $(SEL4TEST_WRAPPER_EXT_FLASH_TAR)
 	$(RENODE_CMD) -e "\
-    \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
-    \$$tar = @$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar; \
+    \$$repl_file = @sim/config/platforms/$(PLATFORM)-debug.repl; \
+    \$$tar = @$(SEL4TEST_WRAPPER_EXT_FLASH_TAR); \
     \$$kernel = @$(SEL4TEST_KERNEL_DEBUG); \
     \$$cpio = @/dev/null; \
-    $(PORT_PRESTART_CMDS) \
-	  i @sim/config/nexus.resc; $(RENODE_PRESTART_CMDS) start"
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+				$(RENODE_PRESTART_CMDS) start"
 
 .PHONY:: sel4test
 .PHONY:: sel4test-debug
diff --git a/platforms/rpi3/sim.mk b/platforms/rpi3/sim.mk
index daf74cc..89b6ebe 100644
--- a/platforms/rpi3/sim.mk
+++ b/platforms/rpi3/sim.mk
@@ -12,8 +12,24 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-sim_configs::
-clean_sim_configs::
+# Location of pre-loaded memory image for qemu
+QEMU_MEM_DEBUG=$(CANTRIP_OUT_DEBUG)/cantrip.mem
+QEMU_MEM_RELEASE=$(CANTRIP_OUT_RELEASE)/cantrip.mem
+
+# Location of capdl-loader setup for qemu
+QEMU_CAPDL_LOADER_DEBUG=$(CANTRIP_OUT_DEBUG)/capdl-loader-image
+QEMU_CAPDL_LOADER_RELEASE=$(CANTRIP_OUT_RELEASE)/capdl-loader-image
+
+# Dredge the platform configuration for the cpio archive splat into
+# the $QEMU_MEM_* memory image.
+# NB: #define must be at the start of the line so any commented out
+#    copies are skipped
+CPIO_SIZE=$(shell awk '\
+				/^#define[ \t]+CPIO_SIZE_BYTES/ { print strtonum($$3) / (1024*1024) "M" } \
+    ' $(CANTRIP_SRC_DIR)/apps/system/platforms/bcm2837/platform.camkes)
+CPIO_SEEK=$(shell awk '\
+				/^#define[ \t]+CPIO_BASE_ADDR/ { print strtonum($$3) / (1024*1024) } \
+		' $(CANTRIP_SRC_DIR)/apps/system/platforms/bcm2837/platform.camkes)
 
 # qemu fixes the memory size according to the machine type. If you use
 # other than the default you also need to adjust CPIO_BASE_ADDR in the
@@ -36,67 +52,57 @@
 qemu_presence_check:
 	@${QEMU} --version >/dev/null
 
+sim_configs::
+clean_sim_configs::
+
 ## Launches an end-to-end build of the Sparrow system and starts qemu
 #
-# This top-level target triggers building the entire system and then starting
+# This top-level target triggers building the entire system and then starts
 # the qemu simulator with the build artifacts.
 #
 # This is the default target for the build system, and is generally what you
 # need for day-to-day work on the software side of Sparrow.
-simulate: ${CANTRIP_OUT_RELEASE}/capdl-loader-image ${CANTRIP_OUT_RELEASE}/cantrip.mem | qemu_presence_check
-	$(QEMU_CMD) \
-	-kernel ${CANTRIP_OUT_RELEASE}/capdl-loader-image \
-	--mem-path ${CANTRIP_OUT_RELEASE}/cantrip.mem
+simulate: qemu-capdl-loader-release qemu-mem-release | qemu_presence_check
+	$(QEMU_CMD) -kernel ${QEMU_CAPDL_LOADER_RELEASE} --mem-path ${QEMU_MEM_RELEASE}
 
-$(CANTRIP_OUT_RELEASE)/capdl-loader-image: $(CANTRIP_KERNEL_RELEASE) \
+$(QEMU_CAPDL_LOADER_RELEASE): $(CANTRIP_KERNEL_RELEASE) \
 		$(CANTRIP_ROOTSERVER_RELEASE) ${CANTRIP_OUT_RELEASE}/elfloader/elfloader
 	${C_PREFIX}objcopy -O binary ${CANTRIP_OUT_RELEASE}/elfloader/elfloader $@
+qemu-capdl-loader-release: ${QEMU_CAPDL_LOADER_RELEASE}
 
-# XXX no dep on system.camkes
-$(CANTRIP_OUT_RELEASE)/cantrip.mem:  $(CANTRIP_OUT_RELEASE)/ext_builtins.cpio \
+$(QEMU_MEM_RELEASE): cantrip-builtins-release \
 		${CANTRIP_OUT_RELEASE}/kernel/gen_config/kernel/gen_config.h \
     $(ROOTDIR)/build/platforms/rpi3/sim.mk \
     ${CANTRIP_SRC_DIR}/apps/system/platforms/bcm2837/system.camkes
 	dd if=/dev/zero of=$@ bs=${MEMORY_SIZE} count=1
-	SEL4_PLATFORM=$$(awk '\
-		/\<CONFIG_PLAT\>/ { print $$3 } \
-	' ${CANTRIP_OUT_RELEASE}/kernel/gen_config/kernel/gen_config.h) && \
-	DD_ARGS=$$(awk ' \
-        /^#define[ ]+CPIO_SIZE_BYTES/ { print "ibs=" strtonum($$3) / (1024*1024) "M" } \
-        /^#define[ ]+CPIO_BASE_ADDR/ { print "obs=1M seek=" strtonum($$3) / (1024*1024) } \
-	' $(CANTRIP_SRC_DIR)/apps/system/platforms/$${SEL4_PLATFORM}/platform.camkes) && \
-	dd if=$(CANTRIP_OUT_RELEASE)/ext_builtins.cpio of=$@ $${DD_ARGS} conv=sync,nocreat,notrunc
+	dd if=$(EXT_BUILTINS_RELEASE) of=$@ \
+			ibs=${CPIO_SIZE} obs=1M seek=${CPIO_SEEK} conv=sync,nocreat,notrunc
+qemu-mem-release: $(QEMU_MEM_RELEASE)
 
 ## Debug version of the `simulate` target
-simulate-debug: ${CANTRIP_OUT_DEBUG}/cantrip.mem ${CANTRIP_OUT_DEBUG}/capdl-loader-image | qemu_presence_check
-	$(QEMU_CMD) -s \
-	-kernel ${CANTRIP_OUT_DEBUG}/capdl-loader-image \
-	--mem-path ${CANTRIP_OUT_DEBUG}/cantrip.mem
+simulate-debug: qemu-capdl-loader-debug qemu-mem-debug | qemu_presence_check
+	$(QEMU_CMD) -s -kernel ${QEMU_CAPDL_LOADER_DEBUG} --mem-path ${QEMU_MEM_DEBUG}
 
-$(CANTRIP_OUT_DEBUG)/capdl-loader-image: $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_ROOTSERVER_DEBUG) ${CANTRIP_OUT_DEBUG}/elfloader/elfloader
+$(QEMU_CAPDL_LOADER_DEBUG): $(CANTRIP_KERNEL_DEBUG) \
+		$(CANTRIP_ROOTSERVER_DEBUG) ${CANTRIP_OUT_DEBUG}/elfloader/elfloader
 	${C_PREFIX}objcopy -O binary ${CANTRIP_OUT_DEBUG}/elfloader/elfloader $@
+qemu-capdl-loader-debug: ${QEMU_CAPDL_LOADER_RELEASE}
 
-# XXX no dep on system.camkes
-$(CANTRIP_OUT_DEBUG)/cantrip.mem:  $(CANTRIP_OUT_DEBUG)/ext_builtins.cpio ${CANTRIP_OUT_DEBUG}/kernel/gen_config/kernel/gen_config.h
+$(QEMU_MEM_DEBUG): cantrip-builtins-debug \
+    ${CANTRIP_OUT_DEBUG}/kernel/gen_config/kernel/gen_config.h \
+    $(ROOTDIR)/build/platforms/rpi3/sim.mk \
+    ${CANTRIP_SRC_DIR}/apps/system/platforms/bcm2837/system.camkes
 	dd if=/dev/zero of=$@ bs=${MEMORY_SIZE} count=1
-	SEL4_PLATFORM=$$(awk '\
-		/\<CONFIG_PLAT\>/ { print $$3 } \
-	' ${CANTRIP_OUT_DEBUG}/kernel/gen_config/kernel/gen_config.h) && \
-	DD_ARGS=$$(awk ' \
-        /cpio.cpio_size = / { print "ibs=" strtonum($$3) / (1024*1024) "M" } \
-        /cpio.cpio_paddr = / { print "obs=1M seek=" strtonum($$3) / (1024*1024) } \
-	' $(CANTRIP_SRC_DIR)/apps/system/platforms/$${SEL4_PLATFORM}/system.camkes) && \
-	dd if=$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio of=$@ $${DD_ARGS} conv=sync,nocreat,notrunc
+	dd if=$(EXT_BUILTINS_DEBUG) of=$@ \
+			ibs=${CPIO_SIZE} obs=1M seek=${CPIO_SEEK} conv=sync,nocreat,notrunc
+qemu-mem-debug: $(QEMU_MEM_DEBUG)
 
 ## Debug version of the `simulate` target
 #
 # This top-level target does the same job as `simulate-debug`, but instead of
-# unhalting the CPUs and starting the system, this alternate target starts
-# renode with no CPUs unhalted, allowing for GDB to be used for early system
-# start.
-debug-simulation: ${CANTRIP_OUT_DEBUG}/cantrip.mem ${CANTRIP_OUT_DEBUG}/capdl-loader-image | qemu_presence_check
-	$(QEMU_CMD) -s -S \
-	-kernel ${CANTRIP_OUT_DEBUG}/capdl-loader-image \
-	--mem-path ${CANTRIP_OUT_DEBUG}/cantrip.mem
+# unhalting the CPU and starting the system, this alternate target
+# allows for GDB to be used for early system debugging.
+debug-simulation: qemu-capdl-loader-debug qemu-mem-debug | qemu_presence_check
+	$(QEMU_CMD) -s -S -kernel ${QEMU_CAPDL_LOADER_DEBUG} --mem-path ${QEMU_MEM_DEBUG}
 
 .PHONY:: sim_configs clean_sim_configs simulate simulate-debug debug-simulation
diff --git a/platforms/shodan/sim.mk b/platforms/shodan/sim.mk
index 6711172..3e8abd5 100644
--- a/platforms/shodan/sim.mk
+++ b/platforms/shodan/sim.mk
@@ -12,29 +12,43 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# NB: keep tarballs in CANTRIP_OUT_DIR to avoid shodan/nexus collisions
+EXT_FLASH_DEBUG=$(CANTRIP_OUT_DEBUG)/ext_flash.tar
+EXT_FLASH_RELEASE=$(CANTRIP_OUT_RELEASE)/ext_flash.tar
+
+TMP_DEBUG=$(CANTRIP_OUT_DEBUG)/tmp
+TMP_RELEASE=$(CANTRIP_OUT_RELEASE)/tmp
+
 sim_configs:
 	$(RENODE_SIM_GENERATOR_SCRIPT)
 
 clean_sim_configs:
 	@rm -rf $(OUT)/renode_configs
 
+$(TMP_DEBUG):
+	mkdir $(TMP_DEBUG)
+$(TMP_RELEASE):
+	mkdir $(TMP_RELEASE)
+
 # NB: $(CANTRIP_ROOTSERVER_*) is built together with $(CANTRIP_KERNEL_*)
 
-$(OUT)/ext_flash_debug.tar: $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_ROOTSERVER_DEBUG) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(CANTRIP_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_ROOTSERVER_DEBUG) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_debug.tar matcha-tock-bundle.bin kernel capdl-loader
+$(EXT_FLASH_DEBUG): $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_ROOTSERVER_DEBUG) | $(TMP_DEBUG)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_DEBUG)/matcha-tock-bundle $(TMP_DEBUG)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_DEBUG) $(TMP_DEBUG)/kernel
+	ln -sf $(CANTRIP_ROOTSERVER_DEBUG) $(TMP_DEBUG)/capdl-loader
+	tar -C $(TMP_DEBUG) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_debug: $(EXT_FLASH_DEBUG)
 
-$(OUT)/ext_flash_release.tar: $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_ROOTSERVER_RELEASE) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_RELEASE) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(CANTRIP_KERNEL_RELEASE) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_ROOTSERVER_RELEASE) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_release.tar matcha-tock-bundle.bin kernel capdl-loader
+$(EXT_FLASH_RELEASE): $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_ROOTSERVER_RELEASE) | $(TMP_RELEASE)
+	cp -f $(MATCHA_BUNDLE_RELEASE) $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_RELEASE)/matcha-tock-bundle $(TMP_RELEASE)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_RELEASE) $(TMP_RELEASE)/kernel
+	ln -sf $(CANTRIP_ROOTSERVER_RELEASE) $(TMP_RELEASE)/capdl-loader
+	tar -C $(TMP_RELEASE) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_release: $(EXT_FLASH_RELEASE)
 
 # Dredge the platform configuration for the physical address where the
 # cpio archive is expected.
@@ -56,26 +70,28 @@
 #
 # This is the default target for the build system, and is generally what you
 # need for day-to-day work on the software side of Shodan.
-simulate: renode multihart_boot_rom $(OUT)/ext_flash_release.tar iree_model_builtins $(CANTRIP_OUT_RELEASE)/ext_builtins.cpio
+simulate: renode multihart_boot_rom ext_flash_release iree_model_builtins cantrip-builtins-release
 	$(RENODE_CMD) -e "\
-    \$$tar = @$(ROOTDIR)/out/ext_flash_release.tar; \
-    \$$cpio = @$(CANTRIP_OUT_RELEASE)/ext_builtins.cpio; \
+    \$$tar = @$(EXT_FLASH_RELEASE); \
+    \$$cpio = @$(EXT_BUILTINS_RELEASE); \
     \$$cpio_load_address = ${CPIO_LOAD_ADDRESS}; \
-    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) start"
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
 ## Debug version of the `simulate` target
 #
 # This top-level target does the same job as `simulate`, but instead of
 # unhalting the CPUs and starting the system, this alternate target only unhalts
 # cpu0, and uses the debug build of TockOS from the `matcha_tock_debug` target.
-simulate-debug: renode multihart_boot_rom $(OUT)/ext_flash_debug.tar iree_model_builtins $(CANTRIP_OUT_DEBUG)/ext_builtins.cpio
+simulate-debug: renode multihart_boot_rom ext_flash_debug iree_model_builtins cantrip-builtins-debug
 	$(RENODE_CMD) -e "\
     \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_debug.tar; \
-    \$$cpio = @$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio; \
+    \$$tar = @$(EXT_FLASH_DEBUG); \
+    \$$cpio = @$(EXT_BUILTINS_DEBUG); \
     \$$cpio_load_address = ${CPIO_LOAD_ADDRESS}; \
-    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) cpu1 CreateSeL4 0xffffffee; start"
+    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) cpu1 CreateSeL4 0xffffffee; start"
 
 ## Debug version of the `simulate` target
 #
@@ -83,37 +99,57 @@
 # unhalting the CPUs and starting the system, this alternate target starts
 # renode with no CPUs unhalted, allowing for GDB to be used for early system
 # start.
-debug-simulation: renode multihart_boot_rom $(OUT)/ext_flash_debug.tar iree_model_builtins $(CANTRIP_OUT_DEBUG)/ext_builtins.cpio
+debug-simulation: renode multihart_boot_rom ext_flash_debug iree_model_builtins cantrip-builtins-debug
 	$(RENODE_CMD) -e "\
     \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
-    \$$tar = @$(ROOTDIR)/out/ext_flash_debug.tar; \
-    \$$cpio = @$(CANTRIP_OUT_DEBUG)/ext_builtins.cpio; \
+    \$$tar = @$(EXT_FLASH_DEBUG); \
+    \$$cpio = @$(EXT_BUILTINS_DEBUG); \
     \$$cpio_load_address = ${CPIO_LOAD_ADDRESS}; \
-    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; start"
+    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; start"
+
+EXT_FLASH_MINISEL_DEBUG=$(CANTRIP_OUT_DEBUG)/ext_flash_minisel.tar
+EXT_FLASH_MINISEL_RELEASE=$(CANTRIP_OUT_RELEASE)/ext_flash_minisel.tar
 
 # Launches Shodan with Minisel as the rootserver for low-level testing purposes.
-# FIXME(@aappleby) - The Minisel bundle renames "minisel.elf" to "capdl-loader"
+# NB: the minisel bundle renames "minisel.elf" to "capdl-loader"
 # because we don't currently have any way to specify the rootserver app other
 # than via filename
-$(OUT)/ext_flash_minisel_debug.tar: $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf | $(OUT)/tmp
-	ln -sf $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	ln -sf $(CANTRIP_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_minisel_debug.tar matcha-tock-bundle kernel capdl-loader
+# TODO(sleffler): the rootserver is built as a byproduct of building the kernel
+$(EXT_FLASH_MINISEL_DEBUG): $(MATCHA_BUNDLE_DEBUG) $(CANTRIP_KERNEL_DEBUG) $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf | $(TMP_DEBUG)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_DEBUG)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_DEBUG)/matcha-tock-bundle $(TMP_DEBUG)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_DEBUG) $(TMP_DEBUG)/kernel
+	ln -sf $(CANTRIP_OUT_DEBUG)/minisel/minisel.elf $(TMP_DEBUG)/capdl-loader
+	tar -C $(TMP_DEBUG) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_minisel_debug: $(EXT_FLASH_MINISEL_DEBUG)
 
-$(OUT)/ext_flash_minisel_release.tar: $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf | $(OUT)/tmp
-	ln -sf $(MATCHA_BUNDLE_RELEASE) $(OUT)/tmp/matcha-tock-bundle
-	ln -sf $(CANTRIP_KERNEL_RELEASE) $(OUT)/tmp/kernel
-	ln -sf $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $(OUT)/ext_flash_minisel_release.tar matcha-tock-bundle kernel capdl-loader
+# TODO(sleffler): the rootserver is built as a byproduct of building the kernel
+$(EXT_FLASH_MINISEL_RELEASE): $(MATCHA_BUNDLE_RELEASE) $(CANTRIP_KERNEL_RELEASE) $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf | $(TMP_RELEASE)
+	cp -f $(MATCHA_BUNDLE_RELEASE) $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}strip $(TMP_RELEASE)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(TMP_RELEASE)/matcha-tock-bundle $(TMP_RELEASE)/matcha-tock-bundle.bin
+	ln -sf $(CANTRIP_KERNEL_RELEASE) $(TMP_RELEASE)/kernel
+	ln -sf $(CANTRIP_OUT_RELEASE)/minisel/minisel.elf $(TMP_RELEASE)/capdl-loader
+	tar -C $(TMP_RELEASE) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+ext_flash_minisel_release: $(EXT_FLASH_MINISEL_RELEASE)
 
-simulate_minisel: renode multihart_boot_rom $(OUT)/ext_flash_minisel_debug.tar
-	$(RENODE_CMD) -e "\$$tar = @$(ROOTDIR)/out/ext_flash_minisel_debug.tar; \$$kernel = @$(CANTRIP_KERNEL_DEBUG); $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) start"
+simulate_minisel: renode multihart_boot_rom ext_flash_minisel_debug
+	$(RENODE_CMD) -e "\
+    \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
+    \$$tar = @$(EXT_FLASH_MINISEL_DEBUG); \
+    \$$kernel = @$(CANTRIP_KERNEL_DEBUG); \
+    \$$cpio = @/dev/null; \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
-simulate_minisel_release: renode multihart_boot_rom $(OUT)/ext_flash_minisel_release.tar
-	$(RENODE_CMD) -e "\$$tar = @$(ROOTDIR)/out/ext_flash_minisel_release.tar; $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) start"
+simulate_minisel_release: renode multihart_boot_rom ext_flash_minisel_release
+	$(RENODE_CMD) -e "\
+    \$$tar = @$(EXT_FLASH_MINISEL_RELEASE); \
+    \$$kernel = @$(CANTRIP_KERNEL_RELEASE); \
+    \$$cpio = @/dev/null; \
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
 .PHONY:: sim_configs clean_sim_configs simulate simulate-debug debug-simulation
diff --git a/platforms/shodan/sim_sel4test.mk b/platforms/shodan/sim_sel4test.mk
index 061234f..93a9701 100644
--- a/platforms/shodan/sim_sel4test.mk
+++ b/platforms/shodan/sim_sel4test.mk
@@ -14,51 +14,62 @@
 
 # sel4test simulation support; this is meant to be included from sim.mk
 
+SEL4TEST_TMP=$(SEL4TEST_OUT_DEBUG)/tmp
+${SEL4TEST_TMP}:
+	mkdir $@
+
+SEL4TEST_EXT_FLASH_TAR=$(SEL4TEST_OUT_DEBUG)/ext_flash.tar
+
 # NB: release builds do not have enough memory to run sel4test; they
 #   will fail to build when elfloader looks for a location to load the image
 
-$(SEL4TEST_OUT_DEBUG)/ext_flash.tar: $(MATCHA_BUNDLE_DEBUG) \
-		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_ROOTSERVER_DEBUG) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(SEL4TEST_ROOTSERVER_DEBUG) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+$(SEL4TEST_EXT_FLASH_TAR): $(MATCHA_BUNDLE_DEBUG) \
+		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_ROOTSERVER_DEBUG) | $(SEL4TEST_TMP)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(SEL4TEST_TMP)/matcha-tock-bundle
+	${C_PREFIX}strip $(SEL4TEST_TMP)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(SEL4TEST_TMP)/matcha-tock-bundle ${SEL4TEST_TMP}/matcha-tock-bundle.bin
+	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_TMP)/kernel
+	ln -sf $(SEL4TEST_ROOTSERVER_DEBUG) $(SEL4TEST_TMP)/capdl-loader
+	tar -C $(SEL4TEST_TMP) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
 
 ## Launches the sel4test target with minimal modifications.
-sel4test: renode multihart_boot_rom $(SEL4TEST_OUT_DEBUG)/ext_flash.tar
+sel4test: renode multihart_boot_rom $(SEL4TEST_EXT_FLASH_TAR)
 	$(RENODE_CMD) -e "\
-    \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
-    \$$tar = @$(SEL4TEST_OUT_DEBUG)/ext_flash.tar; \
+    \$$repl_file = @sim/config/platforms/$(PLATFORM)-debug.repl; \
+    \$$tar = @$(SEL4TEST_EXT_FLASH_TAR); \
     \$$kernel = @$(SEL4TEST_KERNEL_DEBUG); \
     \$$cpio = @/dev/null; \
-    $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) start"
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+        $(RENODE_PRESTART_CMDS) start"
 
 # NB: for compatability
 sel4test-debug: sel4test
 
-$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar: $(MATCHA_BUNDLE_DEBUG) \
-		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) | $(OUT)/tmp
-	cp -f $(MATCHA_BUNDLE_DEBUG) $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}strip $(OUT)/tmp/matcha-tock-bundle
-	${C_PREFIX}objcopy -O binary -g $(OUT)/tmp/matcha-tock-bundle ${OUT}/tmp/matcha-tock-bundle.bin
-	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(OUT)/tmp/kernel
-	ln -sf $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) $(OUT)/tmp/capdl-loader
-	tar -C $(OUT)/tmp -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
+SEL4TEST_WRAPPER_TMP=$(SEL4TEST_WRAPPER_OUT_DEBUG)/tmp
+${SEL4TEST_WRAPPER_TMP}:
+	mkdir $@
+
+SEL4TEST_WRAPPER_EXT_FLASH_TAR=$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar
+
+$(SEL4TEST_WRAPPER_EXT_FLASH_TAR): $(MATCHA_BUNDLE_DEBUG) \
+		$(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) | $(SEL4TEST_WRAPPER_TMP)
+	cp -f $(MATCHA_BUNDLE_DEBUG) $(SEL4TEST_WRAPPER_TMP)/matcha-tock-bundle
+	${C_PREFIX}strip $(SEL4TEST_WRAPPER_TMP)/matcha-tock-bundle
+	${C_PREFIX}objcopy -O binary -g $(SEL4TEST_WRAPPER_TMP)/matcha-tock-bundle ${SEL4TEST_WRAPPER_TMP}/matcha-tock-bundle.bin
+	ln -sf $(SEL4TEST_KERNEL_DEBUG) $(SEL4TEST_WRAPPER_TMP)/kernel
+	ln -sf $(SEL4TEST_WRAPPER_ROOTSERVER_DEBUG) $(SEL4TEST_WRAPPER_TMP)/capdl-loader
+	tar -C $(SEL4TEST_WRAPPER_TMP) -cvhf $@ matcha-tock-bundle.bin kernel capdl-loader
 
 ## Launches a version of the sel4test target that uses the sel4-sys Rust
 ## crate wrapped with C shims. The result is run under Renode.
-sel4test+wrapper: renode multihart_boot_rom \
-		$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar
+sel4test+wrapper: renode multihart_boot_rom $(SEL4TEST_WRAPPER_EXT_FLASH_TAR)
 	$(RENODE_CMD) -e "\
-    \$$repl_file = @sim/config/platforms/shodan-debug.repl; \
-    \$$tar = @$(SEL4TEST_WRAPPER_OUT_DEBUG)/ext_flash.tar; \
+    \$$repl_file = @sim/config/platforms/$(PLATFORM)-debug.repl; \
+    \$$tar = @$(SEL4TEST_WRAPPER_EXT_FLASH_TAR); \
     \$$kernel = @$(SEL4TEST_KERNEL_DEBUG); \
     \$$cpio = @/dev/null; \
-    $(PORT_PRESTART_CMDS) \
-	  i @sim/config/shodan.resc; $(RENODE_PRESTART_CMDS) start"
+    $(PORT_PRESTART_CMDS) i @sim/config/shodan.resc; \
+				$(RENODE_PRESTART_CMDS) start"
 
 .PHONY:: sel4test
 .PHONY:: sel4test-debug