Add modifier goal incrementaljavac

With "incrementaljavac" on your make command line, you will recompile
only Java source files that have been changed since last build.
Nothing is changed if "incrementaljavac" is not among your make goals.

Change-Id: Iae591459827df81ac91e95292464db5e9828343a
diff --git a/core/base_rules.mk b/core/base_rules.mk
index d0c4aaf..107af9b 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -416,12 +416,14 @@
 #                 to guarantee that the files in full_java_libs will
 #                 be up-to-date.
 ifdef LOCAL_IS_HOST_MODULE
-# TODO: make prebuilt java libraries use the same
-#       intermediates path pattern as target java libraries.
 ifeq ($(LOCAL_BUILD_HOST_DEX),true)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,core-hostdex,$(LOCAL_IS_HOST_MODULE))
+
 full_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
 full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
 else
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH :=
+
 full_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,$(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
 full_java_lib_deps := $(full_java_libs)
 endif # LOCAL_BUILD_HOST_DEX
diff --git a/core/definitions.mk b/core/definitions.mk
index ea47f6b..3b0e464 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -1418,12 +1418,12 @@
 $(hide) mkdir -p $(dir $@)
 $(hide) mkdir -p $(PRIVATE_CLASS_INTERMEDIATES_DIR)
 $(call unzip-jar-files,$(PRIVATE_STATIC_JAVA_LIBRARIES),$(PRIVATE_CLASS_INTERMEDIATES_DIR))
-$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))/java-source-list)
+$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list)
 $(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
-	    find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))/java-source-list; \
+	    find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \
 fi
-$(hide) tr ' ' '\n' < $(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))java-source-list \
-    | sort -u > $(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))java-source-list-uniq
+$(hide) tr ' ' '\n' < $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list \
+    | sort -u > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
 $(hide) $(1) -encoding ascii \
     $(strip $(PRIVATE_JAVAC_DEBUG_FLAGS)) \
     $(if $(findstring true,$(LOCAL_WARNINGS_ENABLE)),$(xlint_unchecked),) \
@@ -1433,10 +1433,10 @@
     $(if $(findstring true,$(LOCAL_WARNINGS_ENABLE)),$(xlint_unchecked),) \
     -extdirs "" -d $(PRIVATE_CLASS_INTERMEDIATES_DIR) \
     $(PRIVATE_JAVACFLAGS) \
-    \@$(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))java-source-list-uniq \
+    \@$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq \
     || ( rm -rf $(PRIVATE_CLASS_INTERMEDIATES_DIR) ; exit 41 )
-$(hide) rm -f $(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))/java-source-list
-$(hide) rm -f $(dir $(PRIVATE_CLASS_INTERMEDIATES_DIR))/java-source-list-uniq
+$(hide) rm -f $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list
+$(hide) rm -f $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
 $(hide) jar $(if $(strip $(PRIVATE_JAR_MANIFEST)),-cfm,-cf) \
     $@ $(PRIVATE_JAR_MANIFEST) -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .
 endef
@@ -1447,6 +1447,51 @@
 $(hide) rm -rf $(PRIVATE_CLASS_INTERMEDIATES_DIR)
 endef
 
