Compile using Jack.

This allows to compile dex targeted java sources using Jack and Jill.
Default is still to compile with the legacy toolchain. Default can be
switched to the new toolchain by setting environement variable:
export ANDROID_COMPILE_WITH_JACK=true
Toolchain can also be forced for one module by defining
LOCAL_USE_JACK:=true # false
in the mk portion defining the module.

Jack execution environement can be controlled with:

Global variable ANDROID_JACK_VM allow to change the jvm executing Jack.
Global variable ANDROID_JACK_VM_ARGS allows to change default args given
to the jvm.
Global variable ANDROID_JACK_EXTRA_ARGS allows to define some default args
to give to Jack

LOCAL_JACK_VM_ARGS allows to override default args given to the jvm for
the module.
LOCAL_JACK_EXTRA_ARGS allows to override default args passed to Jack.

Change-Id: Ib81a0fd5f86a51d1e0edbb81cc791d828a05dd29
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 38f04f1..8e423e4 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -409,6 +409,7 @@
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
 $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JAVA_LIBRARIES := $(full_static_java_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JACK_LIBRARIES := $(full_static_jack_libs)
 
 # full_java_libs: The list of files that should be used as the classpath.
 #                 Using this list as a dependency list WILL NOT WORK.
@@ -417,7 +418,7 @@
 #                 be up-to-date.
 ifdef LOCAL_IS_HOST_MODULE
 ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-deps,core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(call java-lib-files,core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
 
 full_shared_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))
@@ -679,6 +680,105 @@
 endif
 
 ###########################################################
