1// Copyright 2020 Google Inc. 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
15package bp2build
16
17const (
18	// The default `load` preamble for every generated queryview BUILD file.
19	soongModuleLoad = `package(default_visibility = ["//visibility:public"])
20load("//build/bazel/queryview_rules:soong_module.bzl", "soong_module")
21
22`
23
24	// A macro call in the BUILD file representing a Soong module, with space
25	// for expanding more attributes.
26	soongModuleTarget = `soong_module(
27    name = "%s",
28    soong_module_name = "%s",
29    soong_module_type = "%s",
30    soong_module_variant = "%s",
31    soong_module_deps = %s,
32%s)`
33
34	bazelTarget = `%s(
35    name = "%s",
36%s)`
37
38	// A simple provider to mark and differentiate Soong module rule shims from
39	// regular Bazel rules. Every Soong module rule shim returns a
40	// SoongModuleInfo provider, and can only depend on rules returning
41	// SoongModuleInfo in the `soong_module_deps` attribute.
42	providersBzl = `SoongModuleInfo = provider(
43    fields = {
44        "name": "Name of module",
45        "type": "Type of module",
46        "variant": "Variant of module",
47    },
48)
49`
50
51	// The soong_module rule implementation in a .bzl file.
52	soongModuleBzl = `
53%s
54
55load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
56
57def _generic_soong_module_impl(ctx):
58    return [
59        SoongModuleInfo(
60            name = ctx.attr.soong_module_name,
61            type = ctx.attr.soong_module_type,
62            variant = ctx.attr.soong_module_variant,
63        ),
64    ]
65
66generic_soong_module = rule(
67    implementation = _generic_soong_module_impl,
68    attrs = {
69        "soong_module_name": attr.string(mandatory = True),
70        "soong_module_type": attr.string(mandatory = True),
71        "soong_module_variant": attr.string(),
72        "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
73    },
74)
75
76soong_module_rule_map = {
77%s}
78
79_SUPPORTED_TYPES = ["bool", "int", "string"]
80
81def _is_supported_type(value):
82    if type(value) in _SUPPORTED_TYPES:
83        return True
84    elif type(value) == "list":
85        supported = True
86        for v in value:
87            supported = supported and type(v) in _SUPPORTED_TYPES
88        return supported
89    else:
90        return False
91
92# soong_module is a macro that supports arbitrary kwargs, and uses soong_module_type to
93# expand to the right underlying shim.
94def soong_module(name, soong_module_type, **kwargs):
95    soong_module_rule = soong_module_rule_map.get(soong_module_type)
96
97    if soong_module_rule == None:
98        # This module type does not have an existing rule to map to, so use the
99        # generic_soong_module rule instead.
100        generic_soong_module(
101            name = name,
102            soong_module_type = soong_module_type,
103            soong_module_name = kwargs.pop("soong_module_name", ""),
104            soong_module_variant = kwargs.pop("soong_module_variant", ""),
105            soong_module_deps = kwargs.pop("soong_module_deps", []),
106        )
107    else:
108        supported_kwargs = dict()
109        for key, value in kwargs.items():
110            if _is_supported_type(value):
111                supported_kwargs[key] = value
112        soong_module_rule(
113            name = name,
114            **supported_kwargs,
115        )
116`
117
118	// A rule shim for representing a Soong module type and its properties.
119	moduleRuleShim = `
120def _%[1]s_impl(ctx):
121    return [SoongModuleInfo()]
122
123%[1]s = rule(
124    implementation = _%[1]s_impl,
125    attrs = %[2]s
126)
127`
128)
129