+# Override the above definitions if we want to do incremetal javac
+ifeq (true, $(ENABLE_INCREMENTALJAVAC))
+define compile-java
+$(hide) mkdir -p $(dir $@)
+$(hide) mkdir -p $(PRIVATE_CLASS_INTERMEDIATES_DIR)
+$(hide) touch $(PRIVATE_CLASS_INTERMEDIATES_DIR)/newstamp
+$(call unzip-jar-files,$(PRIVATE_STATIC_JAVA_LIBRARIES),$(PRIVATE_CLASS_INTERMEDIATES_DIR))
+$(hide) if [ -e $(PRIVATE_CLASS_INTERMEDIATES_DIR)/stamp ] ; then \
+        newerFlag=$$(echo -n "-newer $(PRIVATE_CLASS_INTERMEDIATES_DIR)/stamp") ; \
+    fi ; \
+    find $(PRIVATE_JAVA_SOURCES) $$newerFlag > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list ; \
+    if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
+        find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' $$newerFlag >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \
+    fi
+$(hide) tr ' ' '\n' < $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list \
+    | sort -u > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
+@echo "(Incremental) build source files:"
+@cat $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
+$(hide) if [ -s $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
+    $(1) -encoding ascii \
+    $(strip $(PRIVATE_JAVAC_DEBUG_FLAGS)) \
+    $(if $(findstring true,$(LOCAL_WARNINGS_ENABLE)),$(xlint_unchecked),) \
+    $(2) \
+    $(addprefix -classpath ,$(strip \
+        $(call normalize-path-list,$(PRIVATE_ALL_JAVA_LIBRARIES) $(PRIVATE_CLASS_INTERMEDIATES_DIR)))) \
+    $(if $(findstring true,$(LOCAL_WARNINGS_ENABLE)),$(xlint_unchecked),) \
+    -extdirs "" -d $(PRIVATE_CLASS_INTERMEDIATES_DIR) \
+    $(PRIVATE_JAVACFLAGS) \
+    \@$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq \
+    || ( exit 41 ) \
+fi
+$(hide) rm -f $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list
+$(hide) rm -f $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
+$(hide) rm -f $@
+$(hide) jar $(if $(strip $(PRIVATE_JAR_MANIFEST)),-cfm,-cf) \
+    $@ $(PRIVATE_JAR_MANIFEST) -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .
+$(hide) mv $(PRIVATE_CLASS_INTERMEDIATES_DIR)/newstamp $(PRIVATE_CLASS_INTERMEDIATES_DIR)/stamp
+endef
+
+define transform-java-to-classes.jar
+@echo "target Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
+$(call compile-java,$(TARGET_JAVAC),$(PRIVATE_BOOTCLASSPATH))
+endef
+endif # ENABLE_INCREMENTALJAVAC
+
 define transform-classes.jar-to-emma
 $(hide) java -classpath $(EMMA_JAR) emma instr -outmode fullcopy -outfile \
     $(PRIVATE_EMMA_COVERAGE_FILE) -ip $< -d $(PRIVATE_EMMA_INTERMEDIATES_DIR) \
@@ -1570,7 +1615,7 @@
 # in transform-java-to-classes for the sake of vm-tests.
 define transform-host-java-to-package
 @echo "host Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
-$(call compile-java,$(HOST_JAVAC),)
+$(call compile-java,$(HOST_JAVAC),$(PRIVATE_BOOTCLASSPATH))
 $(hide) if [ ! -z "$(PRIVATE_EXTRA_JAR_ARGS)" ]; then jar uf $@ $(PRIVATE_EXTRA_JAR_ARGS); fi
 endef
 
diff --git a/core/main.mk b/core/main.mk
index 4a530d0..2c8811c 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -155,7 +155,23 @@
 # These are the modifier targets that don't do anything themselves, but
 # change the behavior of the build.
 # (must be defined before including definitions.make)
-INTERNAL_MODIFIER_TARGETS := showcommands checkbuild all
+INTERNAL_MODIFIER_TARGETS := showcommands checkbuild all incrementaljavac
+
+.PHONY: incrementaljavac
+incrementaljavac: ;
+
+# WARNING:
+# ENABLE_INCREMENTALJAVAC should NOT be enabled by default, because change of
+# a Java source file won't trigger rebuild of its dependent Java files.
+# You can only enable it by adding "incrementaljavac" to your make command line.
+# You are responsible for the correctness of the incremental build.
+# This may decrease incremental build time dramatically for large Java libraries,
+# such as core.jar, framework.jar, etc.
+ENABLE_INCREMENTALJAVAC :=
+ifneq (,$(filter incrementaljavac, $(MAKECMDGOALS)))
+ENABLE_INCREMENTALJAVAC := true
+MAKECMDGOALS := $(filter-out incrementaljavac, $(MAKECMDGOALS))
+endif
 
 # Bring in standard build system definitions.
 include $(BUILD_SYSTEM)/definitions.mk
diff --git a/envsetup.sh b/envsetup.sh
index 4b2c19e..2faeed1 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -695,6 +695,8 @@
                     ARGS="$ARGS showcommands"
                 elif [ "$DIR" = dist ]; then
                     ARGS="$ARGS dist"
+                elif [ "$DIR" = incrementaljavac ]; then
+                    ARGS="$ARGS incrementaljavac"
                 else
                     echo "No Android.mk in $DIR."
                     return 1