+# JACK
+###########################################################
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+ifdef need_compile_java
+
+full_static_jack_libs := \
+    $(foreach lib,$(LOCAL_STATIC_JAVA_LIBRARIES), \
+      $(call intermediates-dir-for, \
+        JAVA_LIBRARIES,$(lib),$(LOCAL_IS_HOST_MODULE),COMMON)/classes.jack)
+
+ifeq ($(my_prefix),TARGET_)
+ifeq ($(LOCAL_SDK_VERSION),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,core-libart)
+else
+ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
+# LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,android_stubs_current)
+else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,android_system_stubs_current)
+else
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,sdk_v$(LOCAL_SDK_VERSION))
+endif # current or system_current
+endif # LOCAL_SDK_VERSION
+endif # TARGET_
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JACK_LIBRARIES := $(full_static_jack_libs)
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM_ARGS := $(DEFAULT_JACK_VM_ARGS)
+ifneq ($(ANDROID_JACK_VM_ARGS),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM_ARGS := $(ANDROID_JACK_VM_ARGS)
+endif
+ifneq ($(LOCAL_JACK_VM_ARGS),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM_ARGS := $(LOCAL_JACK_VM_ARGS)
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_EXTRA_ARGS := $(DEFAULT_JACK_EXTRA_ARGS)
+ifneq ($(ANDROID_JACK_EXTRA_ARGS),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_EXTRA_ARGS := $(ANDROID_JACK_EXTRA_ARGS)
+endif
+ifneq ($(LOCAL_JACK_EXTRA_ARGS),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_EXTRA_ARGS := $(LOCAL_JACK_EXTRA_ARGS)
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM := $(DEFAULT_JACK_VM)
+ifneq ($(strip $(ANDROID_JACK_VM)),)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VM := $(ANDROID_JACK_VM)
+endif
+
+ifdef LOCAL_IS_HOST_MODULE
+ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES := $(call jack-lib-files,core-libart-hostdex,$(LOCAL_IS_HOST_MODULE))
+full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_jack_lib_deps := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+else
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES :=
+full_shared_jack_libs := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_jack_lib_deps := $(full_shared_jack_libs)
+endif # USE_CORE_LIB_BOOTCLASSPATH
+else # !LOCAL_IS_HOST_MODULE
+full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_jack_lib_deps := $(call jack-lib-deps,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+endif # !LOCAL_IS_HOST_MODULE
+full_jack_libs := $(full_shared_jack_libs) $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
+full_jack_lib_deps += $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
+
+# This is set by packages that are linking to other packages that export
+# shared libraries, allowing them to make use of the code in the linked apk.
+ifneq ($(apk_libraries),)
+  link_apk_jack_libraries := \
+      $(foreach lib,$(apk_libraries), \
+        $(call intermediates-dir-for, \
+              APPS,$(lib),,COMMON)/classes.jack)
+
+  # link against the jar with full original names (before proguard processing).
+  full_shared_jack_libs += $(link_apk_jack_libraries)
+  full_jack_libs += $(link_apk_jack_libraries)
+  full_jack_lib_deps += $(link_apk_jack_libraries)
+endif
+
+# This is set by packages that contain instrumentation, allowing them to
+# link against the package they are instrumenting.  Currently only one such
+# package is allowed.
+ifdef LOCAL_INSTRUMENTATION_FOR
+
+   # link against the jar with full original names (before proguard processing).
+   link_instr_classes_jack := $(link_instr_intermediates_dir.COMMON)/classes.noshrob.jack
+   full_jack_libs += $(link_instr_classes_jack)
+   full_jack_lib_deps += $(link_instr_classes_jack)
+endif
+
+endif  # need_compile_java
+
+# Propagate local configuration options to this target.
+$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_ALL_JACK_LIBRARIES:= $(full_jack_libs)
+$(LOCAL_INTERMEDIATE_TARGETS) : PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
+
+endif # LOCAL_USE_JACK
+
+###########################################################
 ## NOTICE files
 ###########################################################
 
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index f3f4ce9..142d09d 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -72,6 +72,7 @@
 LOCAL_JAVA_LAYERS_FILE:=
 LOCAL_NO_STANDARD_LIBRARIES:=
 LOCAL_CLASSPATH:=
+LOCAL_JACK_CLASSPATH:=
 LOCAL_DROIDDOC_USE_STANDARD_DOCLET:=
 LOCAL_DROIDDOC_SOURCE_PATH:=
 LOCAL_DROIDDOC_TEMPLATE_DIR:=
@@ -105,6 +106,10 @@
 LOCAL_ADDITIONAL_JAVA_DIR:=
 LOCAL_ALLOW_UNDEFINED_SYMBOLS:=
 LOCAL_DX_FLAGS:=
+LOCAL_USE_JACK:=$(ANDROID_COMPILE_WITH_JACK)
+LOCAL_JACK_VM_ARGS :=
+LOCAL_JACK_EXTRA_ARGS :=
+LOCAL_JACK_FLAGS:=
 LOCAL_CERTIFICATE:=
 LOCAL_SDK_VERSION:=
 LOCAL_SDK_RES_VERSION:=
@@ -112,6 +117,7 @@
 LOCAL_EMMA_INSTRUMENT:=
 LOCAL_PROGUARD_ENABLED:= # '',full,custom,nosystem,disabled,obfuscation,optimization
 LOCAL_PROGUARD_FLAGS:=
+LOCAL_JACK_PROGUARD_FLAGS:=
 LOCAL_PROGUARD_FLAG_FILES:=
 LOCAL_TEST_MODULE_TO_PROGUARD_WITH:=
 LOCAL_EMMA_COVERAGE_FILTER:=
diff --git a/core/config.mk b/core/config.mk
index c9453ef..358aa5e 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -365,6 +365,9 @@
 
 # ---------------------------------------------------------------
 # Generic tools.
+JACK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/jack.jar
+JILL_JAR := $(HOST_OUT_JAVA_LIBRARIES)/jill.jar
+JACK_MULTIDEX_DEFAULT_PREPROCESSOR := frameworks/multidex/library/resources/JACK-INF/legacyMultidexInstallation.jpp
 
 LEX := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/flex/flex-2.5.39
 # The default PKGDATADIR built in the prebuilt bison is a relative path
@@ -404,6 +407,18 @@
 TUNE2FS := $(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)
 E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
 JARJAR := $(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar
+# call jack
+#
+# $(1): vm
+# $(2): vm arguments
+# $(3): jack perf arguments
+define call-jack
+$(1) $(2) -cp $(JACK_JAR) com.android.jack.Main $(3)
+endef
+DEFAULT_JACK_VM := java
+DEFAULT_JACK_VM_ARGS := -Dfile.encoding=UTF-8 -Xmx3584m -Xms2560m -XX:+TieredCompilation
+DEFAULT_JACK_EXTRA_ARGS := -D sched.runner=single-threaded --sanity-checks off
+JILL := java -Xmx3500m -cp $(JILL_JAR) com.android.jill.Main
 PROGUARD := external/proguard/bin/proguard.sh
 JAVATAGS := build/tools/java-event-log-tags.py
 LLVM_RS_CC := $(HOST_OUT_EXECUTABLES)/llvm-rs-cc$(HOST_EXECUTABLE_SUFFIX)
diff --git a/core/definitions.mk b/core/definitions.mk
index c730231..b9884e6 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -403,6 +403,14 @@
 endef
 
 ###########################################################
+## Reverse order of a list
+###########################################################
+
+define reverse-list
+$(if $(1),$(call reverse-list,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
+endef
+
+###########################################################
 ## The intermediates directory.  Where object files go for
 ## a given target.  We could technically get away without
 ## the "_intermediates" suffix on the directory, but it's
@@ -592,7 +600,7 @@
 # $(1): library name
 # $(2): Non-empty if IS_HOST_MODULE
 define _java-lib-full-dep
-$(call _java-lib-dir,$(1),$(2))/$(if $(2),javalib,classes)$(COMMON_JAVA_PACKAGE_SUFFIX)
+$(call _java-lib-dir,$(1),$(2))/$(if $(2),javalib,classes)$(COMMON_JAVA_PACKAGE_SUFFIX) $(call _java-lib-full-classes.jar,$(lib),$(2))
 endef
 
 # $(1): library name list
@@ -602,6 +610,36 @@
 endef
 
 ###########################################################
+## Convert "core ext framework" to "out/.../classes.jack ..."
+## $(1): library list
+## $(2): Non-empty if IS_HOST_MODULE
+###########################################################
+
+# $(1): library name
+# $(2): Non-empty if IS_HOST_MODULE
+define _jack-lib-full-classes
+$(call _java-lib-dir,$(1),$(2))/classes.jack
+endef
+
+# $(1): library name list
+# $(2): Non-empty if IS_HOST_MODULE
+define jack-lib-files
+$(foreach lib,$(1),$(call _jack-lib-full-classes,$(lib),$(2)))
+endef
+
+# $(1): library name
+# $(2): Non-empty if IS_HOST_MODULE
+define _jack-lib-full-dep
+$(call _jack-lib-full-classes,$(1),$(2))
+endef
+
+# $(1): library name list
+# $(2): Non-empty if IS_HOST_MODULE
+define jack-lib-deps
+$(foreach lib,$(1),$(call _jack-lib-full-dep,$(lib),$(2)))
+endef
+
+###########################################################
 ## Run rot13 on a string
 ## $(1): the string.  Must be one line.
 ###########################################################
@@ -1647,6 +1685,122 @@
 $(call compile-java,$(TARGET_JAVAC),$(PRIVATE_BOOTCLASSPATH))
 endef
 
+# Invoke Jack to compile java from source to dex and jack files.
+#
+# Some historical notes:
+# - below we write the list of java files to java-source-list to avoid argument
+#   list length problems with Cygwin
+# - we filter out duplicate java file names because Jack doesn't like them.
+# TODO (yroussel) PRIVATE_RMTYPEDEFS
+define jack-java-to-dex
+$(hide) rm -f $@
+$(hide) rm -f $(PRIVATE_CLASSES_JACK)
+$(hide) rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(hide) mkdir -p $(dir $@)
+$(hide) mkdir -p $(dir $(PRIVATE_CLASSES_JACK))
+$(hide) mkdir -p $(PRIVATE_JACK_INTERMEDIATES_DIR)
+# TODO unzip only resources?
+$(call unzip-jar-files,$(PRIVATE_STATIC_JACK_LIBRARIES),$(PRIVATE_JACK_INTERMEDIATES_DIR))
+$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list)
+$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
+          find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list; \
+fi
+$(hide) tr ' ' '\n' < $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list \
+    | sort -u > $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
+$(if $(PRIVATE_JACK_PROGUARD_FLAGS), \
+    $(hide) echo -basedirectory $(CURDIR) > $@.flags; \
+    echo $(PRIVATE_JACK_PROGUARD_FLAGS) >> $@.flags; \
+)
+$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
+    export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
+else \
+    export tmpEcjArg=""; \
+fi; \
+$(call call-jack,$(PRIVATE_JACK_VM),$(PRIVATE_JACK_VM_ARGS),$(PRIVATE_JACK_EXTRA_ARGS)) \
+    $(strip $(PRIVATE_JACK_FLAGS)) \
+    $(strip $(PRIVATE_JACK_DEBUG_FLAGS)) \
+    $(if $(NO_OPTIMIZE_DX), \
+        -D jack.dex.optimize="false") \
+    $(addprefix --classpath ,$(strip \
+        $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+    $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
+    -D jack.import.resource.policy=keep-first \
+    -D jack.import.jackfile.policy=keep-first \
+    --output-jack $(PRIVATE_CLASSES_JACK) \
+    -D jack.java.source.version=1.7 \
+    --output-dex $(dir $@) \
+    $(addprefix --config-jarjar ,$(strip $(PRIVATE_JARJAR_RULES))) \
+    $(if $(PRIVATE_JACK_PROGUARD_FLAGS),--config-proguard $@.flags) \
+    $$tmpEcjArg \
+    || ( rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR); rm -f $@; exit 41 )
+$(call unzip-jar-files,$(PRIVATE_CLASSES_JACK),$(PRIVATE_JACK_INTERMEDIATES_DIR))
+$(hide) rm -f $(PRIVATE_CLASSES_JACK)
+$(hide) rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list
+$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq $(PRIVATE_JACK_INTERMEDIATES_DIR).java-source-list
+$(if $(PRIVATE_JAR_PACKAGES), $(hide) echo unsupported options PRIVATE_JAR_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) echo unsupported options JAR_EXCLUDE_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_MANIFEST), \
+    $(hide) sed -e 's/%BUILD_NUMBER%/$(BUILD_NUMBER)/' \
+            $(PRIVATE_JAR_MANIFEST) > $(dir $(PRIVATE_CLASSES_JACK))/manifest.mf && \
+        jar -cfm $(PRIVATE_CLASSES_JACK) $(dir $@)/manifest.mf \
+            -C $(PRIVATE_JACK_INTERMEDIATES_DIR) ., \
+    $(hide) jar -cf $(PRIVATE_CLASSES_JACK) -C $(PRIVATE_JACK_INTERMEDIATES_DIR) .)
+endef
+
+define transform-jar-to-jack
+	$(hide) mkdir -p $(dir $@)
+	$(JILL) --output $@ $<
+endef
+
+
+# Invoke Jack to compile java from source to jack files without shrink or obfuscation.
+#
+# Some historical notes:
+# - below we write the list of java files to java-source-list to avoid argument
+#   list length problems with Cygwin
+# - we filter out duplicate java file names because Jack doesn't like them.
+define java-to-jack
+$(hide) rm -f $@
+$(hide) rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(hide) mkdir -p $(dir $@)
+$(hide) mkdir -p $(PRIVATE_JACK_INTERMEDIATES_DIR)
+$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list)
+$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
+          find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list; \
+fi
+$(hide) tr ' ' '\n' < $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list \
+    | sort -u > $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
+$(if $(PRIVATE_JACK_PROGUARD_FLAGS), \
+    $(hide) echo -basedirectory $(CURDIR) > $@.flags; \
+    echo $(PRIVATE_JACK_PROGUARD_FLAGS) >> $@.flags; \
+)
+$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
+    export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
+else \
+    export tmpEcjArg=""; \
+fi; \
+$(call call-jack,$(PRIVATE_JACK_VM),$(PRIVATE_JACK_VM_ARGS),$(PRIVATE_JACK_EXTRA_ARGS)) \
+    $(strip $(PRIVATE_JACK_FLAGS)) \
+    $(strip $(PRIVATE_JACK_DEBUG_FLAGS)) \
+    $(if $(NO_OPTIMIZE_DX), \
+        -D jack.dex.optimize="false") \
+    $(addprefix --classpath ,$(strip \
+        $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH_JAVA_LIBRARIES) $(PRIVATE_ALL_JACK_LIBRARIES)))) \
+    $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
+    -D jack.import.resource.policy=keep-first \
+    -D jack.import.jackfile.policy=keep-first \
+    -D jack.java.source.version=1.7 \
+    --output-jack $@ \
+    $(addprefix --config-jarjar ,$(strip $(PRIVATE_JARJAR_RULES))) \
+    $(if $(PRIVATE_JACK_PROGUARD_FLAGS),--config-proguard $@.flags) \
+    $$tmpEcjArg \
+    || ( echo rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR); rm -f $@ ; exit 41 )
+$(hide) echo rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list
+$(hide) echo rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
+$(if $(PRIVATE_JAR_PACKAGES), $(hide) echo unsupported options PRIVATE_JAR_PACKAGES in $@; exit 53)
+$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) echo unsupported options JAR_EXCLUDE_PACKAGES in $@; exit 53)
+endef
+
 # Override the above definitions if we want to do incremetal javac
 ifeq (true, $(ENABLE_INCREMENTALJAVAC))
 define compile-java
