rework emerge integration to run a single instance

The original design was that people could only install the latest version
of packages and that's it.  Requests are now coming in to support older
SLOTs (like getting python-2.7).  The current system turns the atoms into
make targets, but the full atom syntax includes bytes that are not valid
targets (such as the colon in "dev-lang/python:2.7").

Rework the modules so that we only run one instance of emerge, and give
it the full list of packages in one go.

BUG=b:26861037
TEST=`lunch brilloemulator_x86_64-eng && make -j32` now includes python in the image

Change-Id: Ia95e522572f4c944acbf449f93c702c6687f3fd1
diff --git a/Android.mk b/Android.mk
index b5c4088..7798035 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,6 +3,12 @@
 # Only load these subdirs when 3rd party packages have been requested.
 ifneq ($(PRODUCT_3RD_PARTY_PACKAGES),)
 
+# Make sure they don't try putting quotes into the string.
+# We'll take care of that for them.
+ifneq (,$(findstring ',$(PRODUCT_3RD_PARTY_PACKAGES))$(findstring ",$(PRODUCT_3RD_PARTY_PACKAGES)))
+$(error Please do not quote atoms in PRODUCT_3RD_PARTY_PACKAGES.)
+endif
+
 ifeq ($(TARGET_IS_64_BIT),true)
 3RD_PARTY_LIBDIR := lib64
 else
@@ -71,38 +77,31 @@
 # Only depend on the packages that are actually requested.
 3RD_PARTY_EXTERNAL_DEPS += $(filter $(3RD_PARTY_EXTERNAL_LIBS),$(product_MODULES) $(PRODUCT_PACKAGES))
 
-# Actually run the emerge command for the specific package.
-TARGET_TO_ATOM = $(notdir $(patsubst %/,%,$(dir $(1))))/$(notdir $(1:.emerge=))
-%.emerge: | $(3RD_PARTY_WRAPPERS) $(3RD_PARTY_CONFIGS) $(3RD_PARTY_EXTERNAL_DEPS)
-	$(hide)mkdir -p $(dir $@) $(TARGET_OUT_GENTOO)/tmp
-	$(hide)emerge $(call TARGET_TO_ATOM,$@)
-	$(hide)3rd-party-merge \
-		--package $(call TARGET_TO_ATOM,$@) \
-		--input-root $(3RD_PARTY_ROOT) \
-		--output-root $(TARGET_OUT) \
-		--make-root $(TARGET_OUT_GENTOO)/mk-installed
-	$(hide)touch $@
-
-# Set up a module for each requested package.
-define 3rd-party-merge
-include $(CLEAR_VARS)
-LOCAL_MODULE := mk-installed/$(1).emerge
-LOCAL_MODULE_CLASS := GENTOO
-LOCAL_UNINSTALLABLE_MODULE := true
-include $$(BUILD_SYSTEM)/base_rules.mk
-endef
-$(foreach p,$(PRODUCT_3RD_PARTY_PACKAGES),$(eval $(call 3rd-party-merge,$(p))))
-
 # A pseudo target that depends on all the generated packages above.
 # The board can use this in their PRODUCT_PACKAGES list.
 include $(CLEAR_VARS)
 LOCAL_MODULE := 3rd-party-packages
 LOCAL_MODULE_CLASS := GENTOO
-LOCAL_ADDITIONAL_DEPENDENCIES := $(foreach p,$(PRODUCT_3RD_PARTY_PACKAGES),mk-installed/$(p).emerge)
+LOCAL_ADDITIONAL_DEPENDENCIES := $(3RD_PARTY_WRAPPERS) $(3RD_PARTY_CONFIGS) $(3RD_PARTY_EXTERNAL_DEPS)
+
 include $(BUILD_SYSTEM)/base_rules.mk
+
+3RD_PARTY_PACKAGES_QUOTED := $(patsubst %,'%',$(PRODUCT_3RD_PARTY_PACKAGES))
 LOCAL_BUILT_MODULE := $(intermediates)/$(LOCAL_MODULE)
 $(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
-	$(hide)mkdir -p $(dir $@)
+	$(hide)mkdir -p $(dir $@) $(TARGET_OUT_GENTOO)/tmp
+	$(hide)\
+		printf '%s\n' $(3RD_PARTY_PACKAGES_QUOTED) | LC_ALL=C sort > $@.tmp; \
+		if cmp $@.tmp $@ 2>/dev/null; then \
+			mv $@.tmp $@; \
+			exit 0; \
+		fi; \
+		emerge -uN $(3RD_PARTY_PACKAGES_QUOTED) || exit; \
+		3rd-party-merge \
+			$(patsubst %,--package %,$(3RD_PARTY_PACKAGES_QUOTED)) \
+			--input-root $(3RD_PARTY_ROOT) \
+			--output-root $(TARGET_OUT) \
+			--make-root $(TARGET_OUT_GENTOO)/mk-installed
 	$(hide)touch $@
 
 endif