diff options
author | Alex Humesky <ahumesky@google.com> | 2023-08-22 12:49:29 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-08-22 12:49:59 -0700 |
commit | b79878d71688baff303a9a2ee4218d5505ccf4e2 (patch) | |
tree | 32105c0dd0e10037435ccb2b05f23b6378f4853e /test | |
parent | 7b2db559b0974ac8e27ad3e1ad1d9ac09654e01f (diff) | |
download | bazelbuild-rules_android-b79878d71688baff303a9a2ee4218d5505ccf4e2.tar.gz |
Add R8 integration to the Starlark Bazel Android rules.
https://github.com/bazelbuild/bazel/issues/18239
https://github.com/bazelbuild/rules_android/issues/31
https://github.com/bazelbuild/rules_android/issues/105
PiperOrigin-RevId: 559196543
Change-Id: Id2a6aea5079a14f305ca48d79d292b166677befa
Diffstat (limited to 'test')
16 files changed, 381 insertions, 0 deletions
diff --git a/test/rules/android_binary_internal/r8_integration/BUILD b/test/rules/android_binary_internal/r8_integration/BUILD new file mode 100644 index 0000000..fcefaeb --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/BUILD @@ -0,0 +1,12 @@ +load("@rules_python//python:py_test.bzl", "py_test") + +py_test( + name = "r8_integration_test", + srcs = ["r8_integration_test.py"], + data = [ + "//test/rules/android_binary_internal/r8_integration/java/com/basicapp:basic_app_R8_no_shrink", + "//test/rules/android_binary_internal/r8_integration/java/com/basicapp:basic_app_R8_shrink", + "//test/rules/android_binary_internal/r8_integration/java/com/basicapp:basic_app_no_R8", + "@androidsdk-supplemental//:dexdump", + ], +) diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml new file mode 100644 index 0000000..8d9cc4a --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.basicapp" > + + <uses-sdk + android:minSdkVersion="27" + android:targetSdkVersion="30" /> + + <application + android:allowBackup="true" + android:label="@string/app_name" + android:taskAffinity="" > + <activity + android:name="com.basicapp.BasicActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml new file mode 100644 index 0000000..f661d59 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.basicapp" > + + <uses-sdk + android:minSdkVersion="27" + android:targetSdkVersion="30" /> + +</manifest> diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD new file mode 100644 index 0000000..4727887 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD @@ -0,0 +1,56 @@ +load("//rules:rules.bzl", "android_binary", "android_library") + +[ + android_binary( + name = name, + srcs = ["BasicActivity.java"], + manifest = "AndroidManifest.xml", + min_sdk_version = 27, + proguard_specs = specs, + resource_files = glob(["res/**"]), + shrink_resources = shrink, + visibility = ["//test/rules/android_binary_internal/r8_integration:__pkg__"], + deps = [ + ":basic_lib", + ":lib_with_specs", + ], + # Work around --java_runtime_version=17 and --java_language_version=11 + # set in the presubmit tests. + javacopts = ["-target", "8", "-source", "8"], + ) + for name, specs, shrink in [ + ( + "basic_app_R8_shrink", + ["proguard.cfg"], + True, + ), + ( + "basic_app_R8_no_shrink", + ["proguard.cfg"], + False, + ), + ("basic_app_no_R8", [], False), + ] +] + +android_library( + name = "basic_lib", + srcs = ["UnusedActivity.java"], + manifest = "AndroidManifest_lib.xml", + resource_files = glob(["res_lib/**"]), +) + +android_library( + name = "lib_with_specs", + srcs = ["LibWithSpecsActivity.java"], + manifest = "AndroidManifest_lib.xml", + proguard_specs = ["lib_proguard.cfg"], + deps = [":lib2_with_specs"], +) + +android_library( + name = "lib2_with_specs", + srcs = ["Lib2WithSpecsActivity.java"], + manifest = "AndroidManifest_lib.xml", + proguard_specs = ["lib2_proguard.cfg"], +) diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java new file mode 100644 index 0000000..4aee8d1 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java @@ -0,0 +1,49 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// 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. + +package com.basicapp; + +import android.app.Activity; +import android.os.Bundle; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; + +/** The main activity of the Basic Sample App. */ +public class BasicActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.basic_activity); + + final Button buttons[] = { + findViewById(R.id.button_id_fizz), findViewById(R.id.button_id_buzz), + }; + + for (Button b : buttons) { + b.setOnClickListener( + new View.OnClickListener() { + public void onClick(View v) { + TextView tv = findViewById(R.id.text_hello); + if (v.getId() == R.id.button_id_fizz) { + tv.setText("fizz"); + } else if (v.getId() == R.id.button_id_buzz) { + tv.setText("buzz"); + } + } + }); + } + } +} diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java new file mode 100644 index 0000000..57d613f --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java @@ -0,0 +1,29 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// 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. + +package com.basicapp; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +/** The main activity of the Basic Sample App. */ +public class Lib2WithSpecsActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.i("TAG", "onCreate"); + } +} diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java new file mode 100644 index 0000000..b40be64 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java @@ -0,0 +1,29 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// 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. + +package com.basicapp; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +/** The main activity of the Basic Sample App. */ +public class LibWithSpecsActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.i("TAG", "onCreate"); + } +} diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java new file mode 100644 index 0000000..e188f87 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java @@ -0,0 +1,30 @@ +// Copyright 2023 The Bazel Authors. All rights reserved. +// +// 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. + +package com.basicapp; + +import android.app.Activity; +import android.os.Bundle; +import android.util.Log; + +/** The main activity of the Basic Sample App. */ +public class UnusedActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.unused_activity); + Log.i("TAG", "onCreate"); + } +} diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg new file mode 100644 index 0000000..3fddc01 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg @@ -0,0 +1 @@ +-keep class com.basicapp.Lib2WithSpecsActivity
\ No newline at end of file diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg new file mode 100644 index 0000000..e0ef7ce --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg @@ -0,0 +1,2 @@ +# proguard specs +-dontobfuscate diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml new file mode 100644 index 0000000..f84199c --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml @@ -0,0 +1,23 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/text_hello" + android:text="@string/hello_world" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + + <Button + android:id="@+id/button_id_fizz" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="fizz" /> + <Button + android:id="@+id/button_id_buzz" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="buzz" /> + +</LinearLayout> diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml new file mode 100644 index 0000000..565c987 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="app_name" translatable="false">basicapp</string> + <string name="hello_world" translatable="false">Hello world!</string> + <string name="action_settings" translatable="false">Settings</string> + +</resources> diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml new file mode 100644 index 0000000..61fb73e --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml @@ -0,0 +1,12 @@ +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + <TextView + android:id="@+id/text_hello" + android:text="@string/hello_world" + android:layout_width="wrap_content" + android:layout_height="wrap_content" /> + +</LinearLayout> diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml new file mode 100644 index 0000000..79934a2 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + + <string name="app_name" translatable="false">basicapp</string> + <string name="hello_world" translatable="false">Hello world! unused</string> + <string name="action_settings" translatable="false">Settings</string> + +</resources> diff --git a/test/rules/android_binary_internal/r8_integration/r8_integration_test.py b/test/rules/android_binary_internal/r8_integration/r8_integration_test.py new file mode 100755 index 0000000..b9ba7e2 --- /dev/null +++ b/test/rules/android_binary_internal/r8_integration/r8_integration_test.py @@ -0,0 +1,91 @@ +# Copyright 2023 The Bazel Authors. All rights reserved. +# +# 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 os +import subprocess +import unittest +import zipfile + + +class R8IntegrationTest(unittest.TestCase): + """Tests Bazel's R8 integration.""" + + def _r8_integration_check( + self, apk, expect_unused_activity_resource, expect_unused_activity_class + ): + tmp = os.environ["TEST_TMPDIR"] + apk_directory = ( + "test/rules/android_binary_internal/r8_integration/java/com/basicapp" + ) + apk_tmp = os.path.join(tmp, apk) + classes_dex = os.path.join(apk_tmp, "classes.dex") + with zipfile.ZipFile(os.path.join(apk_directory, apk)) as zf: + apk_files = zf.namelist() + zf.extract("classes.dex", apk_tmp) + + self.assertEqual( + expect_unused_activity_resource, + "res/layout/unused_activity.xml" in apk_files, + ) + + build_tools_dir = "external/androidsdk-supplemental/build-tools" + build_tools_version = os.listdir(build_tools_dir)[0] + dexdump = os.path.join(build_tools_dir, build_tools_version, "dexdump") + + dexdump_proc = subprocess.run( + [dexdump, classes_dex], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + check=True, + ) + dexdump_stdout = str(dexdump_proc.stdout) + self.assertEqual( + expect_unused_activity_class, + "Class descriptor : 'Lcom/basicapp/UnusedActivity;'" in dexdump_stdout, + ) + + # In all cases, the Lib2WithSpecsActivity class should be in the app, + # since lib2_proguard.cfg (an indirect dependency) specifies to keep it. + self.assertIn( + "Class descriptor : 'Lcom/basicapp/Lib2WithSpecsActivity;'", + dexdump_stdout, + ) + + def test_r8_integration(self): + # No R8, so unused resources and unused classes should be in the app + self._r8_integration_check( + "basic_app_no_R8.apk", + expect_unused_activity_resource=True, + expect_unused_activity_class=True, + ) + + # Run R8, don't shrink, so unused class should not be in the app but unused + # resource should remain. + self._r8_integration_check( + "basic_app_R8_no_shrink.apk", + expect_unused_activity_resource=True, + expect_unused_activity_class=False, + ) + + # Run R8 and shrinkings, so unused classes and resources should not be in + # the app. + self._r8_integration_check( + "basic_app_R8_shrink.apk", + expect_unused_activity_resource=False, + expect_unused_activity_class=False, + ) + + +if __name__ == "__main__": + unittest.main() |