Merge "Allow use of ellipsis in non-argument positions in Proguard rules"
diff --git a/compatibility-faq.md b/compatibility-faq.md
new file mode 100644
index 0000000..8b15be4
--- /dev/null
+++ b/compatibility-faq.md
@@ -0,0 +1,103 @@
+# R8 compatibility FAQ
+
+R8 uses the same configuration specification language as ProGuard, and tries to
+be compatible with ProGuard. However as R8 has different optimizations it can be
+necessary to change the configuration when switching to R8.
+
+This FAQ collects some of the common issues.
+
+## GSON
+
+### Member in a data object is always `null`
+
+For data classes used for serialization all fields that are used in the
+serialization must be kept by the configuration. R8 can decide to replace
+instances of types that are never instantiated with `null`. So if instances of a
+given class are only created through deserialization from JSON, R8 will not see
+that class as instantiated leaving it as always `null`.
+
+If the `@SerializedName` annotation is used consistently for data classes the
+following keep rule can be used:
+
+```
+-keepclassmembers,allowobfuscation class * {
+ @com.google.gson.annotations.SerializedName <fields>;
+}
+```
+
+This will ensure that all fields annotated with `SerializedName` will be
+kept. These fields can still be renamed during obfuscation as the
+`SerializedName` annotation (not the source field name) controls the name in the
+JSON serialization.
+
+If the `@SerializedName` annotation is _not_ used the following conservative
+rule can be used for each data class:
+
+```
+-keepclassmembers class MyDataClass {
+ !transient <fields>;
+}
+```
+
+This will ensure that all fields are kept and not renamed for these
+classes. Fields with modifier `transient` are never serialized and therefore
+keeping these is not needed.
+
+### Error `java.lang.IllegalArgumentException: class <class name> declares multiple JSON fields named <name>`
+
+This can be caused by obfuscation selecting the same name for private fields in
+several classes in a class hierachy. Consider the following example:
+
+```
+class A {
+ private String fieldInA;
+}
+
+class B extends A {
+ private String fieldInB;
+}
+```
+
+Here R8 can choose to rename both `fieldInA` and `fieldInB` to the same name,
+e.g. `a`. This creates a conflict when GSON is used to either serialize an
+instance of class `B` to JSON or create an instance of class `B` from JSON. If
+the fields should _not_ be serialized they should be marked `transient` so that
+they will be ignored by GSON:
+
+```
+class A {
+ private transient String fieldInA;
+}
+
+class B extends A {
+ private transient String fieldInB;
+}
+```
+
+If the fields _are_ to be serialized, the annotation `SerializedName` can be
+used to fix the `IllegalArgumentException` together the rule to keep fields
+annotated with `SerializedName`
+
+```
+class A {
+ @SerializedName("fieldInA")
+ private String fieldInA;
+}
+
+class B extends A {
+ @SerializedName("fieldInB")
+ private String fieldInB;
+}
+```
+
+```
+-keepclassmembers,allowobfuscation class * {
+ @com.google.gson.annotations.SerializedName <fields>;
+}
+```
+
+
+Both the use of `transient` and the use of the annotation `SerializedName` allow
+the fields to be renamed by R8 to the same name, but GSON serialization will
+work as expected.
+
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg
index 863bbbe..5131b19 100644
--- a/infra/config/global/cr-buildbucket.cfg
+++ b/infra/config/global/cr-buildbucket.cfg
@@ -96,8 +96,7 @@
mixins: "linux"
execution_timeout_secs: 1800 # 1/2h
recipe {
- # TODO(ricow): set archive flag when we flip over
- # properties: "archive:True"
+ properties: "archive:True"
}
}
@@ -192,6 +191,7 @@
builders {
name: "d8-linux-jctf"
mixins: "linux"
+ dimensions: "jctf:true"
execution_timeout_secs: 43200 # 12h
recipe {
properties: "tool:d8"
@@ -202,6 +202,7 @@
builders {
name: "d8-linux-jctf_release"
mixins: "linux"
+ dimensions: "jctf:true"
execution_timeout_secs: 43200 # 12h
recipe {
properties: "tool:d8"
@@ -313,16 +314,21 @@
builders {
name: "linux-internal"
mixins: "linux"
- # TODO(move)
+ recipe {
+ properties: "internal:True"
+ }
}
builders {
name: "linux-internal_release"
mixins: "linux"
- # TODO(move)
+ recipe {
+ properties: "internal:True"
+ }
}
builders {
name: "linux-jctf"
mixins: "linux"
+ dimensions: "jctf:true"
execution_timeout_secs: 43200 # 12h
recipe {
properties: "tool:r8"
@@ -333,6 +339,7 @@
builders {
name: "linux-jctf_release"
mixins: "linux"
+ dimensions: "jctf:true"
execution_timeout_secs: 43200 # 12h
recipe {
properties: "tool:r8"
@@ -343,6 +350,7 @@
builders {
name: "r8cf-linux-jctf"
mixins: "linux"
+ dimensions: "jctf:true"
execution_timeout_secs: 43200 # 12h
recipe {
properties: "tool:r8cf"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg
index a329c9e..8dc59cb 100644
--- a/infra/config/global/luci-milo.cfg
+++ b/infra/config/global/luci-milo.cfg
@@ -193,3 +193,182 @@
# short_name: "win"
# }
}
+
+consoles {
+ id: "main_all"
+ name: "R8 all"
+ repo_url: "https://r8.googlesource.com/r8"
+ refs: "regexp:refs/heads/.*"
+ manifest_name: "REVISION"
+
+ builders {
+ name: "buildbucket/luci.r8.ci/archive"
+ category: "archive"
+ short_name: "archive"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux"
+ category: "R8"
+ short_name: "linux"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-4.0.4"
+ category: "R8"
+ short_name: "4.0.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-4.4.4"
+ category: "R8"
+ short_name: "4.4.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-5.1.1"
+ category: "R8"
+ short_name: "5.1.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-6.0.1"
+ category: "R8"
+ short_name: "6.0.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-7.0.0"
+ category: "R8"
+ short_name: "7.0.0"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-internal"
+ category: "R8"
+ short_name: "internal"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-jctf"
+ category: "R8"
+ short_name: "jctf"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/r8cf-linux-jctf"
+ category: "R8"
+ short_name: "cf-jctf"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux"
+ category: "D8"
+ short_name: "linux"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-4.0.4"
+ category: "D8"
+ short_name: "4.0.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-4.4.4"
+ category: "D8"
+ short_name: "4.4.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-5.1.1"
+ category: "D8"
+ short_name: "5.1.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-6.0.1"
+ category: "D8"
+ short_name: "6.0.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-7.0.0"
+ category: "D8"
+ short_name: "7.0.0"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-jctf"
+ category: "D8"
+ short_name: "jctf"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/windows"
+ category: "win"
+ short_name: "win"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/archive_release"
+ category: "release archive"
+ short_name: "archive"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux_release"
+ category: "R8 release"
+ short_name: "linux"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-4.0.4_release"
+ category: "R8 release"
+ short_name: "4.0.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-4.4.4_release"
+ category: "R8 release"
+ short_name: "4.4.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-5.1.1_release"
+ category: "R8 release"
+ short_name: "5.1.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-6.0.1_release"
+ category: "R8 release"
+ short_name: "6.0.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-android-7.0.0_release"
+ category: "R8 release"
+ short_name: "7.0.0"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-internal_release"
+ category: "R8 release"
+ short_name: "internal"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/linux-jctf_release"
+ category: "R8 release"
+ short_name: "jctf"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux_release"
+ category: "D8 release"
+ short_name: "Linux"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-4.0.4_release"
+ category: "D8 release"
+ short_name: "4.0.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-4.4.4_release"
+ category: "D8 release"
+ short_name: "4.4.4"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-5.1.1_release"
+ category: "D8 release"
+ short_name: "5.1.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-6.0.1_release"
+ category: "D8 release"
+ short_name: "6.0.1"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-android-7.0.0_release"
+ category: "D8 release"
+ short_name: "7.0.0"
+ }
+ builders {
+ name: "buildbucket/luci.r8.ci/d8-linux-jctf_release"
+ category: "D8 release"
+ short_name: "jctf"
+ }
+}
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg
index 7c867e5..2b67476 100644
--- a/infra/config/global/luci-scheduler.cfg
+++ b/infra/config/global/luci-scheduler.cfg
@@ -23,7 +23,7 @@
repo: "https://r8.googlesource.com/r8"
refs: "refs/heads/master"
}
-
+ triggers: "archive"
triggers: "d8-linux"
triggers: "d8-linux"
triggers: "d8-linux-android-4.0.4"
@@ -39,13 +39,10 @@
triggers: "linux-android-5.1.1"
triggers: "linux-android-6.0.1"
triggers: "linux-android-7.0.0"
+ triggers: "linux-internal"
+ triggers: "linux-jctf"
+ triggers: "r8cf-linux-jctf"
triggers: "windows"
- triggers: "archive"
-
- # TODO(ricow): enable remaining
- # triggers: "linux-internal"
- # triggers: "linux-jctf"
- # triggers: "r8cf-linux-jctf"
}
trigger {
@@ -55,28 +52,23 @@
repo: "https://r8.googlesource.com/r8"
refs: "regexp:refs/heads/d8.*"
}
+ triggers: "archive_release"
triggers: "d8-linux-android-4.0.4_release"
triggers: "d8-linux-android-4.4.4_release"
triggers: "d8-linux-android-5.1.1_release"
triggers: "d8-linux-android-6.0.1_release"
triggers: "d8-linux-android-7.0.0_release"
+ triggers: "d8-linux-jctf_release"
triggers: "d8-linux_release"
triggers: "linux-android-4.0.4_release"
triggers: "linux-android-4.4.4_release"
triggers: "linux-android-5.1.1_release"
triggers: "linux-android-6.0.1_release"
triggers: "linux-android-7.0.0_release"
+ triggers: "linux-internal_release"
+ triggers: "linux-jctf_release"
triggers: "linux_release"
-
- # TODO(ricow): enable remaining
- # triggers: "archive_release"
- # triggers: "d8-linux-jctf_release"
- # triggers: "linux-internal_release"
- # triggers: "linux-jctf_release"
-
- # TODO(ricow): Windows on the release branches currently do not work
- # There is no java available.
- # triggers: "windows_release"
+ triggers: "windows_release"
}
job {
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index b591bab..a89ff39 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -23,7 +23,7 @@
this.content = content;
}
- public DexString(String string) {
+ DexString(String string) {
this.size = string.length();
this.content = encodeToMutf8(string);
}
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineStaticInterfaceMethodTest.java b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineStaticInterfaceMethodTest.java
new file mode 100644
index 0000000..af29bc7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/inliner/InlineStaticInterfaceMethodTest.java
@@ -0,0 +1,53 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.inliner;
+
+import static com.android.tools.r8.ir.desugar.InterfaceMethodRewriter.COMPANION_CLASS_NAME_SUFFIX;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.StringUtils;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import org.junit.Test;
+
+public class InlineStaticInterfaceMethodTest extends TestBase {
+
+ @Test
+ public void test() throws Exception {
+ String expectedOutput = StringUtils.lines("Hello world!");
+
+ CodeInspector inspector =
+ testForR8(Backend.DEX)
+ .addInnerClasses(InlineStaticInterfaceMethodTest.class)
+ .addKeepMainRule(TestClass.class)
+ .setMinApi(AndroidApiLevel.M)
+ .run(TestClass.class)
+ .assertSuccessWithOutput(expectedOutput)
+ .inspector();
+
+ // TODO(b/124017330): greet() should have been inlined into main().
+ ClassSubject classSubject =
+ inspector.clazz(I.class.getTypeName() + COMPANION_CLASS_NAME_SUFFIX);
+ assertThat(classSubject, isPresent());
+ assertThat(classSubject.uniqueMethodWithName("greet"), isPresent());
+ }
+
+ static class TestClass {
+
+ public static void main(String[] args) {
+ I.greet();
+ }
+ }
+
+ interface I {
+
+ static void greet() {
+ System.out.println("Hello world!");
+ }
+ }
+}
diff --git a/third_party/android_sdk.tar.gz.sha1 b/third_party/android_sdk.tar.gz.sha1
index ebc2c1d..9a9b464 100644
--- a/third_party/android_sdk.tar.gz.sha1
+++ b/third_party/android_sdk.tar.gz.sha1
@@ -1 +1 @@
-fdbcfa08e6a1772bc9569bf706819a95a15bc3a0
\ No newline at end of file
+acfc4d8ff4def954eb85da4bd5fff3a63764c09d
\ No newline at end of file
diff --git a/tools/archive.py b/tools/archive.py
index f86530a..c842c69 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -26,6 +26,7 @@
return result.parse_args()
def GetToolVersion(jar_path):
+ # TODO(mkroghj) This would not work for r8-lib, maybe use utils.getR8Version.
output = subprocess.check_output([
jdk.GetJavaExecutable(), '-jar', jar_path, '--version'
])
@@ -94,8 +95,8 @@
if not utils.is_bot() and not options.dry_run:
raise Exception('You are not a bot, don\'t archive builds')
- if utils.is_new_bot():
- print("Archiving is disabled on new bots.")
+ if utils.is_old_bot():
+ print("Archiving is disabled on old bots.")
return
# Create maven release which uses a build that exclude dependencies.
@@ -135,7 +136,7 @@
with open(version_file,'w') as version_writer:
version_writer.write('version.sha=' + GetGitHash() + '\n')
version_writer.write(
- 'releaser=go/r8bot (' + os.environ.get('BUILDBOT_SLAVENAME') + ')\n')
+ 'releaser=go/r8bot (' + os.environ.get('SWARMING_BOT_ID') + ')\n')
version_writer.write('version-file.version.code=1\n')
for file in [
diff --git a/tools/internal_test.py b/tools/internal_test.py
index a9a90eb..032f1fe 100755
--- a/tools/internal_test.py
+++ b/tools/internal_test.py
@@ -193,6 +193,9 @@
print('\n\n%s had value:\n%s' % (to_print, value))
def run_bot():
+ if utils.is_old_bot():
+ print('Not running on on old bot, please see: https://ci.chromium.org/p/r8')
+ return
print_magic_file_state()
# Ensure that there is nothing currently scheduled (broken/stopped run)
for magic in ALL_MAGIC:
diff --git a/tools/run_on_as_app.py b/tools/run_on_as_app.py
index fef337a..d95453f 100755
--- a/tools/run_on_as_app.py
+++ b/tools/run_on_as_app.py
@@ -198,12 +198,15 @@
assert len(lines) >= 1
return lines[-1]
-def CheckIsBuiltWithExpectedR8(apk, temp_dir, options):
+def CheckIsBuiltWithExpectedR8(apk, temp_dir, shrinker, options):
marker = ExtractMarker(apk, temp_dir, options)
expected_version = (
options.version
if options.version
- else create_maven_release.determine_version())
+ else utils.getR8Version(
+ os.path.join(
+ temp_dir,
+ 'r8lib.jar' if IsMinifiedR8(shrinker) else 'r8.jar')))
if marker.startswith('~~R8'):
actual_version = json.loads(marker[4:]).get('version')
if actual_version == expected_version:
@@ -509,7 +512,7 @@
as_utils.MoveFile(unsigned_apk, apk_dest, quiet=options.quiet)
assert ('r8' not in shrinker
- or CheckIsBuiltWithExpectedR8(apk_dest, temp_dir, options))
+ or CheckIsBuiltWithExpectedR8(apk_dest, temp_dir, shrinker, options))
profile_dest_dir = os.path.join(out_dir, 'profile')
as_utils.MoveProfileReportTo(profile_dest_dir, stdout, quiet=options.quiet)
diff --git a/tools/test.py b/tools/test.py
index d6753ed..a7e0b98 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -253,6 +253,10 @@
# Now run tests on selected runtime(s).
vms_to_test = [options.dex_vm] if options.dex_vm != "all" else ALL_ART_VMS
+ # TODO(126683699): remove once we have single run
+ if options.dex_vm == 'all' and options.only_jctf:
+ vms_to_test = ["default", "5.1.1"]
+
for art_vm in vms_to_test:
vm_kind_to_test = "_" + options.dex_vm_kind if art_vm != "default" else ""
return_code = gradle.RunGradle(gradle_args + ['-Pdex_vm=%s' % (art_vm + vm_kind_to_test)],
diff --git a/tools/utils.py b/tools/utils.py
index 12535be..8c168a6 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -488,8 +488,18 @@
def is_new_bot():
return 'SWARMING_BOT_ID' in os.environ
+def is_old_bot():
+ return 'BUILDBOT_SLAVENAME' in os.environ
+
def is_bot():
return 'USER' in os.environ and os.environ['USER'] == 'chrome-bot'
def uncompressed_size(path):
return sum(z.file_size for z in zipfile.ZipFile(path).infolist())
+
+def getR8Version(path):
+ cmd = [jdk.GetJavaExecutable(), '-cp', path, 'com.android.tools.r8.R8',
+ '--version']
+ output = subprocess.check_output(cmd, stderr = subprocess.STDOUT)
+ # output is on form 'R8 <version>' so we just strip of 'R8 '.
+ return output.splitlines()[0][3:]
diff --git a/tools/windows/README.dx b/tools/windows/README.dx
index 4d93487..c9f4c54 100644
--- a/tools/windows/README.dx
+++ b/tools/windows/README.dx
@@ -4,6 +4,8 @@
is removed and replaced by a direct reference to it.
This is done because this relies on a tool found in the SDK and not present in the
current package.
+Also, the deprecated java.ext.dirs argument has been removed.
+
Diff:
26,29c26,29
@@ -19,7 +21,7 @@
87c87
< call "%java_exe%" %javaOpts% -Djava.ext.dirs="%frameworkdir%" -jar "%jarpath%" %params%
---
-> call java %javaOpts% -Djava.ext.dirs="%frameworkdir%" -jar "%jarpath%" %params%
+> call java %javaOpts% -jar "%jarpath%" %params%
dexmerger.bat has been copied from dx.bat, and the command line has been updated
according to the SDK dexmerger bash script to call the right class.
\ No newline at end of file
diff --git a/tools/windows/dx.tar.gz.sha1 b/tools/windows/dx.tar.gz.sha1
index 867adab..46c3ee8 100644
--- a/tools/windows/dx.tar.gz.sha1
+++ b/tools/windows/dx.tar.gz.sha1
@@ -1 +1 @@
-47414f7ebc8a8cc14b29fc6732510a20947870aa
\ No newline at end of file
+42495c1c7914814e4cfe7f3c199fbbac6711c37e
\ No newline at end of file