@@ -1818,6 +1972,20 @@
 fi
 endef
 
+# Add resources carried by static Jack libraries.
+#
+define add-carried-jack-resources
+ $(hide) if [ -d $(PRIVATE_JACK_INTERMEDIATES_DIR) ] ; then \
+    jack_res_jar_flags=$$(find $(PRIVATE_JACK_INTERMEDIATES_DIR) -type f -a -not -name "*.jayce" \
+        | sed -e "s?^$(PRIVATE_JACK_INTERMEDIATES_DIR)/? -C $(PRIVATE_JACK_INTERMEDIATES_DIR) ?"); \
+    if [ -n "$$jack_res_jar_flags" ] ; then \
+        echo $$jack_res_jar_flags >$(dir $@)jack_res_jar_flags; \
+        jar uf $@ $$jack_res_jar_flags; \
+    fi; \
+fi
+endef
+
+
 # Sign a package using the specified key/cert.
 #
 define sign-package
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index 6583dd7..772245e 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -33,11 +33,13 @@
 full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
 full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
 full_classes_jar := $(intermediates.COMMON)/classes.jar
+full_classes_jack := $(intermediates.COMMON)/classes.jack
 built_dex := $(intermediates.COMMON)/classes.dex
 
 LOCAL_INTERMEDIATE_TARGETS += \
     $(full_classes_compiled_jar) \
     $(full_classes_jarjar_jar) \
