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