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