+    $(full_classes_jack) \
     $(full_classes_jar) \
     $(built_dex)
 
@@ -95,6 +97,7 @@
 	@echo Copying: $@
 	$(hide) $(ACP) -fp $< $@
 
+ifneq ($(strip $(LOCAL_USE_JACK)),true)
 $(built_dex): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)
 $(built_dex): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
 $(built_dex): $(full_classes_jar) $(DX)
@@ -110,4 +113,31 @@
 	$(add-java-resources-to-package)
 endif
 
+else # LOCAL_USE_JACK
+$(LOCAL_INTERMEDIATE_TARGETS): \
+	PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jayces
+$(LOCAL_INTERMEDIATE_TARGETS):  PRIVATE_JACK_DEBUG_FLAGS := -g
+
+$(built_dex): PRIVATE_CLASSES_JACK := $(full_classes_jack)
+$(built_dex): PRIVATE_JACK_FLAGS := $(LOCAL_JACK_FLAGS)
+$(built_dex): $(java_sources) $(java_resource_sources) $(full_jack_lib_deps) \
+        $(jar_manifest_file) $(proto_java_sources_file_stamp) $(LOCAL_MODULE_MAKEFILE) \
+        $(LOCAL_MODULE_MAKEFILE) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK_JAR)
+	@echo Building with Jack: $@
+	$(jack-java-to-dex)
+
+$(full_classes_jack): $(built_dex)
+
+$(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
+$(LOCAL_BUILT_MODULE): $(built_dex) $(java_resource_sources)
+	@echo "Host Jar: $(PRIVATE_MODULE) ($@)"
+	$(create-empty-package)
+	$(add-dex-to-package)
+	$(add-carried-jack-resources)
+ifneq ($(extra_jar_args),)
+	$(add-java-resources-to-package)
+endif
+
+endif # LOCAL_USE_JACK
+
 USE_CORE_LIB_BOOTCLASSPATH :=
diff --git a/core/host_dalvik_static_java_library.mk b/core/host_dalvik_static_java_library.mk
index 3ae74e4..bb12e7e 100644
--- a/core/host_dalvik_static_java_library.mk
+++ b/core/host_dalvik_static_java_library.mk
@@ -23,6 +23,23 @@
 USE_CORE_LIB_BOOTCLASSPATH := true
 LOCAL_JAVA_LIBRARIES += core-libart-hostdex
 
+intermediates.COMMON := $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE),true,COMMON,)
+full_classes_jack := $(intermediates.COMMON)/classes.jack
+LOCAL_INTERMEDIATE_TARGETS += \
+    $(full_classes_jack)
+
 include $(BUILD_SYSTEM)/host_java_library.mk
