summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/004-UnsafeTest/src/Main.java2
-rw-r--r--test/004-checker-UnsafeTest18/expected.txt2
-rw-r--r--test/004-checker-UnsafeTest18/info.txt1
-rw-r--r--test/004-checker-UnsafeTest18/src/Main.java270
-rw-r--r--test/145-alloc-tracking-stress/src/Main.java1
-rw-r--r--test/462-checker-inlining-across-dex-files/multidex.jpp8
-rw-r--r--test/556-invoke-super/multidex.jpp4
-rw-r--r--test/569-checker-pattern-replacement/multidex.jpp8
-rw-r--r--test/577-profile-foreign-dex/expected.txt0
-rw-r--r--test/577-profile-foreign-dex/info.txt1
-rw-r--r--test/577-profile-foreign-dex/run20
-rw-r--r--test/577-profile-foreign-dex/src-ex/OtherDex.java17
-rw-r--r--test/577-profile-foreign-dex/src/Main.java175
-rw-r--r--test/Android.run-test.mk4
-rwxr-xr-xtest/etc/default-build29
15 files changed, 527 insertions, 15 deletions
diff --git a/test/004-UnsafeTest/src/Main.java b/test/004-UnsafeTest/src/Main.java
index a9a7a058e0..b2f905e0ee 100644
--- a/test/004-UnsafeTest/src/Main.java
+++ b/test/004-UnsafeTest/src/Main.java
@@ -40,7 +40,7 @@ public class Main {
}
private static Unsafe getUnsafe() throws Exception {
- Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
+ Class<?> unsafeClass = Unsafe.class;
Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
diff --git a/test/004-checker-UnsafeTest18/expected.txt b/test/004-checker-UnsafeTest18/expected.txt
new file mode 100644
index 0000000000..651da727af
--- /dev/null
+++ b/test/004-checker-UnsafeTest18/expected.txt
@@ -0,0 +1,2 @@
+starting
+passed
diff --git a/test/004-checker-UnsafeTest18/info.txt b/test/004-checker-UnsafeTest18/info.txt
new file mode 100644
index 0000000000..0fca5ebf03
--- /dev/null
+++ b/test/004-checker-UnsafeTest18/info.txt
@@ -0,0 +1 @@
+Test support for 1.8 sun.misc.Unsafe.
diff --git a/test/004-checker-UnsafeTest18/src/Main.java b/test/004-checker-UnsafeTest18/src/Main.java
new file mode 100644
index 0000000000..bb020b9b9f
--- /dev/null
+++ b/test/004-checker-UnsafeTest18/src/Main.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Field;
+
+import sun.misc.Unsafe;
+
+/**
+ * Checker test on the 1.8 unsafe operations. Note, this is by no means an
+ * exhaustive unit test for these CAS (compare-and-swap) and fence operations.
+ * Instead, this test ensures the methods are recognized as intrinsic and behave
+ * as expected.
+ */
+public class Main {
+
+ private static final Unsafe unsafe = getUnsafe();
+
+ private static Thread[] sThreads = new Thread[10];
+
+ //
+ // Fields accessed by setters and adders.
+ //
+
+ public int i = 0;
+ public long l = 0;
+ public Object o = null;
+
+ //
+ // Setters.
+ //
+
+ /// CHECK-START: int Main.set32(java.lang.Object, long, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetInt
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int set32(Object o, long offset, int newValue) {
+ return unsafe.getAndSetInt(o, offset, newValue);
+ }
+
+ /// CHECK-START: long Main.set64(java.lang.Object, long, long) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetLong
+ /// CHECK-DAG: Return [<<Result>>]
+ private static long set64(Object o, long offset, long newValue) {
+ return unsafe.getAndSetLong(o, offset, newValue);
+ }
+
+ /// CHECK-START: java.lang.Object Main.setObj(java.lang.Object, long, java.lang.Object) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:l\d+>> InvokeVirtual intrinsic:UnsafeGetAndSetObject
+ /// CHECK-DAG: Return [<<Result>>]
+ private static Object setObj(Object o, long offset, Object newValue) {
+ return unsafe.getAndSetObject(o, offset, newValue);
+ }
+
+ //
+ // Adders.
+ //
+
+ /// CHECK-START: int Main.add32(java.lang.Object, long, int) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:i\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddInt
+ /// CHECK-DAG: Return [<<Result>>]
+ private static int add32(Object o, long offset, int delta) {
+ return unsafe.getAndAddInt(o, offset, delta);
+ }
+
+ /// CHECK-START: long Main.add64(java.lang.Object, long, long) intrinsics_recognition (after)
+ /// CHECK-DAG: <<Result:j\d+>> InvokeVirtual intrinsic:UnsafeGetAndAddLong
+ /// CHECK-DAG: Return [<<Result>>]
+ private static long add64(Object o, long offset, long delta) {
+ return unsafe.getAndAddLong(o, offset, delta);
+ }
+
+ //
+ // Fences (native).
+ //
+
+ /// CHECK-START: void Main.load() intrinsics_recognition (after)
+ /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeLoadFence
+ //
+ /// CHECK-START: void Main.load() instruction_simplifier (after)
+ /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeLoadFence
+ //
+ /// CHECK-START: void Main.load() instruction_simplifier (after)
+ /// CHECK-DAG: MemoryBarrier kind:LoadAny
+ private static void load() {
+ unsafe.loadFence();
+ }
+
+ /// CHECK-START: void Main.store() intrinsics_recognition (after)
+ /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeStoreFence
+ //
+ /// CHECK-START: void Main.store() instruction_simplifier (after)
+ /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeStoreFence
+ //
+ /// CHECK-START: void Main.store() instruction_simplifier (after)
+ /// CHECK-DAG: MemoryBarrier kind:AnyStore
+ private static void store() {
+ unsafe.storeFence();
+ }
+
+ /// CHECK-START: void Main.full() intrinsics_recognition (after)
+ /// CHECK-DAG: InvokeVirtual intrinsic:UnsafeFullFence
+ //
+ /// CHECK-START: void Main.full() instruction_simplifier (after)
+ /// CHECK-NOT: InvokeVirtual intrinsic:UnsafeFullFence
+ //
+ /// CHECK-START: void Main.full() instruction_simplifier (after)
+ /// CHECK-DAG: MemoryBarrier kind:AnyAny
+ private static void full() {
+ unsafe.fullFence();
+ }
+
+ //
+ // Thread fork/join.
+ //
+
+ private static void fork(Runnable r) {
+ for (int i = 0; i < 10; i++) {
+ sThreads[i] = new Thread(r);
+ sThreads[i].start();
+ }
+ }
+
+ private static void join() {
+ try {
+ for (int i = 0; i < 10; i++) {
+ sThreads[i].join();
+ }
+ } catch (InterruptedException e) {
+ throw new Error("Failed join: " + e);
+ }
+ }
+
+ //
+ // Driver.
+ //
+
+ public static void main(String[] args) {
+ System.out.println("starting");
+
+ final Main m = new Main();
+
+ // Get the offsets.
+
+ final long intOffset, longOffset, objOffset;
+ try {
+ Field intField = Main.class.getDeclaredField("i");
+ Field longField = Main.class.getDeclaredField("l");
+ Field objField = Main.class.getDeclaredField("o");
+
+ intOffset = unsafe.objectFieldOffset(intField);
+ longOffset = unsafe.objectFieldOffset(longField);
+ objOffset = unsafe.objectFieldOffset(objField);
+
+ } catch (NoSuchFieldException e) {
+ throw new Error("No offset: " + e);
+ }
+
+ // Some sanity within same thread.
+
+ set32(m, intOffset, 3);
+ expectEquals32(3, m.i);
+
+ set64(m, longOffset, 7L);
+ expectEquals64(7L, m.l);
+
+ setObj(m, objOffset, m);
+ expectEqualsObj(m, m.o);
+
+ add32(m, intOffset, 11);
+ expectEquals32(14, m.i);
+
+ add64(m, longOffset, 13L);
+ expectEquals64(20L, m.l);
+
+ // Some sanity on setters within different threads.
+
+ fork(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 10; i++)
+ set32(m, intOffset, i);
+ }
+ });
+ join();
+ expectEquals32(9, m.i); // one thread's last value wins
+
+ fork(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 10; i++)
+ set64(m, longOffset, (long) (100 + i));
+ }
+ });
+ join();
+ expectEquals64(109L, m.l); // one thread's last value wins
+
+ fork(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 10; i++)
+ setObj(m, objOffset, sThreads[i]);
+ }
+ });
+ join();
+ expectEqualsObj(sThreads[9], m.o); // one thread's last value wins
+
+ // Some sanity on adders within different threads.
+
+ fork(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 10; i++)
+ add32(m, intOffset, i + 1);
+ }
+ });
+ join();
+ expectEquals32(559, m.i); // all values accounted for
+
+ fork(new Runnable() {
+ public void run() {
+ for (int i = 0; i < 10; i++)
+ add64(m, longOffset, (long) (i + 1));
+ }
+ });
+ join();
+ expectEquals64(659L, m.l); // all values accounted for
+
+ // TODO: the fences
+
+ System.out.println("passed");
+ }
+
+ // Use reflection to implement "Unsafe.getUnsafe()";
+ private static Unsafe getUnsafe() {
+ try {
+ Class<?> unsafeClass = Unsafe.class;
+ Field f = unsafeClass.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ return (Unsafe) f.get(null);
+ } catch (Exception e) {
+ throw new Error("Cannot get Unsafe instance");
+ }
+ }
+
+ private static void expectEquals32(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEquals64(long expected, long result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+
+ private static void expectEqualsObj(Object expected, Object result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}
diff --git a/test/145-alloc-tracking-stress/src/Main.java b/test/145-alloc-tracking-stress/src/Main.java
index 752fdd9135..418690a2a6 100644
--- a/test/145-alloc-tracking-stress/src/Main.java
+++ b/test/145-alloc-tracking-stress/src/Main.java
@@ -1,5 +1,4 @@
/*
-
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/test/462-checker-inlining-across-dex-files/multidex.jpp b/test/462-checker-inlining-across-dex-files/multidex.jpp
new file mode 100644
index 0000000000..ae554566cb
--- /dev/null
+++ b/test/462-checker-inlining-across-dex-files/multidex.jpp
@@ -0,0 +1,8 @@
+Main:
+ @@com.android.jack.annotations.ForceInMainDex
+ class Main
+
+AAA:
+ @@com.android.jack.annotations.ForceInMainDex
+ class AAA
+
diff --git a/test/556-invoke-super/multidex.jpp b/test/556-invoke-super/multidex.jpp
new file mode 100644
index 0000000000..fe018019e3
--- /dev/null
+++ b/test/556-invoke-super/multidex.jpp
@@ -0,0 +1,4 @@
+Main:
+ @@com.android.jack.annotations.ForceInMainDex
+ class Main*
+
diff --git a/test/569-checker-pattern-replacement/multidex.jpp b/test/569-checker-pattern-replacement/multidex.jpp
new file mode 100644
index 0000000000..cfc8ad1fc9
--- /dev/null
+++ b/test/569-checker-pattern-replacement/multidex.jpp
@@ -0,0 +1,8 @@
+Main:
+ @@com.android.jack.annotations.ForceInMainDex
+ class Main
+
+BaseInMainDex:
+ @@com.android.jack.annotations.ForceInMainDex
+ class BaseInMainDex
+
diff --git a/test/577-profile-foreign-dex/expected.txt b/test/577-profile-foreign-dex/expected.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/577-profile-foreign-dex/expected.txt
diff --git a/test/577-profile-foreign-dex/info.txt b/test/577-profile-foreign-dex/info.txt
new file mode 100644
index 0000000000..090db3fdc6
--- /dev/null
+++ b/test/577-profile-foreign-dex/info.txt
@@ -0,0 +1 @@
+Check that we record the use of foreign dex files when profiles are enabled.
diff --git a/test/577-profile-foreign-dex/run b/test/577-profile-foreign-dex/run
new file mode 100644
index 0000000000..ad57d14c60
--- /dev/null
+++ b/test/577-profile-foreign-dex/run
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Copyright 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+exec ${RUN} \
+ --runtime-option -Xjitsaveprofilinginfo \
+ --runtime-option -Xusejit:true \
+ "${@}"
diff --git a/test/577-profile-foreign-dex/src-ex/OtherDex.java b/test/577-profile-foreign-dex/src-ex/OtherDex.java
new file mode 100644
index 0000000000..cba73b3094
--- /dev/null
+++ b/test/577-profile-foreign-dex/src-ex/OtherDex.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+public class OtherDex {
+}
diff --git a/test/577-profile-foreign-dex/src/Main.java b/test/577-profile-foreign-dex/src/Main.java
new file mode 100644
index 0000000000..0cd85b58e8
--- /dev/null
+++ b/test/577-profile-foreign-dex/src/Main.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+
+public class Main {
+
+ private static final String PROFILE_NAME = "primary.prof";
+ private static final String APP_DIR_PREFIX = "app_dir_";
+ private static final String FOREIGN_DEX_PROFILE_DIR = "foreign-dex";
+ private static final String TEMP_FILE_NAME_PREFIX = "dummy";
+ private static final String TEMP_FILE_NAME_SUFFIX = "-file";
+
+ public static void main(String[] args) throws Exception {
+ File tmpFile = null;
+ File appDir = null;
+ File profileFile = null;
+ File foreignDexProfileDir = null;
+
+ try {
+ // Create the necessary files layout.
+ tmpFile = createTempFile();
+ appDir = new File(tmpFile.getParent(), APP_DIR_PREFIX + tmpFile.getName());
+ appDir.mkdir();
+ foreignDexProfileDir = new File(tmpFile.getParent(), FOREIGN_DEX_PROFILE_DIR);
+ foreignDexProfileDir.mkdir();
+ profileFile = createTempFile();
+
+ String codePath = System.getenv("DEX_LOCATION") + "/577-profile-foreign-dex.jar";
+
+ // Register the app with the runtime
+ VMRuntime.registerAppInfo(profileFile.getPath(), appDir.getPath(),
+ new String[] { codePath }, foreignDexProfileDir.getPath());
+
+ testMarkerForForeignDex(foreignDexProfileDir);
+ testMarkerForCodePath(foreignDexProfileDir);
+ testMarkerForApplicationDexFile(foreignDexProfileDir, appDir);
+ } finally {
+ if (tmpFile != null) {
+ tmpFile.delete();
+ }
+ if (profileFile != null) {
+ profileFile.delete();
+ }
+ if (foreignDexProfileDir != null) {
+ foreignDexProfileDir.delete();
+ }
+ if (appDir != null) {
+ appDir.delete();
+ }
+ }
+ }
+
+ // Verify we actually create a marker on disk for foreign dex files.
+ private static void testMarkerForForeignDex(File foreignDexProfileDir) throws Exception {
+ String foreignDex = System.getenv("DEX_LOCATION") + "/577-profile-foreign-dex-ex.jar";
+ loadDexFile(foreignDex);
+ checkMarker(foreignDexProfileDir, foreignDex, /* exists */ true);
+ }
+
+ // Verify we do not create a marker on disk for dex files path of the code path.
+ private static void testMarkerForCodePath(File foreignDexProfileDir) throws Exception {
+ String codePath = System.getenv("DEX_LOCATION") + "/577-profile-foreign-dex.jar";
+ loadDexFile(codePath);
+ checkMarker(foreignDexProfileDir, codePath, /* exists */ false);
+ }
+
+ private static void testMarkerForApplicationDexFile(File foreignDexProfileDir, File appDir)
+ throws Exception {
+ // Copy the -ex jar to the application directory and load it from there.
+ // This will record duplicate class conflicts but we don't care for this use case.
+ File foreignDex = new File(System.getenv("DEX_LOCATION") + "/577-profile-foreign-dex-ex.jar");
+ File appDex = new File(appDir, "appDex.jar");
+ try {
+ copyFile(foreignDex, appDex);
+
+ loadDexFile(appDex.getAbsolutePath());
+ checkMarker(foreignDexProfileDir, appDex.getAbsolutePath(), /* exists */ false);
+ } finally {
+ if (appDex != null) {
+ appDex.delete();
+ }
+ }
+ }
+
+ private static void checkMarker(File foreignDexProfileDir, String dexFile, boolean exists) {
+ File marker = new File(foreignDexProfileDir, dexFile.replace('/', '@'));
+ boolean result_ok = exists ? marker.exists() : !marker.exists();
+ if (!result_ok) {
+ throw new RuntimeException("Marker test failed for:" + marker.getPath());
+ }
+ }
+
+ private static void loadDexFile(String dexFile) throws Exception {
+ Class pathClassLoader = Class.forName("dalvik.system.PathClassLoader");
+ if (pathClassLoader == null) {
+ throw new RuntimeException("Couldn't find path class loader class");
+ }
+ Constructor constructor =
+ pathClassLoader.getDeclaredConstructor(String.class, ClassLoader.class);
+ constructor.newInstance(
+ dexFile, ClassLoader.getSystemClassLoader());
+ }
+
+ private static class VMRuntime {
+ private static final Method registerAppInfoMethod;
+ static {
+ try {
+ Class c = Class.forName("dalvik.system.VMRuntime");
+ registerAppInfoMethod = c.getDeclaredMethod("registerAppInfo",
+ String.class, String.class, String[].class, String.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static void registerAppInfo(String pkgName, String appDir,
+ String[] codePath, String foreignDexProfileDir) throws Exception {
+ registerAppInfoMethod.invoke(null, pkgName, appDir, codePath, foreignDexProfileDir);
+ }
+ }
+
+ private static void copyFile(File fromFile, File toFile) throws Exception {
+ FileInputStream in = new FileInputStream(fromFile);
+ FileOutputStream out = new FileOutputStream(toFile);
+ try {
+ byte[] buffer = new byte[4096];
+ int bytesRead;
+ while ((bytesRead = in.read(buffer)) >= 0) {
+ out.write(buffer, 0, bytesRead);
+ }
+ } finally {
+ out.flush();
+ try {
+ out.getFD().sync();
+ } catch (IOException e) {
+ }
+ out.close();
+ in.close();
+ }
+ }
+
+ private static File createTempFile() throws Exception {
+ try {
+ return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
+ } catch (IOException e) {
+ System.setProperty("java.io.tmpdir", "/data/local/tmp");
+ try {
+ return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
+ } catch (IOException e2) {
+ System.setProperty("java.io.tmpdir", "/sdcard");
+ return File.createTempFile(TEMP_FILE_NAME_PREFIX, TEMP_FILE_NAME_SUFFIX);
+ }
+ }
+ }
+}
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index c4f0171f0d..7036bdcaf5 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -567,7 +567,9 @@ TEST_ART_BROKEN_OPTIMIZING_READ_BARRIER_RUN_TESTS := \
537-checker-arraycopy
# Tests that should fail in the read barrier configuration with JIT (Optimizing compiler).
-TEST_ART_BROKEN_JIT_READ_BARRIER_RUN_TESTS :=
+# 145: Test sometimes times out in read barrier configuration (b/27467554).
+TEST_ART_BROKEN_JIT_READ_BARRIER_RUN_TESTS := \
+ 145-alloc-tracking-stress
ifeq ($(ART_USE_READ_BARRIER),true)
ifneq (,$(filter interpreter,$(COMPILER_TYPES)))
diff --git a/test/etc/default-build b/test/etc/default-build
index 6e855ec30a..5f78496c3f 100755
--- a/test/etc/default-build
+++ b/test/etc/default-build
@@ -116,28 +116,33 @@ if ! [ "${HAS_SRC}" = "true" ] && ! [ "${HAS_SRC2}" = "true" ]; then
SKIP_DX_MERGER="true"
fi
-if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
- # Jack does not support this configuration unless we specify how to partition the DEX file
- # with a .jpp file.
- USE_JACK="false"
-fi
-
if [ ${USE_JACK} = "true" ]; then
# Jack toolchain
if [ "${HAS_SRC}" = "true" ]; then
- ${JACK} ${JACK_ARGS} --output-jack src.jack src
- imported_jack_files="--import src.jack"
+ if [ "${HAS_SRC_MULTIDEX}" = "true" ]; then
+ # Compile src and src-multidex in the same .jack file. We will apply multidex partitioning
+ # when creating the output .dex file.
+ ${JACK} ${JACK_ARGS} --output-jack src.jack src src src-multidex
+ jack_extra_args="${jack_extra_args} -D jack.dex.output.policy=minimal-multidex"
+ jack_extra_args="${jack_extra_args} -D jack.preprocessor=true"
+ jack_extra_args="${jack_extra_args} -D jack.preprocessor.file=multidex.jpp"
+ else
+ ${JACK} ${JACK_ARGS} --output-jack src.jack src
+ fi
+ jack_extra_args="${jack_extra_args} --import src.jack"
fi
if [ "${HAS_SRC2}" = "true" ]; then
${JACK} ${JACK_ARGS} --output-jack src2.jack src2
- imported_jack_files="--import src2.jack ${imported_jack_files}"
+ # In case of duplicate classes, we want to take into account the classes from src2. Therefore
+ # we apply the 'keep-first' policy and import src2.jack file *before* the src.jack file.
+ jack_extra_args="${jack_extra_args} -D jack.import.type.policy=keep-first"
+ jack_extra_args="--import src2.jack ${jack_extra_args}"
fi
- # Compile jack files into a DEX file. We set jack.import.type.policy=keep-first to consider
- # class definitions from src2 first.
+ # Compile jack files into a DEX file.
if [ "${HAS_SRC}" = "true" ] || [ "${HAS_SRC2}" = "true" ]; then
- ${JACK} ${JACK_ARGS} ${imported_jack_files} -D jack.import.type.policy=keep-first --output-dex .
+ ${JACK} ${JACK_ARGS} ${jack_extra_args} --output-dex .
fi
else
# Legacy toolchain with javac+dx