xref: /aosp_15_r20/external/bazelbuild-rules_android/rules/android_library/impl.bzl (revision 9e965d6fece27a77de5377433c2f7e6999b8cc0b)
1# Copyright 2018 The Bazel Authors. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#    http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Implementation."""
16
17load("//rules:acls.bzl", "acls")
18load("//rules:attrs.bzl", _attrs = "attrs")
19load("//rules:common.bzl", _common = "common")
20load("//rules:data_binding.bzl", _data_binding = "data_binding")
21load("//rules:idl.bzl", _idl = "idl")
22load("//rules:intellij.bzl", _intellij = "intellij")
23load("//rules:java.bzl", _java = "java")
24load(
25    "//rules:processing_pipeline.bzl",
26    "ProviderInfo",
27    "processing_pipeline",
28)
29load("//rules:proguard.bzl", _proguard = "proguard")
30load("//rules:providers.bzl", "AndroidLintRulesInfo", "StarlarkApkInfo")
31load("//rules:resources.bzl", _resources = "resources")
32load("//rules:utils.bzl", "get_android_sdk", "get_android_toolchain", "log", "utils")
33load("//rules/flags:flags.bzl", _flags = "flags")
34
35_USES_DEPRECATED_IMPLICIT_EXPORT_ERROR = (
36    "Use android_library.exports to explicitly specify the exported " +
37    "targets of %s."
38)
39
40_SRCS_CONTAIN_RESOURCE_LABEL_ERROR = (
41    "The srcs attribute of an android_library rule should not contain label " +
42    "with resources %s"
43)
44
45_IDL_IMPORT_ROOT_SET_WITHOUT_SRCS_OR_PARCELABLES_ERROR = (
46    "The 'idl_import_root' attribute of the android_library rule was set, " +
47    "but neither 'idl_srcs' nor 'idl_parcelables' were specified."
48)
49
50_IDL_SRC_FROM_DIFFERENT_PACKAGE_ERROR = (
51    "Do not import '%s' directly. You should either move the file to this " +
52    "package or depend on an appropriate rule there."
53)
54
55_IDL_USES_AOSP_COMPILER_ERROR = (
56    "Use of `idl_uses_aosp_compiler` is not allowed for %s."
57)
58
59_IDL_IDLOPTS_UNSUPPORTERD_ERROR = (
60    "`idlopts` is supported only if `idl_uses_aosp_compiler` is set to true."
61)
62
63# Android library AAR context attributes.
64_PROVIDERS = "providers"
65_VALIDATION_OUTPUTS = "validation_outputs"
66
67_AARContextInfo = provider(
68    "Android library AAR context object",
69    fields = {
70        _PROVIDERS: "The list of all providers to propagate.",
71        _VALIDATION_OUTPUTS: "List of outputs given to OutputGroupInfo _validation group",
72    },
73)
74
75def _has_srcs(ctx):
76    return ctx.files.srcs or ctx.files.idl_srcs or getattr(ctx.files, "common_srcs", False)
77
78def _uses_deprecated_implicit_export(ctx):
79    return (ctx.attr.deps and not (_has_srcs(ctx) or
80                                   ctx.attr._defined_assets or
81                                   ctx.files.resource_files or
82                                   ctx.attr.manifest or
83                                   ctx.attr.baseline_profiles))
84
85def _uses_resources_and_deps_without_srcs(ctx):
86    return (ctx.attr.deps and
87            (ctx.attr._defined_assets or ctx.files.resource_files or ctx.attr.manifest) and
88            not _has_srcs(ctx))
89
90def _check_deps_without_java_srcs(ctx):
91    if not ctx.attr.deps or _has_srcs(ctx):
92        return False
93    gfn = getattr(ctx.attr, "generator_function", "")
94    if _uses_deprecated_implicit_export(ctx):
95        log.error(_USES_DEPRECATED_IMPLICIT_EXPORT_ERROR % ctx.label)
96    if _uses_resources_and_deps_without_srcs(ctx):
97        if (acls.in_android_library_resources_without_srcs_generator_functions(gfn) or
98            acls.in_android_library_resources_without_srcs(str(ctx.label))):
99            return True
100    return False
101
102def _validate_rule_context(ctx):
103    # Verify that idl_import_root is specified with idl_src or idl_parcelables.
104    if (ctx.attr._defined_idl_import_root and
105        not (ctx.attr._defined_idl_srcs or ctx.attr._defined_idl_parcelables)):
106        log.error(_IDL_IMPORT_ROOT_SET_WITHOUT_SRCS_OR_PARCELABLES_ERROR)
107
108    # Verify that idl_srcs are not from another package.
109    for idl_src in ctx.attr.idl_srcs:
110        if ctx.label.package != idl_src.label.package:
111            log.error(_IDL_SRC_FROM_DIFFERENT_PACKAGE_ERROR % idl_src.label)
112
113    # Ensure that the AOSP AIDL compiler is used only in allowlisted packages
114    if (ctx.attr.idl_uses_aosp_compiler and
115        not acls.in_android_library_use_aosp_aidl_compiler_allowlist(str(ctx.label))):
116        log.error(_IDL_USES_AOSP_COMPILER_ERROR % ctx.label)
117
118    # Check if idlopts is with idl_uses_aosp_compiler
119    if ctx.attr.idlopts and not ctx.attr.idl_uses_aosp_compiler:
120        log.error(_IDL_IDLOPTS_UNSUPPORTERD_ERROR)
121
122    return struct(
123        enable_deps_without_srcs = _check_deps_without_java_srcs(ctx),
124    )
125
126def _exceptions_processor(ctx, **unused_ctxs):
127    return ProviderInfo(
128        name = "exceptions_ctx",
129        value = _validate_rule_context(ctx),
130    )
131
132def _process_manifest(ctx, **unused_ctxs):
133    manifest_ctx = _resources.bump_min_sdk(
134        ctx,
135        manifest = ctx.file.manifest,
136        floor = acls.get_min_sdk_floor(str(ctx.label)),
137        enforce_min_sdk_floor_tool = get_android_toolchain(ctx).enforce_min_sdk_floor_tool.files_to_run,
138    )
139
140    return ProviderInfo(
141        name = "manifest_ctx",
142        value = manifest_ctx,
143    )
144
145def _process_resources(ctx, java_package, manifest_ctx, **unused_ctxs):
146    # exports_manifest can be overridden by a bazel flag.
147    if ctx.attr.exports_manifest == _attrs.tristate.auto:
148        exports_manifest = ctx.fragments.android.get_exports_manifest_default
149    else:
150        exports_manifest = ctx.attr.exports_manifest == _attrs.tristate.yes
151
152    resource_apks = []
153    for apk in utils.collect_providers(StarlarkApkInfo, ctx.attr.resource_apks):
154        resource_apks.append(apk.signed_apk)
155
156    # Process Android Resources
157    resources_ctx = _resources.process(
158        ctx,
159        manifest = manifest_ctx.processed_manifest,
160        resource_files = ctx.attr.resource_files,
161        defined_assets = ctx.attr._defined_assets,
162        assets = ctx.attr.assets,
163        defined_assets_dir = ctx.attr._defined_assets_dir,
164        assets_dir = ctx.attr.assets_dir,
165        exports_manifest = exports_manifest,
166        java_package = java_package,
167        custom_package = ctx.attr.custom_package,
168        neverlink = ctx.attr.neverlink,
169        enable_data_binding = ctx.attr.enable_data_binding,
170        deps = ctx.attr.deps,
171        resource_apks = resource_apks,
172        exports = ctx.attr.exports,
173
174        # Processing behavior changing flags.
175        enable_res_v3 = _flags.get(ctx).android_enable_res_v3,
176        # TODO(b/144163743): remove fix_resource_transitivity, which was only added to emulate
177        # misbehavior on the Java side.
178        fix_resource_transitivity = bool(ctx.attr.srcs),
179        fix_export_exporting = acls.in_fix_export_exporting_rollout(str(ctx.label)),
180
181        # Tool and Processing related inputs
182        aapt = get_android_toolchain(ctx).aapt2.files_to_run,
183        android_jar = get_android_sdk(ctx).android_jar,
184        android_kit = get_android_toolchain(ctx).android_kit.files_to_run,
185        busybox = get_android_toolchain(ctx).android_resources_busybox.files_to_run,
186        java_toolchain = _common.get_java_toolchain(ctx),
187        host_javabase = _common.get_host_javabase(ctx),
188        instrument_xslt = utils.only(get_android_toolchain(ctx).add_g3itr_xslt.files.to_list()),
189        res_v3_dummy_manifest = utils.only(
190            get_android_toolchain(ctx).res_v3_dummy_manifest.files.to_list(),
191        ),
192        res_v3_dummy_r_txt = utils.only(
193            get_android_toolchain(ctx).res_v3_dummy_r_txt.files.to_list(),
194        ),
195        xsltproc = get_android_toolchain(ctx).xsltproc_tool.files_to_run,
196        zip_tool = get_android_toolchain(ctx).zip_tool.files_to_run,
197    )
198
199    # TODO(b/139305816): Remove the ability for android_library to be added in
200    # the srcs attribute of another android_library.
201    if resources_ctx.defines_resources:
202        # Verify that srcs do no contain labels.
203        for src in ctx.attr.srcs:
204            if AndroidResourcesInfo in src:
205                log.error(_SRCS_CONTAIN_RESOURCE_LABEL_ERROR %
206                          src[AndroidResourcesInfo].label)
207
208    return ProviderInfo(
209        name = "resources_ctx",
210        value = resources_ctx,
211    )
212
213def _process_idl(ctx, **unused_sub_ctxs):
214    return ProviderInfo(
215        name = "idl_ctx",
216        value = _idl.process(
217            ctx,
218            idl_srcs = ctx.files.idl_srcs,
219            idl_parcelables = ctx.files.idl_parcelables,
220            idl_import_root =
221                ctx.attr.idl_import_root if ctx.attr._defined_idl_import_root else None,
222            idl_preprocessed = ctx.files.idl_preprocessed,
223            deps = utils.collect_providers(AndroidIdlInfo, ctx.attr.deps),
224            exports = utils.collect_providers(AndroidIdlInfo, ctx.attr.exports),
225            aidl = get_android_sdk(ctx).aidl,
226            aidl_lib = get_android_sdk(ctx).aidl_lib,
227            aidl_framework = get_android_sdk(ctx).framework_aidl,
228            uses_aosp_compiler = ctx.attr.idl_uses_aosp_compiler,
229            idlopts = ctx.attr.idlopts,
230        ),
231    )
232
233def _process_data_binding(ctx, java_package, resources_ctx, **unused_sub_ctxs):
234    if ctx.attr.enable_data_binding and not acls.in_databinding_allowed(str(ctx.label)):
235        fail("This target is not allowed to use databinding and enable_data_binding is True.")
236    return ProviderInfo(
237        name = "db_ctx",
238        value = _data_binding.process(
239            ctx,
240            defines_resources = resources_ctx.defines_resources,
241            enable_data_binding = ctx.attr.enable_data_binding,
242            java_package = java_package,
243            layout_info = resources_ctx.data_binding_layout_info,
244            deps = utils.collect_providers(DataBindingV2Info, ctx.attr.deps),
245            exports = utils.collect_providers(DataBindingV2Info, ctx.attr.exports),
246            data_binding_exec = get_android_toolchain(ctx).data_binding_exec.files_to_run,
247            data_binding_annotation_processor =
248                get_android_toolchain(ctx).data_binding_annotation_processor,
249            data_binding_annotation_template =
250                utils.only(get_android_toolchain(ctx).data_binding_annotation_template.files.to_list()),
251        ),
252    )
253
254def _process_proguard(ctx, idl_ctx, **unused_sub_ctxs):
255    return ProviderInfo(
256        name = "proguard_ctx",
257        value = _proguard.process_specs(
258            ctx,
259            proguard_configs = ctx.files.proguard_specs,
260            proguard_spec_providers = utils.collect_providers(
261                ProguardSpecProvider,
262                ctx.attr.deps,
263                ctx.attr.exports,
264                idl_ctx.idl_deps,
265            ),
266            proguard_allowlister =
267                get_android_toolchain(ctx).proguard_allowlister.files_to_run,
268        ),
269    )
270
271def _process_jvm(ctx, exceptions_ctx, resources_ctx, idl_ctx, db_ctx, **unused_sub_ctxs):
272    java_info = _java.compile_android(
273        ctx,
274        ctx.outputs.lib_jar,
275        ctx.outputs.lib_src_jar,
276        srcs = ctx.files.srcs + idl_ctx.idl_java_srcs + db_ctx.java_srcs,
277        javac_opts = ctx.attr.javacopts + db_ctx.javac_opts,
278        r_java = resources_ctx.r_java,
279        deps =
280            utils.collect_providers(JavaInfo, ctx.attr.deps, idl_ctx.idl_deps),
281        exports = utils.collect_providers(JavaInfo, ctx.attr.exports),
282        plugins = utils.collect_providers(JavaPluginInfo, ctx.attr.plugins, db_ctx.java_plugins),
283        exported_plugins = utils.collect_providers(
284            JavaPluginInfo,
285            ctx.attr.exported_plugins,
286        ),
287        annotation_processor_additional_outputs = (
288            db_ctx.java_annotation_processor_additional_outputs
289        ),
290        annotation_processor_additional_inputs = (
291            db_ctx.java_annotation_processor_additional_inputs
292        ),
293        enable_deps_without_srcs = exceptions_ctx.enable_deps_without_srcs,
294        neverlink = ctx.attr.neverlink,
295        strict_deps = "DEFAULT",
296        java_toolchain = _common.get_java_toolchain(ctx),
297    )
298
299    providers = [java_info]
300
301    # Propagate Lint rule Jars from any exported AARs (b/229993446)
302    android_lint_rules = [info.lint_jars for info in utils.collect_providers(
303        AndroidLintRulesInfo,
304        ctx.attr.exports,
305    )]
306    if android_lint_rules:
307        providers.append(
308            AndroidLintRulesInfo(
309                lint_jars = depset(transitive = android_lint_rules),
310            ),
311        )
312
313    return ProviderInfo(
314        name = "jvm_ctx",
315        value = struct(
316            java_info = java_info,
317            providers = providers,
318        ),
319    )
320
321def _process_aar(ctx, java_package, resources_ctx, proguard_ctx, **unused_ctx):
322    aar_ctx = {
323        _PROVIDERS: [],
324        _VALIDATION_OUTPUTS: [],
325    }
326
327    starlark_aar = _resources.make_aar(
328        ctx,
329        manifest = resources_ctx.starlark_processed_manifest,
330        assets = ctx.files.assets,
331        assets_dir = ctx.attr.assets_dir,
332        resource_files = resources_ctx.starlark_processed_resources if not ctx.attr.neverlink else [],
333        class_jar = ctx.outputs.lib_jar,
334        r_txt = resources_ctx.starlark_r_txt,
335        proguard_specs = proguard_ctx.proguard_configs,
336        busybox = get_android_toolchain(ctx).android_resources_busybox.files_to_run,
337        host_javabase = _common.get_host_javabase(ctx),
338    )
339
340    # TODO(b/170409221): Clean this up once Starlark migration is complete. Create and propagate
341    # a native aar info provider with the Starlark artifacts to avoid breaking downstream
342    # targets.
343    if not ctx.attr.neverlink:
344        aar_ctx[_PROVIDERS].append(AndroidLibraryAarInfo(
345            aar = starlark_aar,
346            manifest = resources_ctx.starlark_processed_manifest,
347            aars_from_deps = utils.collect_providers(
348                AndroidLibraryAarInfo,
349                ctx.attr.deps,
350                ctx.attr.exports,
351            ),
352            defines_local_resources = resources_ctx.defines_resources,
353        ))
354
355    return ProviderInfo(
356        name = "aar_ctx",
357        value = _AARContextInfo(**aar_ctx),
358    )
359
360def _process_native(ctx, idl_ctx, **unused_ctx):
361    return ProviderInfo(
362        name = "native_ctx",
363        value = struct(
364            providers = [
365                AndroidNativeLibsInfo(
366                    depset(
367                        transitive = [
368                            p.native_libs
369                            for p in utils.collect_providers(
370                                AndroidNativeLibsInfo,
371                                ctx.attr.deps,
372                                ctx.attr.exports,
373                            )
374                        ],
375                        order = "preorder",
376                    ),
377                ),
378                AndroidCcLinkParamsInfo(
379                    cc_common.merge_cc_infos(
380                        cc_infos = [
381                                       info.cc_link_params_info
382                                       for info in utils.collect_providers(
383                                           JavaInfo,
384                                           ctx.attr.deps,
385                                           ctx.attr.exports,
386                                           idl_ctx.idl_deps,
387                                       )
388                                   ] +
389                                   [
390                                       info.link_params
391                                       for info in utils.collect_providers(
392                                           AndroidCcLinkParamsInfo,
393                                           ctx.attr.deps,
394                                           ctx.attr.exports,
395                                           idl_ctx.idl_deps,
396                                       )
397                                   ] +
398                                   utils.collect_providers(
399                                       CcInfo,
400                                       ctx.attr.deps,
401                                       ctx.attr.exports,
402                                       idl_ctx.idl_deps,
403                                   ),
404                    ),
405                ),
406            ],
407        ),
408    )
409
410def _process_intellij(ctx, java_package, manifest_ctx, resources_ctx, idl_ctx, jvm_ctx, **unused_sub_ctxs):
411    android_ide_info = _intellij.make_android_ide_info(
412        ctx,
413        java_package = java_package,
414        manifest = manifest_ctx.processed_manifest,
415        defines_resources = resources_ctx.defines_resources,
416        merged_manifest = resources_ctx.merged_manifest,
417        resources_apk = resources_ctx.resources_apk,
418        r_jar = utils.only(resources_ctx.r_java.outputs.jars) if resources_ctx.r_java else None,
419        idl_import_root = idl_ctx.idl_import_root,
420        idl_srcs = idl_ctx.idl_srcs,
421        idl_java_srcs = idl_ctx.idl_java_srcs,
422        java_info = jvm_ctx.java_info,
423        signed_apk = None,  # signed_apk, always empty for android_library.
424        aar = getattr(ctx.outputs, "aar", None),  # Deprecate aar for android_library.
425        apks_under_test = [],  # apks_under_test, always empty for android_library
426        native_libs = dict(),  # nativelibs, always empty for android_library
427        idlclass = get_android_toolchain(ctx).idlclass.files_to_run,
428        host_javabase = _common.get_host_javabase(ctx),
429    )
430    return ProviderInfo(
431        name = "intellij_ctx",
432        value = struct(
433            android_ide_info = android_ide_info,
434            providers = [android_ide_info],
435        ),
436    )
437
438def _process_coverage(ctx, **unused_ctx):
439    return ProviderInfo(
440        name = "coverage_ctx",
441        value = struct(
442            providers = [
443                coverage_common.instrumented_files_info(
444                    ctx,
445                    source_attributes = ["srcs"],
446                    dependency_attributes = ["assets", "deps", "exports"],
447                ),
448            ],
449        ),
450    )
451
452def _process_baseline_profiles(ctx, **unused_ctx):
453    return ProviderInfo(
454        name = "bp_ctx",
455        value = struct(
456            providers = [
457                BaselineProfileProvider(depset(
458                    ctx.files.baseline_profiles,
459                    transitive = [bp.files for bp in utils.collect_providers(BaselineProfileProvider, ctx.attr.deps, ctx.attr.exports)],
460                )),
461            ],
462        ),
463    )
464
465# Order dependent, as providers will not be available to downstream processors
466# that may depend on the provider. Iteration order for a dictionary is based on
467# insertion.
468PROCESSORS = dict(
469    ExceptionsProcessor = _exceptions_processor,
470    ManifestProcessor = _process_manifest,
471    ResourceProcessor = _process_resources,
472    IdlProcessor = _process_idl,
473    DataBindingProcessor = _process_data_binding,
474    JvmProcessor = _process_jvm,
475    ProguardProcessor = _process_proguard,
476    AarProcessor = _process_aar,
477    NativeProcessor = _process_native,
478    IntelliJProcessor = _process_intellij,
479    CoverageProcessor = _process_coverage,
480    BaselineProfilesProcessor = _process_baseline_profiles,
481)
482
483# TODO(b/119560471): Deprecate the usage of legacy providers.
484def _make_legacy_provider(intellij_ctx, jvm_ctx, providers):
485    return struct(
486        android = _intellij.make_legacy_android_provider(intellij_ctx.android_ide_info),
487        java = struct(
488            annotation_processing = jvm_ctx.java_info.annotation_processing,
489            outputs = jvm_ctx.java_info.outputs,
490            source_jars = depset(jvm_ctx.java_info.source_jars),
491            transitive_deps = jvm_ctx.java_info.transitive_compile_time_jars,
492            transitive_runtime_deps = jvm_ctx.java_info.transitive_runtime_jars,
493            transitive_source_jars = jvm_ctx.java_info.transitive_source_jars,
494        ),
495        providers = providers,
496    )
497
498def finalize(
499        ctx,
500        resources_ctx,
501        intellij_ctx,
502        jvm_ctx,
503        proguard_ctx,
504        providers,
505        validation_outputs,
506        **unused_ctxs):
507    """Creates the DefaultInfo and OutputGroupInfo providers.
508
509    Args:
510      ctx: The context.
511      resources_ctx: ProviderInfo. The resources ctx.
512      intellij_ctx: ProviderInfo. The intellij ctx.
513      jvm_ctx: ProviderInfo. The jvm ctx.
514      proguard_ctx: ProviderInfo. The proguard ctx.
515      providers: sequence of providers. The providers to propagate.
516      validation_outputs: sequence of Files. The validation outputs.
517      **unused_ctxs: Unused ProviderInfo.
518
519    Returns:
520      A struct with Android and Java legacy providers and a list of providers.
521    """
522    transitive_runfiles = []
523    if not ctx.attr.neverlink:
524        for p in utils.collect_providers(
525            DefaultInfo,
526            ctx.attr.deps,
527            ctx.attr.exports,
528        ):
529            transitive_runfiles.append(p.data_runfiles.files)
530            transitive_runfiles.append(p.default_runfiles.files)
531    runfiles = ctx.runfiles(
532        files = (
533            (resources_ctx.r_java.runtime_output_jars if resources_ctx.r_java and not ctx.attr.neverlink else []) +
534            ([ctx.outputs.lib_jar] if (ctx.attr.srcs or ctx.attr.idl_srcs) and not ctx.attr.neverlink else [])
535        ),
536        transitive_files = depset(transitive = transitive_runfiles),
537        collect_default = True,
538    )
539    files = [ctx.outputs.lib_jar]
540    if getattr(ctx.outputs, "resources_src_jar", None):
541        files.append(ctx.outputs.resources_src_jar)
542    if getattr(ctx.outputs, "resources_jar", None):
543        files.append(ctx.outputs.resources_jar)
544
545    providers.extend([
546        DefaultInfo(
547            files = depset(files),
548            runfiles = runfiles,
549        ),
550        OutputGroupInfo(
551            compilation_outputs = depset([ctx.outputs.lib_jar]),
552            _source_jars = depset(
553                [ctx.outputs.lib_src_jar],
554                transitive = [jvm_ctx.java_info.transitive_source_jars],
555            ),
556            _direct_source_jars = depset([ctx.outputs.lib_src_jar]),
557            _hidden_top_level_INTERNAL_ = depset(
558                resources_ctx.validation_results,
559                transitive = [
560                    info._hidden_top_level_INTERNAL_
561                    for info in utils.collect_providers(
562                        OutputGroupInfo,
563                        ctx.attr.deps,
564                        ctx.attr.exports,
565                    )
566                ] + [proguard_ctx.transitive_proguard_configs],
567            ),
568            _validation = depset(validation_outputs),
569        ),
570    ])
571    return _make_legacy_provider(intellij_ctx, jvm_ctx, providers)
572
573_PROCESSING_PIPELINE = processing_pipeline.make_processing_pipeline(
574    processors = PROCESSORS,
575    finalize = finalize,
576)
577
578def impl(ctx):
579    """The rule implementation.
580
581    Args:
582      ctx: The context.
583
584    Returns:
585      A legacy struct provider.
586    """
587    java_package = _java.resolve_package_from_label(ctx.label, ctx.attr.custom_package)
588    return processing_pipeline.run(ctx, java_package, _PROCESSING_PIPELINE)
589