+# proguard is not supported
+# *.proto files are not supported
+$(full_classes_jack): PRIVATE_JACK_FLAGS := $(LOCAL_JACK_FLAGS)
+$(full_classes_jack): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
+$(full_classes_jack): \
+	PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jayces
+$(full_classes_jack): $(java_sources) $(java_resource_sources) $(full_jack_lib_deps) \
+        $(jar_manifest_file) $(layers_file) $(LOCAL_MODULE_MAKEFILE) \
+        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
+        $(JACK_JAR)
+	@echo Building with Jack: $@
+	$(java-to-jack)
 
 USE_CORE_LIB_BOOTCLASSPATH :=
diff --git a/core/java.mk b/core/java.mk
index 9882ee2..51dc3fe 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -126,6 +126,10 @@
 full_classes_jar := $(intermediates.COMMON)/classes.jar
 built_dex := $(intermediates.COMMON)/classes.dex
 endif
+# final Jack library, shrinked and obfuscated if it must be
+full_classes_jack := $(intermediates.COMMON)/classes.jack
+# intermediate Jack library without shrink and obfuscation
+noshrob_classes_jack := $(intermediates.COMMON)/classes.noshrob.jack
 
 LOCAL_INTERMEDIATE_TARGETS += \
     $(full_classes_compiled_jar) \
