Implement R8's config analyzer as an output group option. https://github.com/bazelbuild/rules_android/issues/542 PiperOrigin-RevId: 976008760 Change-Id: Ifaea5ec11e444492d69f325d7b3d025529a7a112
diff --git a/providers/providers.bzl b/providers/providers.bzl index 45f88b7..e62b3ca 100644 --- a/providers/providers.bzl +++ b/providers/providers.bzl
@@ -224,6 +224,7 @@ fields = dict( d8_optimization_info = "Metadata produced by D8 about the applied optimizations in a JSON format.", r8_optimization_info = "Metadata produced by R8 about the applied optimizations in a JSON format.", + optimization_analysis_report = "HTML report produced by the optimization configuration analyzer.", ), )
diff --git a/rules/android_application/android_application_rule.bzl b/rules/android_application/android_application_rule.bzl index eda37ed..76fc8b8 100644 --- a/rules/android_application/android_application_rule.bzl +++ b/rules/android_application/android_application_rule.bzl
@@ -375,7 +375,7 @@ is_executable = True, ) - return [ + providers = [ ctx.attr.base_module[ApkInfo], ctx.attr.base_module[AndroidPreDexJarInfo], AndroidBundleInfo(unsigned_aab = ctx.outputs.unsigned_aab), @@ -388,6 +388,12 @@ ), ] + # Pass through AndroidOptimizationInfo from base module, if optimization analysis was performed. + if AndroidOptimizationInfo in ctx.attr.base_module: + providers.append(ctx.attr.base_module[AndroidOptimizationInfo]) + + return providers + android_application = rule( attrs = ANDROID_APPLICATION_ATTRS, cfg = android_platforms_transition,
diff --git a/rules/android_binary/impl.bzl b/rules/android_binary/impl.bzl index ab79f58..841c8ed 100644 --- a/rules/android_binary/impl.bzl +++ b/rules/android_binary/impl.bzl
@@ -401,8 +401,13 @@ ) providers.append(AndroidPreDexJarInfo(pre_dex_jar = binary_jar)) - if build_metadata_output != None: - providers.append(AndroidOptimizationInfo(d8_optimization_info = build_metadata_output)) + if build_metadata_output != None or optimize_ctx.html_report != None: + providers.append( + AndroidOptimizationInfo( + d8_optimization_info = build_metadata_output, + optimization_analysis_report = optimize_ctx.html_report, + ), + ) if postprocessing_output_map: providers.append(ProguardMappingInfo(proguard_mapping = postprocessing_output_map)) @@ -719,7 +724,10 @@ return ProviderInfo( name = "optimize_ctx", value = struct( - proguard_output = proguard.create_empty_proguard_output(ctx, proguard_output_jar), + proguard_output = proguard.create_empty_proguard_output( + ctx, + proguard_output_jar = proguard_output_jar, + ), resources_apk = None, providers = [], ), @@ -776,7 +784,7 @@ else: proguard_output_jar = ctx.actions.declare_file(ctx.label.name + "_proguard.jar") proguard_output_config = ctx.actions.declare_file(ctx.label.name + "_proguard.config") - proguard_seeds = ctx.actions.declare_file(ctx.label.name + "_proguard.seeds") + keep_radius = ctx.actions.declare_file(ctx.label.name + "_keep_radius.pb") proguard_usage = ctx.actions.declare_file(ctx.label.name + "_proguard.usage") proguard_why_keeping_file = ctx.actions.declare_file(ctx.label.name + "_proguard.why_keeping") @@ -815,7 +823,7 @@ proguard_output_config = proguard_output_config, proguard_mapping = ctx.file.proguard_apply_mapping, proguard_output_map = proguard_output_map, - proguard_seeds = proguard_seeds, + keep_radius = keep_radius, proguard_usage = proguard_usage, proguard_why_keeping_file = proguard_why_keeping_file, startup_profile = startup_profile, @@ -830,7 +838,7 @@ [ proguard_output.output_jar, proguard_output.config, - proguard_output.seeds, + proguard_output.keep_radius, proguard_output.usage, proguard_output.why_keeping_file, ], @@ -881,6 +889,18 @@ if not optimized_resources_apk and enable_resource_shrinking: optimized_resources_apk = shrunk_resource_output.resources_apk + report_generator = getattr(get_android_toolchain(ctx), "optimization_config_analyzer_generator", None) + html_report = None + if proguard_output.keep_radius and report_generator: + html_report = ctx.actions.declare_file(ctx.label.name + "_optimization_report.html") + proguard.generate_report( + ctx, + out = html_report, + keep_radius = proguard_output.keep_radius, + generator_tool = report_generator.files_to_run, + toolchain_type = ANDROID_TOOLCHAIN_TYPE, + ) + return ProviderInfo( name = "optimize_ctx", value = struct( @@ -888,6 +908,10 @@ resources_apk = optimized_resources_apk, providers = [], implicit_outputs = implicit_outputs, + html_report = html_report, + output_groups = { + "optimization_config_analyzer": depset([html_report]) if html_report else depset(), + }, ), )
diff --git a/rules/android_binary/r8.bzl b/rules/android_binary/r8.bzl index a5814a2..f2d7193 100644 --- a/rules/android_binary/r8.bzl +++ b/rules/android_binary/r8.bzl
@@ -80,6 +80,7 @@ dexes_zip = ctx.actions.declare_file(ctx.label.name + "_dexes.zip") proguard_mappings_output_file = ctx.actions.declare_file(ctx.label.name + "_proguard.map") build_metadata_output = ctx.actions.declare_file(ctx.label.name + "_r8_optimization_info.json") + keep_radius = ctx.actions.declare_file(ctx.label.name + "_keep_radius.pb") android_jar = get_android_sdk(ctx).android_jar proguard_specs = proguard.get_proguard_specs(ctx, packaged_resources_ctx.resource_proguard_config) @@ -141,9 +142,17 @@ executable = get_android_toolchain(ctx).r8.files_to_run, arguments = [args], inputs = depset(r8_inputs, transitive = [neverlink_jars]), - outputs = [dexes_zip, proguard_mappings_output_file, build_metadata_output], + outputs = [ + dexes_zip, + proguard_mappings_output_file, + build_metadata_output, + keep_radius, + ], mnemonic = "AndroidR8", - jvm_flags = ["-Xmx8G"], + jvm_flags = [ + "-Xmx8G", + "-Dcom.android.tools.r8.dumpkeepradiustofile=" + keep_radius.path, + ], progress_message = "R8 Optimizing, Desugaring, and Dexing %{label}", ) @@ -183,16 +192,35 @@ java_resource_jar = java_resource_jar, ) + report_generator = getattr(get_android_toolchain(ctx), "optimization_config_analyzer_generator", None) + html_report = None + if report_generator: + html_report = ctx.actions.declare_file(ctx.label.name + "_optimization_report.html") + proguard.generate_report( + ctx, + out = html_report, + keep_radius = keep_radius, + generator_tool = report_generator.files_to_run, + toolchain_type = ANDROID_TOOLCHAIN_TYPE, + ) + return ProviderInfo( name = "r8_ctx", value = struct( final_classes_dex_zip = final_classes_dex_zip, dex_info = android_dex_info, implicit_outputs = [proguard_mappings_output_file], + html_report = html_report, + output_groups = { + "optimization_config_analyzer": depset([html_report]) if html_report else depset(), + }, providers = [ android_dex_info, AndroidPreDexJarInfo(pre_dex_jar = deploy_jar), - AndroidOptimizationInfo(r8_optimization_info = build_metadata_output), + AndroidOptimizationInfo( + r8_optimization_info = build_metadata_output, + optimization_analysis_report = html_report, + ), ], ), )
diff --git a/rules/proguard.bzl b/rules/proguard.bzl index 08146a3..774901c 100644 --- a/rules/proguard.bzl +++ b/rules/proguard.bzl
@@ -180,7 +180,7 @@ proguard_specs, proguard_mapping = None, proguard_output_map = None, - proguard_seeds = None, + keep_radius = None, proguard_usage = None, proguard_why_keeping_file = None, proguard_config_output = None, @@ -219,8 +219,8 @@ generated by proguard_generate_mapping to be re-used to apply the same map to a new build. proguard_output_map: File. Optional file to be used to write the output map of obfuscated class and member names. - proguard_seeds: File. Optional file used to write the "seeds", which is a list of all - classes and members which match a keep rule. + keep_radius: File. Optional file used to write the "keep radius" proto, which is a mapping of + keep rules to their kept classes and members. proguard_usage: File. Optional file used to write all classes and members that are removed during shrinking (i.e. unused code). proguard_why_keeping_file: File. Optional file used to write whyareyoukeeping relationship graph. @@ -276,9 +276,9 @@ args.add("-printmapping", proguard_output_map) outputs.append(proguard_output_map) - if proguard_seeds: - args.add("-printseeds", proguard_seeds) - outputs.append(proguard_seeds) + if keep_radius: + args.add("-printseeds", keep_radius) + outputs.append(keep_radius) if proguard_usage: args.add("-printusage", proguard_usage) @@ -356,7 +356,7 @@ proguard_output_jar, proguard_output_config = None, proguard_output_map = None, - proguard_seeds = None, + keep_radius = None, proguard_usage = None, proguard_why_keeping_file = None): """ Creates empty proguard outputs. @@ -370,7 +370,7 @@ proguard_output_jar: File. The output optimized jar. proguard_output_config: File. The output proguard config. proguard_output_map: File. The output proguard map. - proguard_seeds: File. The output proguard seeds. + keep_radius: File. The output keep radius proto. proguard_usage: File. The output proguard usage. proguard_why_keeping_file: File. Optional file used to write whyareyoukeeping relationship graph. @@ -382,7 +382,7 @@ ctx, proguard_output_jar = proguard_output_jar, proguard_output_config = proguard_output_config, - proguard_seeds = proguard_seeds, + keep_radius = keep_radius, proguard_usage = proguard_usage, proguard_why_keeping_file = proguard_why_keeping_file, proguard_output_map = proguard_output_map, @@ -400,7 +400,7 @@ outputs.output_jar, outputs.mapping, outputs.config, - outputs.seeds, + outputs.keep_radius, outputs.usage, outputs.why_keeping_file, ) @@ -415,7 +415,7 @@ proguard_output_jar = None, proguard_output_config = None, proguard_output_map = None, - proguard_seeds = None, + keep_radius = None, proguard_usage = None, proguard_why_keeping_file = None, startup_profile = None, @@ -434,7 +434,7 @@ proguard_output_jar: File. The output optimized jar. proguard_output_config: File. The output proguard config. proguard_output_map: File. The output proguard map. - proguard_seeds: File. The output proguard seeds. + keep_radius: File. The output keep radius proto. proguard_usage: File. The output proguard usage. proguard_why_keeping_file: File. Optional file used to write whyareyoukeeping relationship graph. startup_profile: File. The input merged startup profile to be optimized. @@ -452,7 +452,7 @@ proguard_output_jar, proguard_output_config, proguard_output_map, - proguard_seeds, + keep_radius, proguard_usage, proguard_why_keeping_file, ) @@ -468,7 +468,7 @@ return _create_optimization_actions( ctx, proguard_specs, - proguard_seeds, + keep_radius, proguard_usage, proguard_why_keeping_file, proguard_mapping, @@ -490,7 +490,7 @@ ctx, proguard_output_jar, proguard_output_config, - proguard_seeds, + keep_radius, proguard_usage, proguard_why_keeping_file, proguard_output_map, @@ -510,7 +510,7 @@ output_jar = proguard_output_jar, mapping = proguard_output_map, proto_mapping = proguard_output_proto_map, - seeds = proguard_seeds, + keep_radius = keep_radius, usage = proguard_usage, why_keeping_file = proguard_why_keeping_file, library_jar = combined_library_jar, @@ -523,7 +523,7 @@ def _create_optimization_actions( ctx, proguard_specs = None, - proguard_seeds = None, + keep_radius = None, proguard_usage = None, proguard_why_keeping_file = None, proguard_mapping = None, @@ -575,7 +575,7 @@ ctx, proguard_output_jar, proguard_output_config, - proguard_seeds, + keep_radius, proguard_usage, proguard_why_keeping_file, proguard_output_map, @@ -599,7 +599,7 @@ proguard_specs, proguard_mapping = proguard_mapping, proguard_output_map = outputs.mapping, - proguard_seeds = outputs.seeds, + keep_radius = outputs.keep_radius, proguard_usage = outputs.usage, proguard_why_keeping_file = outputs.why_keeping_file, proguard_config_output = outputs.config, @@ -630,7 +630,7 @@ proguard_specs, proguard_mapping = proguard_mapping, proguard_output_map = None, - proguard_seeds = outputs.seeds, + keep_radius = outputs.keep_radius, proguard_usage = None, proguard_why_keeping_file = None, proguard_config_output = None, @@ -703,7 +703,7 @@ proguard_specs, proguard_mapping = proguard_mapping, proguard_output_map = outputs.mapping, - proguard_seeds = None, + keep_radius = None, proguard_usage = outputs.usage, proguard_why_keeping_file = outputs.why_keeping_file, proguard_config_output = outputs.config, @@ -784,9 +784,30 @@ command = "echo \"Unable to run proguard without \\`proguard_specs\\`\"; exit 1;", ) +def _generate_report( + ctx, + out, + keep_radius, + generator_tool, + toolchain_type = None): + args = ctx.actions.args() + args.add(keep_radius) + args.add(out) + + ctx.actions.run( + outputs = [out], + inputs = [keep_radius], + executable = generator_tool, + arguments = [args], + mnemonic = "GenerateOptimizationReport", + progress_message = "Generating optimization report for %s" % ctx.label, + toolchain = toolchain_type, + ) + proguard = struct( apply_proguard = _apply_proguard, create_empty_proguard_output = _create_empty_proguard_output, + generate_report = _generate_report, process_specs = _process_specs, generate_min_sdk_version_assumevalues = _generate_min_sdk_version_assumevalues, get_proguard_specs = _get_proguard_specs,
diff --git a/test/rules/android_binary/r8_integration/BUILD b/test/rules/android_binary/r8_integration/BUILD index 7e444a5..63a2a72 100644 --- a/test/rules/android_binary/r8_integration/BUILD +++ b/test/rules/android_binary/r8_integration/BUILD
@@ -66,3 +66,14 @@ "@rules_shell//shell/runfiles", ], ) + +filegroup( + name = "optimization_config_analyzer_report", + srcs = ["//test/rules/android_binary/r8_integration/java/com/basicapp:basic_app_R8_shrink"], + output_group = "optimization_config_analyzer", +) + +build_test( + name = "optimization_config_analyzer_report_test", + targets = [":optimization_config_analyzer_report"], +)
diff --git a/toolchains/android/toolchain.bzl b/toolchains/android/toolchain.bzl index ce8b61c..bf06e5b 100644 --- a/toolchains/android/toolchain.bzl +++ b/toolchains/android/toolchain.bzl
@@ -215,6 +215,12 @@ default = "@bazel_tools//tools/jdk:proguard_whitelister", executable = True, ), + optimization_config_analyzer_generator = attr.label( + cfg = "exec", + default = "//tools/android:keep_radius_html_report_generator", + executable = True, + allow_files = True, + ), profgen = attr.label( default = "@androidsdk//:fail", cfg = "exec",
diff --git a/tools/android/BUILD b/tools/android/BUILD index 4aa929d..467ba3e 100644 --- a/tools/android/BUILD +++ b/tools/android/BUILD
@@ -284,6 +284,14 @@ ) java_binary( + name = "keep_radius_html_report_generator", + jvm_flags = _JVM_FLAGS, + main_class = "com.android.tools.r8.keepradius.KeepRadiusHtmlReportGenerator", + visibility = ["//visibility:public"], + runtime_deps = ["@rules_android_maven//:com_android_tools_r8"], +) + +java_binary( name = "resource_shrinker", main_class = "com.android.build.shrinker.ResourceShrinkerCli", visibility = ["//visibility:public"],