• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2021 The Android Open Source Project
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"""Rule used to import artifacts prebuilt by Soong into the Bazel workspace.
16
17The rule returns a DefaultInfo provider with all artifacts and runtime dependencies,
18and a SoongPrebuiltInfo provider with the original Soong module name and artifacts.
19"""
20
21SoongPrebuiltInfo = provider(
22    doc = "Info about a prebuilt Soong build module",
23    fields = {
24        "files": "Files imported from Soong outputs",
25        "module_name": "Name of the original Soong build module",
26    },
27)
28
29def _soong_prebuilt_impl(ctx):
30
31    files = ctx.files.files
32
33    # Ensure that soong_prebuilt targets always have at least one file to avoid
34    # evaluation errors when running Bazel cquery on a clean tree to find
35    # dependencies.
36    #
37    # This happens because soong_prebuilt dependency target globs don't match
38    # any files when the workspace symlinks are broken and point to build
39    # artifacts that still don't exist. This in turn causes errors in rules
40    # that reference these targets via attributes with allow_single_file=True
41    # and which expect a file to be present.
42    #
43    # Note that the below action is never really executed during cquery
44    # evaluation but fails when run as part of a test execution to signal that
45    # prebuilts were not correctly imported.
46    if not files:
47        placeholder_file = ctx.actions.declare_file(ctx.label.name + ".missing")
48
49        progress_message = (
50            "Attempting to import missing artifacts for Soong module '%s'; " +
51            "please make sure that the module is built with Soong before " +
52            "running Bazel"
53        ) % ctx.attr.module_name
54
55        # Note that we don't write the file for the action to always be
56        # executed and display the warning message.
57        ctx.actions.run_shell(
58            outputs=[placeholder_file],
59            command="/bin/false",
60            progress_message=progress_message
61        )
62        files = [placeholder_file]
63
64    deps = []
65    deps.extend(ctx.attr.runtime_deps)
66    deps.extend(ctx.attr.data)
67    runfiles = ctx.runfiles(files = files).merge_all([
68        dep[DefaultInfo].default_runfiles
69        for dep in deps
70    ])
71
72    return [
73        SoongPrebuiltInfo(
74            files = depset(files),
75            module_name = ctx.attr.module_name,
76        ),
77        DefaultInfo(
78            files = depset(files),
79            runfiles = runfiles,
80        ),
81    ]
82
83soong_prebuilt = rule(
84    attrs = {
85        "module_name": attr.string(),
86        # Artifacts prebuilt by Soong.
87        "files": attr.label_list(allow_files = True),
88        # Targets that are needed by this target during runtime.
89        "runtime_deps": attr.label_list(),
90        "data": attr.label_list(),
91    },
92    implementation = _soong_prebuilt_impl,
93    doc = "A rule that imports artifacts prebuilt by Soong into the Bazel workspace",
94)
95
96def _soong_uninstalled_prebuilt_impl(ctx):
97
98    runfiles = ctx.runfiles().merge_all([
99        dep[DefaultInfo].default_runfiles
100        for dep in ctx.attr.runtime_deps
101    ])
102
103    return [
104        SoongPrebuiltInfo(
105            module_name = ctx.attr.module_name,
106        ),
107        DefaultInfo(
108            runfiles = runfiles,
109        ),
110    ]
111
112soong_uninstalled_prebuilt = rule(
113    attrs = {
114        "module_name": attr.string(),
115        "runtime_deps": attr.label_list(),
116    },
117    implementation = _soong_uninstalled_prebuilt_impl,
118    doc = "A rule for targets with no runtime outputs",
119)
120