@@ -134,6 +138,8 @@
     $(full_classes_jar) \
     $(full_classes_proguard_jar) \
     $(built_dex_intermediate) \
+    $(full_classes_jack) \
+    $(noshrob_classes_jack) \
     $(built_dex) \
     $(full_classes_stubs_jar)
 
@@ -329,7 +335,7 @@
 # - This extra copy, with the dependency on LOCAL_BUILT_MODULE allows the
 #   PRIVATE_ vars to be preserved.
 $(full_classes_stubs_jar): PRIVATE_SOURCE_FILE := $(full_classes_jar)
-$(full_classes_stubs_jar) : $(LOCAL_BUILT_MODULE) | $(ACP)
+$(full_classes_stubs_jar) : $(full_classes_jar) | $(ACP)
 	@echo Copying $(PRIVATE_SOURCE_FILE)
 	$(hide) $(ACP) -fp $(PRIVATE_SOURCE_FILE) $@
 ALL_MODULES.$(LOCAL_MODULE).STUBS := $(full_classes_stubs_jar)
@@ -415,50 +421,57 @@
     $(error invalid value for LOCAL_PROGUARD_ENABLED: $(LOCAL_PROGUARD_ENABLED))
 endif
 proguard_dictionary := $(intermediates.COMMON)/proguard_dictionary
-proguard_flags := $(addprefix -libraryjars ,$(full_shared_java_libs)) \
+# jack already has the libraries in its classpath and doesn't support jars
+legacy_proguard_flags := $(addprefix -libraryjars ,$(full_shared_java_libs))
+common_proguard_flags :=  \
                   -forceprocessing \
                   -printmapping $(proguard_dictionary)
 
 ifeq ($(filter nosystem,$(LOCAL_PROGUARD_ENABLED)),)
-proguard_flags += -include $(BUILD_SYSTEM)/proguard.flags
+common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.flags
 ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-proguard_flags += -include $(BUILD_SYSTEM)/proguard.emma.flags
+common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.emma.flags
 endif
 # If this is a test package, add proguard keep flags for tests.
 ifneq ($(LOCAL_INSTRUMENTATION_FOR)$(filter tests,$(LOCAL_MODULE_TAGS)),)
-proguard_flags += -include $(BUILD_SYSTEM)/proguard_tests.flags
+common_proguard_flags += -include $(BUILD_SYSTEM)/proguard_tests.flags
 ifeq ($(filter shrinktests,$(LOCAL_PROGUARD_ENABLED)),)
-proguard_flags += -dontshrink # don't shrink tests by default
+common_proguard_flags += -dontshrink # don't shrink tests by default
 endif # shrinktests
 endif # test package
 ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
 # By default no obfuscation
-proguard_flags += -dontobfuscate
+common_proguard_flags += -dontobfuscate
 endif  # No obfuscation
 ifeq ($(filter optimization,$(LOCAL_PROGUARD_ENABLED)),)
 # By default no optimization
-proguard_flags += -dontoptimize
+common_proguard_flags += -dontoptimize
 endif  # No optimization
 
 ifdef LOCAL_INSTRUMENTATION_FOR
 ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
 # If no obfuscation, link in the instrmented package's classes.jar as a library.
 # link_instr_classes_jar is defined in base_rule.mk
