143 lines
6.4 KiB
Python
143 lines
6.4 KiB
Python
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
#
|
|
# This source code is licensed under both the MIT license found in the
|
|
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
|
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
|
# of this source tree.
|
|
|
|
load("@prelude//java:java_providers.bzl", "get_java_packaging_info")
|
|
load("@prelude//utils:utils.bzl", "expect")
|
|
load(":android_providers.bzl", "AndroidResourceInfo", "ExportedAndroidResourceInfo", "merge_android_packageable_info")
|
|
load(":android_toolchain.bzl", "AndroidToolchainInfo")
|
|
|
|
JAVA_PACKAGE_FILENAME = "java_package.txt"
|
|
|
|
def _convert_to_artifact_dir(ctx: "context", attr: ["dependency", "dict", "artifact", None], attr_name: str.type) -> ["artifact", None]:
|
|
if type(attr) == "dependency":
|
|
expect(len(attr[DefaultInfo].default_outputs) == 1, "Expect one default output from build dep of attr {}!".format(attr_name))
|
|
return attr[DefaultInfo].default_outputs[0]
|
|
elif type(attr) == "dict" and len(attr) > 0:
|
|
return ctx.actions.symlinked_dir("{}_dir".format(attr_name), attr)
|
|
else:
|
|
return attr
|
|
|
|
def android_resource_impl(ctx: "context") -> ["provider"]:
|
|
if ctx.attrs._build_only_native_code:
|
|
return [DefaultInfo()]
|
|
|
|
# TODO(T100007184) filter res/assets by ignored filenames
|
|
sub_targets = {}
|
|
providers = []
|
|
default_outputs = []
|
|
|
|
res = _convert_to_artifact_dir(ctx, ctx.attrs.res, "res")
|
|
assets = _convert_to_artifact_dir(ctx, ctx.attrs.assets, "assets")
|
|
|
|
if res:
|
|
aapt2_compile_output = aapt2_compile(ctx, res, ctx.attrs._android_toolchain[AndroidToolchainInfo])
|
|
|
|
sub_targets["aapt2_compile"] = [DefaultInfo(default_outputs = [aapt2_compile_output])]
|
|
|
|
r_dot_txt_output = get_text_symbols(ctx, res, ctx.attrs.deps)
|
|
default_outputs.append(r_dot_txt_output)
|
|
|
|
r_dot_java_package = _get_package(ctx, ctx.attrs.package, ctx.attrs.manifest)
|
|
resource_info = AndroidResourceInfo(
|
|
aapt2_compile_output = aapt2_compile_output,
|
|
allow_strings_as_assets_resource_filtering = not ctx.attrs.has_whitelisted_strings,
|
|
assets = assets,
|
|
manifest_file = ctx.attrs.manifest,
|
|
r_dot_java_package = r_dot_java_package,
|
|
res = res,
|
|
text_symbols = r_dot_txt_output,
|
|
)
|
|
else:
|
|
resource_info = AndroidResourceInfo(
|
|
aapt2_compile_output = None,
|
|
allow_strings_as_assets_resource_filtering = not ctx.attrs.has_whitelisted_strings,
|
|
assets = assets,
|
|
manifest_file = ctx.attrs.manifest,
|
|
r_dot_java_package = None,
|
|
res = None,
|
|
text_symbols = None,
|
|
)
|
|
providers.append(resource_info)
|
|
providers.append(merge_android_packageable_info(ctx.label, ctx.actions, ctx.attrs.deps, manifest = ctx.attrs.manifest, resource_info = resource_info))
|
|
providers.append(get_java_packaging_info(ctx, ctx.attrs.deps))
|
|
providers.append(DefaultInfo(default_outputs = default_outputs, sub_targets = sub_targets))
|
|
|
|
return providers
|
|
|
|
def aapt2_compile(
|
|
ctx: "context",
|
|
resources_dir: "artifact",
|
|
android_toolchain: "AndroidToolchainInfo",
|
|
skip_crunch_pngs: bool.type = False,
|
|
identifier: [str.type, None] = None) -> "artifact":
|
|
aapt2_command = cmd_args(android_toolchain.aapt2)
|
|
aapt2_command.add("compile")
|
|
aapt2_command.add("--legacy")
|
|
if skip_crunch_pngs:
|
|
aapt2_command.add("--no-crunch")
|
|
aapt2_command.add(["--dir", resources_dir])
|
|
aapt2_output = ctx.actions.declare_output("{}_resources.flata".format(identifier) if identifier else "resources.flata")
|
|
aapt2_command.add("-o", aapt2_output.as_output())
|
|
|
|
ctx.actions.run(aapt2_command, category = "aapt2_compile", identifier = identifier)
|
|
|
|
return aapt2_output
|
|
|
|
def _get_package(ctx: "context", package: [str.type, None], manifest: ["artifact", None]) -> "artifact":
|
|
if package:
|
|
return ctx.actions.write(JAVA_PACKAGE_FILENAME, package)
|
|
else:
|
|
expect(manifest != None, "if package is not declared then a manifest must be")
|
|
return extract_package_from_manifest(ctx, manifest)
|
|
|
|
def extract_package_from_manifest(ctx: "context", manifest: "artifact") -> "artifact":
|
|
r_dot_java_package = ctx.actions.declare_output(JAVA_PACKAGE_FILENAME)
|
|
extract_package_cmd = cmd_args(ctx.attrs._android_toolchain[AndroidToolchainInfo].manifest_utils[RunInfo])
|
|
extract_package_cmd.add(["--manifest-path", manifest])
|
|
extract_package_cmd.add(["--package-output", r_dot_java_package.as_output()])
|
|
|
|
ctx.actions.run(extract_package_cmd, category = "android_extract_package")
|
|
|
|
return r_dot_java_package
|
|
|
|
def get_text_symbols(
|
|
ctx: "context",
|
|
res: "artifact",
|
|
deps: ["dependency"],
|
|
identifier: [str.type, None] = None):
|
|
mini_aapt_cmd = cmd_args(ctx.attrs._android_toolchain[AndroidToolchainInfo].mini_aapt[RunInfo])
|
|
|
|
mini_aapt_cmd.add(["--resource-paths", res])
|
|
|
|
dep_symbol_paths = cmd_args()
|
|
dep_symbols = _get_dep_symbols(deps)
|
|
dep_symbol_paths.add(dep_symbols)
|
|
|
|
dep_symbol_paths_file, _ = ctx.actions.write("{}_dep_symbol_paths_file".format(identifier) if identifier else "dep_symbol_paths_file", dep_symbol_paths, allow_args = True)
|
|
|
|
mini_aapt_cmd.add(["--dep-symbol-paths", dep_symbol_paths_file])
|
|
mini_aapt_cmd.hidden(dep_symbols)
|
|
|
|
text_symbols = ctx.actions.declare_output("{}_R.txt".format(identifier) if identifier else "R.txt")
|
|
mini_aapt_cmd.add(["--output-path", text_symbols.as_output()])
|
|
|
|
ctx.actions.run(mini_aapt_cmd, category = "mini_aapt", identifier = identifier)
|
|
|
|
return text_symbols
|
|
|
|
def _get_dep_symbols(deps: ["dependency"]) -> ["artifact"]:
|
|
dep_symbols = []
|
|
for dep in deps:
|
|
android_resource_info = dep.get(AndroidResourceInfo)
|
|
exported_android_resource_info = dep.get(ExportedAndroidResourceInfo)
|
|
expect(android_resource_info != None or exported_android_resource_info != None, "Dependencies of `android_resource` rules should be `android_resource`s or `android_library`s")
|
|
if android_resource_info and android_resource_info.text_symbols:
|
|
dep_symbols.append(android_resource_info.text_symbols)
|
|
if exported_android_resource_info:
|
|
dep_symbols += [resource_info.text_symbols for resource_info in exported_android_resource_info.resource_infos if resource_info.text_symbols]
|
|
|
|
return dedupe(dep_symbols)
|