-proguard_flags += -libraryjars $(link_instr_classes_jar)
+# jack already has this library in its classpath and doesn't support jars
+legacy_proguard_flags += -libraryjars $(link_instr_classes_jar)
 else # obfuscation
 # If obfuscation is enabled, the main app must be obfuscated too.
 # We need to run obfuscation using the main app's dictionary,
 # and treat the main app's class.jar as injars instead of libraryjars.
-proguard_flags := -injars  $(link_instr_classes_jar) \
+legacy_proguard_flags := -injars  $(link_instr_classes_jar) \
     -outjars $(intermediates.COMMON)/proguard.$(LOCAL_INSTRUMENTATION_FOR).jar \
     -include $(link_instr_intermediates_dir.COMMON)/proguard_options \
     -applymapping $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \
     -verbose \
-    $(proguard_flags)
+    $(legacy_proguard_flags)
+# not supported with jack
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+    $(error $(LOCAL_MODULE): Build with jack of instrumentation when obfuscating is not yet supported)
+endif
 
 # Sometimes (test + main app) uses different keep rules from the main app -
 # apply the main app's dictionary anyway.
-proguard_flags += -ignorewarnings
+legacy_proguard_flags += -ignorewarnings
 
 # Make sure we run Proguard on the main app first
 $(full_classes_proguard_jar) : $(link_instr_intermediates_dir.COMMON)/proguard.classes.jar
@@ -476,7 +489,7 @@
 extra_input_jar :=
 endif
 $(full_classes_proguard_jar): PRIVATE_EXTRA_INPUT_JAR := $(extra_input_jar)
-$(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(proguard_flags) $(LOCAL_PROGUARD_FLAGS)
+$(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(legacy_proguard_flags) $(common_proguard_flags) $(LOCAL_PROGUARD_FLAGS)
 $(full_classes_proguard_jar) : $(full_classes_jar) $(extra_input_jar) $(proguard_flag_files) | $(ACP) $(PROGUARD)
 	$(call transform-jar-to-proguard)
 
@@ -503,6 +516,7 @@
 endif
 $(built_dex_intermediate): $(full_classes_proguard_jar) $(DX)
 	$(transform-classes.jar-to-dex)
+
 $(built_dex): $(built_dex_intermediate) | $(ACP)
 	@echo Copying: $@
 	$(hide) mkdir -p $(dir $@)
@@ -540,3 +554,56 @@
 $(LOCAL_MODULE)-findbugs : $(findbugs_html)
 
 endif  # full_classes_jar is defined
+
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+$(LOCAL_INTERMEDIATE_TARGETS): \
+	PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jayces
+
+ifdef full_classes_jar
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_DEBUG_FLAGS := -g
+
+ifdef LOCAL_PROGUARD_ENABLED
+
+ifndef LOCAL_JACK_PROGUARD_FLAGS
+    LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
+endif
+LOCAL_JACK_PROGUARD_FLAGS += $(addprefix -include , $(proguard_flag_files))
+ifdef LOCAL_TEST_MODULE_TO_PROGUARD_WITH
+    $(error $(LOCAL_MODULE): Build with jack when LOCAL_TEST_MODULE_TO_PROGUARD_WITH is defined is not yet implemented)
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_PROGUARD_FLAGS := $(common_proguard_flags) $(LOCAL_JACK_PROGUARD_FLAGS)
+else  # LOCAL_PROGUARD_ENABLED not defined
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_PROGUARD_FLAGS :=
+endif # LOCAL_PROGUARD_ENABLED defined
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_FLAGS := $(LOCAL_JACK_FLAGS)
+
+jack_all_deps := $(java_sources) $(java_resource_sources) $(full_jack_lib_deps) \
+        $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) $(proguard_flag_files) \
+        $(proto_java_sources_file_stamp) $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
+        $(LOCAL_MODULE_MAKEFILE) $(JACK_JAR)
+
+ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
+$(full_classes_jack): $(jack_all_deps)
+	@echo Building with Jack: $@
+	$(java-to-jack)
+
+else #LOCAL_IS_STATIC_JAVA_LIBRARY
+$(built_dex_intermediate): PRIVATE_CLASSES_JACK := $(full_classes_jack)
+
+$(built_dex_intermediate): $(jack_all_deps)
+	@echo Building with Jack: $@
+	$(jack-java-to-dex)
+
+$(full_classes_jack): $(built_dex_intermediate)
+# nothing to do it's built as a side effect of $(built_dex_intermediate)
+endif #LOCAL_IS_STATIC_JAVA_LIBRARY
+
+$(noshrob_classes_jack): PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/noshrob
+$(noshrob_classes_jack): PRIVATE_JACK_PROGUARD_FLAGS :=
+$(noshrob_classes_jack): $(jack_all_deps)
+	@echo Building with Jack: $@
+	$(java-to-jack)
+endif  # full_classes_jar is defined
+endif # LOCAL_USE_JACK
diff --git a/core/java_library.mk b/core/java_library.mk
index dffc7d9..8685777 100644
--- a/core/java_library.mk
+++ b/core/java_library.mk
@@ -72,7 +72,11 @@
 	@echo "target Jar: $(PRIVATE_MODULE) ($@)"
 	$(create-empty-package)
 	$(add-dex-to-package)
+ifneq ($(strip $(LOCAL_USE_JACK)),true)
 	$(add-carried-java-resources)
+else
+	$(add-carried-jack-resources)
+endif
 ifneq ($(extra_jar_args),)
 	$(add-java-resources-to-package)
 endif
diff --git a/core/package_internal.mk b/core/package_internal.mk
index e2c3cf4..c02e9ea 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -161,6 +161,13 @@
 endif # !custom
 LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
 
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+ifndef LOCAL_JACK_PROGUARD_FLAGS
+    LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
+endif
+LOCAL_JACK_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_JACK_PROGUARD_FLAGS)
+endif # LOCAL_USE_JACK
+
 ifeq (true,$(EMMA_INSTRUMENT))
 ifndef LOCAL_EMMA_INSTRUMENT
 # No emma for test apks.
@@ -275,6 +282,18 @@
 # they want to use this module's R.java file.
 $(LOCAL_BUILT_MODULE): $(R_file_stamp)
 
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+ifneq ($(built_dex_intermediate),)
+$(built_dex_intermediate): $(R_file_stamp)
+endif
+ifneq ($(noshrob_classes_jack),)
+$(noshrob_classes_jack): $(R_file_stamp)
+endif
+ifneq ($(full_classes_jack),)
+$(full_classes_jack): $(R_file_stamp)
+endif
+endif # LOCAL_USE_JACK
+
 ifneq ($(full_classes_jar),)
 # If full_classes_jar is non-empty, we're building sources.
 # If we're building sources, the initial javac step (which
@@ -393,7 +412,11 @@
 ifneq ($(full_classes_jar),)
 	$(add-dex-to-package)
 endif
+ifneq ($(strip $(LOCAL_USE_JACK)),true)
 	$(add-carried-java-resources)
+else
+	$(add-carried-jack-resources)
+endif
 ifneq ($(extra_jar_args),)
 	$(add-java-resources-to-package)
 endif
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 828b442..0a6ba9c 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -299,6 +299,13 @@
 $(built_module) : $(common_javalib_jar)
 endif # TARGET JAVA_LIBRARIES
 
+ifeq ($(LOCAL_MODULE_CLASS),JAVA_LIBRARIES)
+$(intermediates.COMMON)/classes.jack : $(my_prebuilt_src_file) $(LOCAL_MODULE_MAKEFILE) \
+        $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JILL_JAR)
+	$(transform-jar-to-jack)
+
+endif # JAVA_LIBRARIES
+
 $(built_module) : $(LOCAL_MODULE_MAKEFILE) $(LOCAL_ADDITIONAL_DEPENDENCIES)
 
 my_prebuilt_src_file :=
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 02078e0..ecdfeeb 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -56,8 +56,16 @@
 ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
   proguard_options_file := $(intermediates.COMMON)/proguard_options
 endif
+
 LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
 
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+ifndef LOCAL_JACK_PROGUARD_FLAGS
+    LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
+endif
+LOCAL_JACK_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_JACK_PROGUARD_FLAGS)
+endif # LOCAL_USE_JACK
+
 endif  # LOCAL_RESOURCE_DIR
 
 all_res_assets := $(all_resources)
@@ -114,9 +122,11 @@
 	$(hide) find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name R.java | xargs cat > $@
 
 $(LOCAL_BUILT_MODULE): $(R_file_stamp)
-ifneq ($(full_classes_jar),)
+ifeq ($(strip $(LOCAL_USE_JACK)),true)
+$(noshrob_classes_jack): $(R_file_stamp)
+$(full_classes_jack): $(R_file_stamp)
+endif # LOCAL_USE_JACK
 $(full_classes_compiled_jar): $(R_file_stamp)
-endif
 
 endif  # need_compile_res