| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 1 | // Copyright 2021 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 |  | 
 | 15 | package android | 
 | 16 |  | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 17 | import ( | 
| Wei Li | bafb6d6 | 2021-12-10 03:14:59 -0800 | [diff] [blame] | 18 | 	"bufio" | 
 | 19 | 	"errors" | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 20 | 	"fmt" | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 21 | 	"strings" | 
 | 22 |  | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 23 | 	"android/soong/ui/metrics/bp2build_metrics_proto" | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 24 |  | 
| Liz Kammer | bdc6099 | 2021-02-24 16:55:11 -0500 | [diff] [blame] | 25 | 	"github.com/google/blueprint" | 
| Spandan Das | 6485242 | 2023-08-02 21:58:41 +0000 | [diff] [blame] | 26 | 	"github.com/google/blueprint/bootstrap" | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 27 | 	"github.com/google/blueprint/proptools" | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 28 |  | 
 | 29 | 	"android/soong/android/allowlists" | 
 | 30 | ) | 
 | 31 |  | 
 | 32 | const ( | 
 | 33 | 	// A sentinel value to be used as a key in Bp2BuildConfig for modules with | 
 | 34 | 	// no package path. This is also the module dir for top level Android.bp | 
 | 35 | 	// modules. | 
 | 36 | 	Bp2BuildTopLevel = "." | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 37 | ) | 
 | 38 |  | 
| MarkDacek | f47e142 | 2023-04-19 16:47:36 +0000 | [diff] [blame] | 39 | type MixedBuildEnabledStatus int | 
 | 40 |  | 
 | 41 | const ( | 
 | 42 | 	// This module can be mixed_built. | 
 | 43 | 	MixedBuildEnabled = iota | 
 | 44 |  | 
 | 45 | 	// There is a technical incompatibility preventing this module from being | 
 | 46 | 	// bazel-analyzed. Note: the module might also be incompatible. | 
 | 47 | 	TechnicalIncompatibility | 
 | 48 |  | 
 | 49 | 	// This module cannot be mixed_built due to some incompatibility with it | 
 | 50 | 	// that is not a platform incompatibility. Example: the module-type is not | 
 | 51 | 	// enabled, or is not bp2build-converted. | 
 | 52 | 	ModuleIncompatibility | 
| Liz Kammer | c13f785 | 2023-05-17 13:01:48 -0400 | [diff] [blame] | 53 |  | 
 | 54 | 	// Missing dependencies. We can't query Bazel for modules if it has missing dependencies, there | 
 | 55 | 	// will be failures. | 
 | 56 | 	ModuleMissingDeps | 
| MarkDacek | f47e142 | 2023-04-19 16:47:36 +0000 | [diff] [blame] | 57 | ) | 
 | 58 |  | 
| Yu Liu | 2aa806b | 2022-09-01 11:54:47 -0700 | [diff] [blame] | 59 | // FileGroupAsLibrary describes a filegroup module that is converted to some library | 
 | 60 | // such as aidl_library or proto_library. | 
 | 61 | type FileGroupAsLibrary interface { | 
| Vinh Tran | 444154d | 2022-08-16 13:10:31 -0400 | [diff] [blame] | 62 | 	ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool | 
| Yu Liu | 2aa806b | 2022-09-01 11:54:47 -0700 | [diff] [blame] | 63 | 	ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool | 
| Vinh Tran | 444154d | 2022-08-16 13:10:31 -0400 | [diff] [blame] | 64 | 	GetAidlLibraryLabel(ctx BazelConversionPathContext) string | 
| Yu Liu | 2aa806b | 2022-09-01 11:54:47 -0700 | [diff] [blame] | 65 | 	GetProtoLibraryLabel(ctx BazelConversionPathContext) string | 
| Vinh Tran | 444154d | 2022-08-16 13:10:31 -0400 | [diff] [blame] | 66 | } | 
 | 67 |  | 
| Sasha Smundak | a095406 | 2022-08-02 18:23:58 -0700 | [diff] [blame] | 68 | type BazelConversionStatus struct { | 
 | 69 | 	// Information about _all_ bp2build targets generated by this module. Multiple targets are | 
 | 70 | 	// supported as Soong handles some things within a single target that we may choose to split into | 
 | 71 | 	// multiple targets, e.g. renderscript, protos, yacc within a cc module. | 
 | 72 | 	Bp2buildInfo []bp2buildInfo `blueprint:"mutated"` | 
 | 73 |  | 
 | 74 | 	// UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to | 
 | 75 | 	// Bazel | 
 | 76 | 	UnconvertedDeps []string `blueprint:"mutated"` | 
 | 77 |  | 
 | 78 | 	// MissingBp2buildDep stores the module names of direct dependency that were not found | 
 | 79 | 	MissingDeps []string `blueprint:"mutated"` | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 80 |  | 
 | 81 | 	// If non-nil, indicates that the module could not be converted successfully | 
 | 82 | 	// with bp2build. This will describe the reason the module could not be converted. | 
 | 83 | 	UnconvertedReason *UnconvertedReason | 
 | 84 | } | 
 | 85 |  | 
 | 86 | // The reason a module could not be converted to a BUILD target via bp2build. | 
 | 87 | // This should match bp2build_metrics_proto.UnconvertedReason, but omits private | 
 | 88 | // proto-related fields that prevent copying this struct. | 
 | 89 | type UnconvertedReason struct { | 
 | 90 | 	// Should correspond to a valid value in bp2build_metrics_proto.UnconvertedReasonType. | 
 | 91 | 	// A raw int is used here instead, because blueprint logic requires that all transitive | 
 | 92 | 	// fields of module definitions be primitives. | 
 | 93 | 	ReasonType int | 
 | 94 | 	Detail     string | 
| Sasha Smundak | a095406 | 2022-08-02 18:23:58 -0700 | [diff] [blame] | 95 | } | 
 | 96 |  | 
| Romain Jobredeaux | 8242b43 | 2023-05-04 10:16:26 -0400 | [diff] [blame] | 97 | type BazelModuleProperties struct { | 
| Jingwen Chen | 0181202 | 2021-11-19 14:29:43 +0000 | [diff] [blame] | 98 | 	// The label of the Bazel target replacing this Soong module. When run in conversion mode, this | 
 | 99 | 	// will import the handcrafted build target into the autogenerated file. Note: this may result in | 
 | 100 | 	// a conflict due to duplicate targets if bp2build_available is also set. | 
 | 101 | 	Label *string | 
 | 102 |  | 
 | 103 | 	// If true, bp2build will generate the converted Bazel target for this module. Note: this may | 
 | 104 | 	// cause a conflict due to the duplicate targets if label is also set. | 
 | 105 | 	// | 
 | 106 | 	// This is a bool pointer to support tristates: true, false, not set. | 
 | 107 | 	// | 
| Sasha Smundak | 39a301c | 2022-12-29 17:11:49 -0800 | [diff] [blame] | 108 | 	// To opt in a module, set bazel_module: { bp2build_available: true } | 
 | 109 | 	// To opt out a module, set bazel_module: { bp2build_available: false } | 
| Jingwen Chen | 0181202 | 2021-11-19 14:29:43 +0000 | [diff] [blame] | 110 | 	// To defer the default setting for the directory, do not set the value. | 
 | 111 | 	Bp2build_available *bool | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 112 |  | 
 | 113 | 	// CanConvertToBazel is set via InitBazelModule to indicate that a module type can be converted to | 
 | 114 | 	// Bazel with Bp2build. | 
 | 115 | 	CanConvertToBazel bool `blueprint:"mutated"` | 
| Jingwen Chen | 0181202 | 2021-11-19 14:29:43 +0000 | [diff] [blame] | 116 | } | 
 | 117 |  | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 118 | // Properties contains common module properties for Bazel migration purposes. | 
 | 119 | type properties struct { | 
| Chris Parsons | 1bb58da | 2022-08-30 13:37:57 -0400 | [diff] [blame] | 120 | 	// In "Bazel mixed build" mode, this represents the Bazel target replacing | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 121 | 	// this Soong module. | 
| Romain Jobredeaux | 8242b43 | 2023-05-04 10:16:26 -0400 | [diff] [blame] | 122 | 	Bazel_module BazelModuleProperties | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 123 | } | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 124 |  | 
| Jingwen Chen | 25825ca | 2021-11-15 12:28:43 +0000 | [diff] [blame] | 125 | // namespacedVariableProperties is a map from a string representing a Soong | 
| Jingwen Chen | 84817de | 2021-11-17 10:57:35 +0000 | [diff] [blame] | 126 | // config variable namespace, like "android" or "vendor_name" to a slice of | 
 | 127 | // pointer to a struct containing a single field called Soong_config_variables | 
 | 128 | // whose value mirrors the structure in the Blueprint file. | 
 | 129 | type namespacedVariableProperties map[string][]interface{} | 
| Jingwen Chen | a47f28d | 2021-11-02 16:43:57 +0000 | [diff] [blame] | 130 |  | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 131 | // BazelModuleBase contains the property structs with metadata for modules which can be converted to | 
 | 132 | // Bazel. | 
 | 133 | type BazelModuleBase struct { | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 134 | 	bazelProperties properties | 
| Jingwen Chen | a47f28d | 2021-11-02 16:43:57 +0000 | [diff] [blame] | 135 |  | 
 | 136 | 	// namespacedVariableProperties is used for soong_config_module_type support | 
 | 137 | 	// in bp2build. Soong config modules allow users to set module properties | 
 | 138 | 	// based on custom product variables defined in Android.bp files. These | 
 | 139 | 	// variables are namespaced to prevent clobbering, especially when set from | 
 | 140 | 	// Makefiles. | 
 | 141 | 	namespacedVariableProperties namespacedVariableProperties | 
 | 142 |  | 
 | 143 | 	// baseModuleType is set when this module was created from a module type | 
 | 144 | 	// defined by a soong_config_module_type. Every soong_config_module_type | 
 | 145 | 	// "wraps" another module type, e.g. a soong_config_module_type can wrap a | 
 | 146 | 	// cc_defaults to a custom_cc_defaults, or cc_binary to a custom_cc_binary. | 
 | 147 | 	// This baseModuleType is set to the wrapped module type. | 
 | 148 | 	baseModuleType string | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 149 | } | 
 | 150 |  | 
 | 151 | // Bazelable is specifies the interface for modules that can be converted to Bazel. | 
 | 152 | type Bazelable interface { | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 153 | 	bazelProps() *properties | 
 | 154 | 	HasHandcraftedLabel() bool | 
| Liz Kammer | bdc6099 | 2021-02-24 16:55:11 -0500 | [diff] [blame] | 155 | 	HandcraftedLabel() string | 
 | 156 | 	GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 157 | 	ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool | 
 | 158 | 	shouldConvertWithBp2build(shouldConvertModuleContext, shouldConvertParams) bool | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 159 |  | 
 | 160 | 	// ConvertWithBp2build either converts the module to a Bazel build target or | 
 | 161 | 	// declares the module as unconvertible (for logging and metrics). | 
 | 162 | 	// Modules must implement this function to be bp2build convertible. The function | 
 | 163 | 	// must either create at least one Bazel target module (using ctx.CreateBazelTargetModule or | 
 | 164 | 	// its related functions), or declare itself unconvertible using ctx.MarkBp2buildUnconvertible. | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 165 | 	ConvertWithBp2build(ctx TopDownMutatorContext) | 
| Jingwen Chen | a47f28d | 2021-11-02 16:43:57 +0000 | [diff] [blame] | 166 |  | 
| Jingwen Chen | 84817de | 2021-11-17 10:57:35 +0000 | [diff] [blame] | 167 | 	// namespacedVariableProps is a map from a soong config variable namespace | 
 | 168 | 	// (e.g. acme, android) to a map of interfaces{}, which are really | 
 | 169 | 	// reflect.Struct pointers, representing the value of the | 
 | 170 | 	// soong_config_variables property of a module. The struct pointer is the | 
 | 171 | 	// one with the single member called Soong_config_variables, which itself is | 
 | 172 | 	// a struct containing fields for each supported feature in that namespace. | 
 | 173 | 	// | 
| Sasha Smundak | 39a301c | 2022-12-29 17:11:49 -0800 | [diff] [blame] | 174 | 	// The reason for using a slice of interface{} is to support defaults | 
| Jingwen Chen | 84817de | 2021-11-17 10:57:35 +0000 | [diff] [blame] | 175 | 	// propagation of the struct pointers. | 
| Jingwen Chen | a47f28d | 2021-11-02 16:43:57 +0000 | [diff] [blame] | 176 | 	namespacedVariableProps() namespacedVariableProperties | 
 | 177 | 	setNamespacedVariableProps(props namespacedVariableProperties) | 
 | 178 | 	BaseModuleType() string | 
| Jingwen Chen | 84817de | 2021-11-17 10:57:35 +0000 | [diff] [blame] | 179 | 	SetBaseModuleType(baseModuleType string) | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 180 | } | 
 | 181 |  | 
| Spandan Das | 5af0bd3 | 2022-09-28 20:43:08 +0000 | [diff] [blame] | 182 | // ApiProvider is implemented by modules that contribute to an API surface | 
 | 183 | type ApiProvider interface { | 
 | 184 | 	ConvertWithApiBp2build(ctx TopDownMutatorContext) | 
 | 185 | } | 
 | 186 |  | 
| Chris Parsons | f874e46 | 2022-05-10 13:50:12 -0400 | [diff] [blame] | 187 | // MixedBuildBuildable is an interface that module types should implement in order | 
 | 188 | // to be "handled by Bazel" in a mixed build. | 
 | 189 | type MixedBuildBuildable interface { | 
 | 190 | 	// IsMixedBuildSupported returns true if and only if this module should be | 
 | 191 | 	// "handled by Bazel" in a mixed build. | 
 | 192 | 	// This "escape hatch" allows modules with corner-case scenarios to opt out | 
 | 193 | 	// of being built with Bazel. | 
 | 194 | 	IsMixedBuildSupported(ctx BaseModuleContext) bool | 
 | 195 |  | 
 | 196 | 	// QueueBazelCall invokes request-queueing functions on the BazelContext | 
 | 197 | 	// so that these requests are handled when Bazel's cquery is invoked. | 
 | 198 | 	QueueBazelCall(ctx BaseModuleContext) | 
 | 199 |  | 
 | 200 | 	// ProcessBazelQueryResponse uses Bazel information (obtained from the BazelContext) | 
 | 201 | 	// to set module fields and providers to propagate this module's metadata upstream. | 
 | 202 | 	// This effectively "bridges the gap" between Bazel and Soong in a mixed build. | 
 | 203 | 	// Soong modules depending on this module should be oblivious to the fact that | 
 | 204 | 	// this module was handled by Bazel. | 
 | 205 | 	ProcessBazelQueryResponse(ctx ModuleContext) | 
 | 206 | } | 
 | 207 |  | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 208 | // BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules. | 
 | 209 | type BazelModule interface { | 
 | 210 | 	Module | 
 | 211 | 	Bazelable | 
 | 212 | } | 
 | 213 |  | 
 | 214 | // InitBazelModule is a wrapper function that decorates a BazelModule with Bazel-conversion | 
 | 215 | // properties. | 
 | 216 | func InitBazelModule(module BazelModule) { | 
 | 217 | 	module.AddProperties(module.bazelProps()) | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 218 | 	module.bazelProps().Bazel_module.CanConvertToBazel = true | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 219 | } | 
 | 220 |  | 
 | 221 | // bazelProps returns the Bazel properties for the given BazelModuleBase. | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 222 | func (b *BazelModuleBase) bazelProps() *properties { | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 223 | 	return &b.bazelProperties | 
 | 224 | } | 
 | 225 |  | 
| Jingwen Chen | a47f28d | 2021-11-02 16:43:57 +0000 | [diff] [blame] | 226 | func (b *BazelModuleBase) namespacedVariableProps() namespacedVariableProperties { | 
 | 227 | 	return b.namespacedVariableProperties | 
 | 228 | } | 
 | 229 |  | 
 | 230 | func (b *BazelModuleBase) setNamespacedVariableProps(props namespacedVariableProperties) { | 
 | 231 | 	b.namespacedVariableProperties = props | 
 | 232 | } | 
 | 233 |  | 
 | 234 | func (b *BazelModuleBase) BaseModuleType() string { | 
 | 235 | 	return b.baseModuleType | 
 | 236 | } | 
 | 237 |  | 
 | 238 | func (b *BazelModuleBase) SetBaseModuleType(baseModuleType string) { | 
 | 239 | 	b.baseModuleType = baseModuleType | 
 | 240 | } | 
 | 241 |  | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 242 | // HasHandcraftedLabel returns whether this module has a handcrafted Bazel label. | 
 | 243 | func (b *BazelModuleBase) HasHandcraftedLabel() bool { | 
 | 244 | 	return b.bazelProperties.Bazel_module.Label != nil | 
 | 245 | } | 
 | 246 |  | 
 | 247 | // HandcraftedLabel returns the handcrafted label for this module, or empty string if there is none | 
 | 248 | func (b *BazelModuleBase) HandcraftedLabel() string { | 
 | 249 | 	return proptools.String(b.bazelProperties.Bazel_module.Label) | 
 | 250 | } | 
 | 251 |  | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 252 | // GetBazelLabel returns the Bazel label for the given BazelModuleBase. | 
| Liz Kammer | bdc6099 | 2021-02-24 16:55:11 -0500 | [diff] [blame] | 253 | func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string { | 
 | 254 | 	if b.HasHandcraftedLabel() { | 
 | 255 | 		return b.HandcraftedLabel() | 
 | 256 | 	} | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 257 | 	if b.ShouldConvertWithBp2build(ctx) { | 
| Liz Kammer | bdc6099 | 2021-02-24 16:55:11 -0500 | [diff] [blame] | 258 | 		return bp2buildModuleLabel(ctx, module) | 
 | 259 | 	} | 
| Spandan Das | 5b18c0c | 2023-07-14 00:23:29 +0000 | [diff] [blame] | 260 | 	panic(fmt.Errorf("requested non-existent label for module %s", module.Name())) | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 261 | } | 
 | 262 |  | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 263 | type Bp2BuildConversionAllowlist struct { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 264 | 	// Configure modules in these directories to enable bp2build_available: true or false by default. | 
 | 265 | 	defaultConfig allowlists.Bp2BuildConfig | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 266 |  | 
| Rupert Shuttleworth | 0096079 | 2021-05-12 21:20:13 -0400 | [diff] [blame] | 267 | 	// Keep any existing BUILD files (and do not generate new BUILD files) for these directories | 
| Jingwen Chen | b643c7a | 2021-07-26 04:45:48 +0000 | [diff] [blame] | 268 | 	// in the synthetic Bazel workspace. | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 269 | 	keepExistingBuildFile map[string]bool | 
| Jingwen Chen | 5d72cba | 2021-03-25 09:28:38 +0000 | [diff] [blame] | 270 |  | 
| Chris Parsons | ef615e5 | 2022-08-18 22:04:11 -0400 | [diff] [blame] | 271 | 	// Per-module allowlist to always opt modules into both bp2build and Bazel Dev Mode mixed | 
 | 272 | 	// builds. These modules are usually in directories with many other modules that are not ready | 
 | 273 | 	// for conversion. | 
| Jingwen Chen | 7edadab | 2022-03-04 07:01:29 +0000 | [diff] [blame] | 274 | 	// | 
 | 275 | 	// A module can either be in this list or its directory allowlisted entirely | 
 | 276 | 	// in bp2buildDefaultConfig, but not both at the same time. | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 277 | 	moduleAlwaysConvert map[string]bool | 
| Sam Delmerico | fa1831c | 2022-02-22 18:07:55 +0000 | [diff] [blame] | 278 |  | 
| Chris Parsons | ef615e5 | 2022-08-18 22:04:11 -0400 | [diff] [blame] | 279 | 	// Per-module-type allowlist to always opt modules in to both bp2build and | 
 | 280 | 	// Bazel Dev Mode mixed builds when they have the same type as one listed. | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 281 | 	moduleTypeAlwaysConvert map[string]bool | 
| Sam Delmerico | 85d831a | 2022-03-07 19:12:42 +0000 | [diff] [blame] | 282 |  | 
| Chris Parsons | ad87601 | 2022-08-20 14:48:32 -0400 | [diff] [blame] | 283 | 	// Per-module denylist to always opt modules out of bp2build conversion. | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 284 | 	moduleDoNotConvert map[string]bool | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 285 | } | 
| Liz Kammer | 5c31358 | 2021-12-03 15:23:26 -0500 | [diff] [blame] | 286 |  | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 287 | // NewBp2BuildAllowlist creates a new, empty Bp2BuildConversionAllowlist | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 288 | // which can be populated using builder pattern Set* methods | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 289 | func NewBp2BuildAllowlist() Bp2BuildConversionAllowlist { | 
 | 290 | 	return Bp2BuildConversionAllowlist{ | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 291 | 		allowlists.Bp2BuildConfig{}, | 
 | 292 | 		map[string]bool{}, | 
 | 293 | 		map[string]bool{}, | 
 | 294 | 		map[string]bool{}, | 
 | 295 | 		map[string]bool{}, | 
| Chris Parsons | bab4d7e | 2021-04-15 17:27:08 -0400 | [diff] [blame] | 296 | 	} | 
 | 297 | } | 
 | 298 |  | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 299 | // SetDefaultConfig copies the entries from defaultConfig into the allowlist | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 300 | func (a Bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) Bp2BuildConversionAllowlist { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 301 | 	if a.defaultConfig == nil { | 
 | 302 | 		a.defaultConfig = allowlists.Bp2BuildConfig{} | 
 | 303 | 	} | 
 | 304 | 	for k, v := range defaultConfig { | 
 | 305 | 		a.defaultConfig[k] = v | 
 | 306 | 	} | 
 | 307 |  | 
 | 308 | 	return a | 
 | 309 | } | 
 | 310 |  | 
 | 311 | // SetKeepExistingBuildFile copies the entries from keepExistingBuildFile into the allowlist | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 312 | func (a Bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) Bp2BuildConversionAllowlist { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 313 | 	if a.keepExistingBuildFile == nil { | 
 | 314 | 		a.keepExistingBuildFile = map[string]bool{} | 
 | 315 | 	} | 
 | 316 | 	for k, v := range keepExistingBuildFile { | 
 | 317 | 		a.keepExistingBuildFile[k] = v | 
 | 318 | 	} | 
 | 319 |  | 
 | 320 | 	return a | 
 | 321 | } | 
 | 322 |  | 
 | 323 | // SetModuleAlwaysConvertList copies the entries from moduleAlwaysConvert into the allowlist | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 324 | func (a Bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) Bp2BuildConversionAllowlist { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 325 | 	if a.moduleAlwaysConvert == nil { | 
 | 326 | 		a.moduleAlwaysConvert = map[string]bool{} | 
 | 327 | 	} | 
 | 328 | 	for _, m := range moduleAlwaysConvert { | 
 | 329 | 		a.moduleAlwaysConvert[m] = true | 
 | 330 | 	} | 
 | 331 |  | 
 | 332 | 	return a | 
 | 333 | } | 
 | 334 |  | 
 | 335 | // SetModuleTypeAlwaysConvertList copies the entries from moduleTypeAlwaysConvert into the allowlist | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 336 | func (a Bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) Bp2BuildConversionAllowlist { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 337 | 	if a.moduleTypeAlwaysConvert == nil { | 
 | 338 | 		a.moduleTypeAlwaysConvert = map[string]bool{} | 
 | 339 | 	} | 
 | 340 | 	for _, m := range moduleTypeAlwaysConvert { | 
 | 341 | 		a.moduleTypeAlwaysConvert[m] = true | 
 | 342 | 	} | 
 | 343 |  | 
 | 344 | 	return a | 
 | 345 | } | 
 | 346 |  | 
 | 347 | // SetModuleDoNotConvertList copies the entries from moduleDoNotConvert into the allowlist | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 348 | func (a Bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) Bp2BuildConversionAllowlist { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 349 | 	if a.moduleDoNotConvert == nil { | 
 | 350 | 		a.moduleDoNotConvert = map[string]bool{} | 
 | 351 | 	} | 
 | 352 | 	for _, m := range moduleDoNotConvert { | 
 | 353 | 		a.moduleDoNotConvert[m] = true | 
 | 354 | 	} | 
 | 355 |  | 
 | 356 | 	return a | 
 | 357 | } | 
 | 358 |  | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 359 | // ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be | 
 | 360 | // added to the build symlink forest based on the current global configuration. | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 361 | func (a Bp2BuildConversionAllowlist) ShouldKeepExistingBuildFileForDir(dir string) bool { | 
 | 362 | 	if _, ok := a.keepExistingBuildFile[dir]; ok { | 
| Rupert Shuttleworth | 0096079 | 2021-05-12 21:20:13 -0400 | [diff] [blame] | 363 | 		// Exact dir match | 
| Rupert Shuttleworth | 2a4fc3e | 2021-04-21 07:10:09 -0400 | [diff] [blame] | 364 | 		return true | 
 | 365 | 	} | 
| Usta Shrestha | ea99964 | 2022-11-02 01:03:07 -0400 | [diff] [blame] | 366 | 	var i int | 
| Rupert Shuttleworth | 0096079 | 2021-05-12 21:20:13 -0400 | [diff] [blame] | 367 | 	// Check if subtree match | 
| Usta Shrestha | ea99964 | 2022-11-02 01:03:07 -0400 | [diff] [blame] | 368 | 	for { | 
 | 369 | 		j := strings.Index(dir[i:], "/") | 
 | 370 | 		if j == -1 { | 
 | 371 | 			return false //default | 
 | 372 | 		} | 
 | 373 | 		prefix := dir[0 : i+j] | 
 | 374 | 		i = i + j + 1 // skip the "/" | 
 | 375 | 		if recursive, ok := a.keepExistingBuildFile[prefix]; ok && recursive { | 
 | 376 | 			return true | 
| Rupert Shuttleworth | 0096079 | 2021-05-12 21:20:13 -0400 | [diff] [blame] | 377 | 		} | 
 | 378 | 	} | 
| Rupert Shuttleworth | 2a4fc3e | 2021-04-21 07:10:09 -0400 | [diff] [blame] | 379 | } | 
 | 380 |  | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 381 | var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist") | 
 | 382 | var bp2buildAllowlist OncePer | 
 | 383 |  | 
 | 384 | func GetBp2BuildAllowList() Bp2BuildConversionAllowlist { | 
 | 385 | 	return bp2buildAllowlist.Once(bp2BuildAllowListKey, func() interface{} { | 
 | 386 | 		return NewBp2BuildAllowlist().SetDefaultConfig(allowlists.Bp2buildDefaultConfig). | 
 | 387 | 			SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile). | 
 | 388 | 			SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList). | 
 | 389 | 			SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList). | 
| Sasha Smundak | 39a301c | 2022-12-29 17:11:49 -0800 | [diff] [blame] | 390 | 			SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList) | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 391 | 	}).(Bp2BuildConversionAllowlist) | 
 | 392 | } | 
 | 393 |  | 
| MarkDacek | f47e142 | 2023-04-19 16:47:36 +0000 | [diff] [blame] | 394 | // MixedBuildsEnabled returns a MixedBuildEnabledStatus regarding whether | 
 | 395 | // a module is ready to be replaced by a converted or handcrafted Bazel target. | 
 | 396 | // As a side effect, calling this method will also log whether this module is | 
 | 397 | // mixed build enabled for metrics reporting. | 
 | 398 | func MixedBuildsEnabled(ctx BaseModuleContext) MixedBuildEnabledStatus { | 
| MarkDacek | f47e142 | 2023-04-19 16:47:36 +0000 | [diff] [blame] | 399 | 	platformIncompatible := isPlatformIncompatible(ctx.Os(), ctx.Arch().ArchType) | 
 | 400 | 	if platformIncompatible { | 
 | 401 | 		ctx.Config().LogMixedBuild(ctx, false) | 
 | 402 | 		return TechnicalIncompatibility | 
 | 403 | 	} | 
 | 404 |  | 
| Liz Kammer | c13f785 | 2023-05-17 13:01:48 -0400 | [diff] [blame] | 405 | 	if ctx.Config().AllowMissingDependencies() { | 
 | 406 | 		missingDeps := ctx.getMissingDependencies() | 
 | 407 | 		// If there are missing dependencies, querying Bazel will fail. Soong instead fails at execution | 
 | 408 | 		// time, not loading/analysis. disable mixed builds and fall back to Soong to maintain that | 
 | 409 | 		// behavior. | 
 | 410 | 		if len(missingDeps) > 0 { | 
 | 411 | 			ctx.Config().LogMixedBuild(ctx, false) | 
 | 412 | 			return ModuleMissingDeps | 
 | 413 | 		} | 
 | 414 | 	} | 
 | 415 |  | 
 | 416 | 	module := ctx.Module() | 
 | 417 | 	apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo) | 
 | 418 | 	withinApex := !apexInfo.IsForPlatform() | 
| Sasha Smundak | 39a301c | 2022-12-29 17:11:49 -0800 | [diff] [blame] | 419 | 	mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() && | 
| Sasha Smundak | 39a301c | 2022-12-29 17:11:49 -0800 | [diff] [blame] | 420 | 		module.Enabled() && | 
 | 421 | 		convertedToBazel(ctx, module) && | 
| Yu Liu | e431240 | 2023-01-18 09:15:31 -0800 | [diff] [blame] | 422 | 		ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex) | 
| MarkDacek | ff851b8 | 2022-04-21 18:33:17 +0000 | [diff] [blame] | 423 | 	ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled) | 
| MarkDacek | f47e142 | 2023-04-19 16:47:36 +0000 | [diff] [blame] | 424 |  | 
 | 425 | 	if mixedBuildEnabled { | 
 | 426 | 		return MixedBuildEnabled | 
 | 427 | 	} | 
 | 428 | 	return ModuleIncompatibility | 
| MarkDacek | ff851b8 | 2022-04-21 18:33:17 +0000 | [diff] [blame] | 429 | } | 
 | 430 |  | 
| Spandan Das | 6485242 | 2023-08-02 21:58:41 +0000 | [diff] [blame] | 431 | func isGoModule(module blueprint.Module) bool { | 
 | 432 | 	if _, ok := module.(*bootstrap.GoPackage); ok { | 
 | 433 | 		return true | 
 | 434 | 	} | 
 | 435 | 	if _, ok := module.(*bootstrap.GoBinary); ok { | 
 | 436 | 		return true | 
 | 437 | 	} | 
 | 438 | 	return false | 
 | 439 | } | 
 | 440 |  | 
| Liz Kammer | 6eff323 | 2021-08-26 08:37:59 -0400 | [diff] [blame] | 441 | // ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel. | 
| Jingwen Chen | 55bc820 | 2021-11-02 06:40:51 +0000 | [diff] [blame] | 442 | func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool { | 
| Spandan Das | 6485242 | 2023-08-02 21:58:41 +0000 | [diff] [blame] | 443 | 	// Special-case bootstrap_go_package and bootstrap_go_binary | 
 | 444 | 	// These do not implement Bazelable, but have been converted | 
 | 445 | 	if isGoModule(module) { | 
 | 446 | 		return true | 
 | 447 | 	} | 
| Liz Kammer | 6eff323 | 2021-08-26 08:37:59 -0400 | [diff] [blame] | 448 | 	b, ok := module.(Bazelable) | 
 | 449 | 	if !ok { | 
 | 450 | 		return false | 
 | 451 | 	} | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 452 |  | 
 | 453 | 	return b.HasHandcraftedLabel() || b.shouldConvertWithBp2build(ctx, shouldConvertParams{ | 
 | 454 | 		module:     module, | 
 | 455 | 		moduleDir:  ctx.OtherModuleDir(module), | 
 | 456 | 		moduleName: ctx.OtherModuleName(module), | 
 | 457 | 		moduleType: ctx.OtherModuleType(module), | 
 | 458 | 	}) | 
 | 459 | } | 
 | 460 |  | 
 | 461 | type ShouldConvertWithBazelContext interface { | 
 | 462 | 	ModuleErrorf(format string, args ...interface{}) | 
 | 463 | 	Module() Module | 
 | 464 | 	Config() Config | 
 | 465 | 	ModuleType() string | 
 | 466 | 	ModuleName() string | 
 | 467 | 	ModuleDir() string | 
| Liz Kammer | 6eff323 | 2021-08-26 08:37:59 -0400 | [diff] [blame] | 468 | } | 
 | 469 |  | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 470 | // ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 471 | func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool { | 
 | 472 | 	return b.shouldConvertWithBp2build(ctx, shouldConvertParams{ | 
 | 473 | 		module:     ctx.Module(), | 
 | 474 | 		moduleDir:  ctx.ModuleDir(), | 
 | 475 | 		moduleName: ctx.ModuleName(), | 
 | 476 | 		moduleType: ctx.ModuleType(), | 
 | 477 | 	}) | 
| Liz Kammer | 6eff323 | 2021-08-26 08:37:59 -0400 | [diff] [blame] | 478 | } | 
 | 479 |  | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 480 | type bazelOtherModuleContext interface { | 
 | 481 | 	ModuleErrorf(format string, args ...interface{}) | 
 | 482 | 	Config() Config | 
 | 483 | 	OtherModuleType(m blueprint.Module) string | 
 | 484 | 	OtherModuleName(m blueprint.Module) string | 
 | 485 | 	OtherModuleDir(m blueprint.Module) string | 
 | 486 | } | 
| Sam Delmerico | fa1831c | 2022-02-22 18:07:55 +0000 | [diff] [blame] | 487 |  | 
| MarkDacek | f47e142 | 2023-04-19 16:47:36 +0000 | [diff] [blame] | 488 | func isPlatformIncompatible(osType OsType, arch ArchType) bool { | 
 | 489 | 	return osType == Windows || // Windows toolchains are not currently supported. | 
 | 490 | 		osType == LinuxBionic || // Linux Bionic toolchains are not currently supported. | 
 | 491 | 		osType == LinuxMusl || // Linux musl toolchains are not currently supported (b/259266326). | 
 | 492 | 		arch == Riscv64 // TODO(b/262192655) Riscv64 toolchains are not currently supported. | 
 | 493 | } | 
 | 494 |  | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 495 | type shouldConvertModuleContext interface { | 
 | 496 | 	ModuleErrorf(format string, args ...interface{}) | 
 | 497 | 	Config() Config | 
 | 498 | } | 
 | 499 |  | 
 | 500 | type shouldConvertParams struct { | 
 | 501 | 	module     blueprint.Module | 
 | 502 | 	moduleType string | 
 | 503 | 	moduleDir  string | 
 | 504 | 	moduleName string | 
 | 505 | } | 
 | 506 |  | 
 | 507 | func (b *BazelModuleBase) shouldConvertWithBp2build(ctx shouldConvertModuleContext, p shouldConvertParams) bool { | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 508 | 	if !b.bazelProps().Bazel_module.CanConvertToBazel { | 
 | 509 | 		return false | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 510 | 	} | 
 | 511 |  | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 512 | 	module := p.module | 
| Spandan Das | 5af0bd3 | 2022-09-28 20:43:08 +0000 | [diff] [blame] | 513 | 	// In api_bp2build mode, all soong modules that can provide API contributions should be converted | 
 | 514 | 	// This is irrespective of its presence/absence in bp2build allowlists | 
 | 515 | 	if ctx.Config().BuildMode == ApiBp2build { | 
 | 516 | 		_, providesApis := module.(ApiProvider) | 
 | 517 | 		return providesApis | 
 | 518 | 	} | 
 | 519 |  | 
| Sam Delmerico | 85d831a | 2022-03-07 19:12:42 +0000 | [diff] [blame] | 520 | 	propValue := b.bazelProperties.Bazel_module.Bp2build_available | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 521 | 	packagePath := moduleDirWithPossibleOverride(ctx, module, p.moduleDir) | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 522 |  | 
| Sam Delmerico | 85d831a | 2022-03-07 19:12:42 +0000 | [diff] [blame] | 523 | 	// Modules in unit tests which are enabled in the allowlist by type or name | 
 | 524 | 	// trigger this conditional because unit tests run under the "." package path | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 525 | 	isTestModule := packagePath == Bp2BuildTopLevel && proptools.BoolDefault(propValue, false) | 
 | 526 | 	if isTestModule { | 
 | 527 | 		return true | 
 | 528 | 	} | 
 | 529 |  | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 530 | 	moduleName := moduleNameWithPossibleOverride(ctx, module, p.moduleName) | 
| Cole Faust | 324a92e | 2022-08-23 15:29:05 -0700 | [diff] [blame] | 531 | 	allowlist := ctx.Config().Bp2buildPackageConfig | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 532 | 	moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName] | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 533 | 	moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[p.moduleType] | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 534 | 	allowlistConvert := moduleNameAllowed || moduleTypeAllowed | 
 | 535 | 	if moduleNameAllowed && moduleTypeAllowed { | 
 | 536 | 		ctx.ModuleErrorf("A module cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert") | 
 | 537 | 		return false | 
 | 538 | 	} | 
 | 539 |  | 
 | 540 | 	if allowlist.moduleDoNotConvert[moduleName] { | 
| Sam Delmerico | 85d831a | 2022-03-07 19:12:42 +0000 | [diff] [blame] | 541 | 		if moduleNameAllowed { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 542 | 			ctx.ModuleErrorf("a module cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert") | 
| Sam Delmerico | 85d831a | 2022-03-07 19:12:42 +0000 | [diff] [blame] | 543 | 		} | 
| Sam Delmerico | 94d26c2 | 2022-02-25 21:34:51 +0000 | [diff] [blame] | 544 | 		return false | 
 | 545 | 	} | 
 | 546 |  | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 547 | 	// This is a tristate value: true, false, or unset. | 
 | 548 | 	if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok { | 
 | 549 | 		if moduleNameAllowed { | 
 | 550 | 			ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+ | 
| Yu Liu | 10853f9 | 2022-09-14 16:05:22 -0700 | [diff] [blame] | 551 | 				" or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'"+ | 
 | 552 | 				" Module: '%s'", directoryPath, moduleName) | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 553 | 			return false | 
| Sam Delmerico | fa1831c | 2022-02-22 18:07:55 +0000 | [diff] [blame] | 554 | 		} | 
 | 555 |  | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 556 | 		// Allow modules to explicitly opt-out. | 
 | 557 | 		return proptools.BoolDefault(propValue, true) | 
 | 558 | 	} | 
 | 559 |  | 
 | 560 | 	// Allow modules to explicitly opt-in. | 
| Sam Delmerico | 85d831a | 2022-03-07 19:12:42 +0000 | [diff] [blame] | 561 | 	return proptools.BoolDefault(propValue, allowlistConvert) | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 562 | } | 
 | 563 |  | 
 | 564 | // bp2buildDefaultTrueRecursively checks that the package contains a prefix from the | 
 | 565 | // set of package prefixes where all modules must be converted. That is, if the | 
 | 566 | // package is x/y/z, and the list contains either x, x/y, or x/y/z, this function will | 
 | 567 | // return true. | 
 | 568 | // | 
 | 569 | // However, if the package is x/y, and it matches a Bp2BuildDefaultFalse "x/y" entry | 
 | 570 | // exactly, this module will return false early. | 
 | 571 | // | 
 | 572 | // This function will also return false if the package doesn't match anything in | 
 | 573 | // the config. | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 574 | // | 
 | 575 | // This function will also return the allowlist entry which caused a particular | 
 | 576 | // package to be enabled. Since packages can be enabled via a recursive declaration, | 
 | 577 | // the path returned will not always be the same as the one provided. | 
 | 578 | func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2BuildConfig) (bool, string) { | 
| Jingwen Chen | 294e774 | 2021-08-31 05:58:01 +0000 | [diff] [blame] | 579 | 	// Check if the package path has an exact match in the config. | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 580 | 	if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively { | 
 | 581 | 		return true, packagePath | 
| MarkDacek | 756b296 | 2022-10-13 17:50:17 +0000 | [diff] [blame] | 582 | 	} else if config[packagePath] == allowlists.Bp2BuildDefaultFalse || config[packagePath] == allowlists.Bp2BuildDefaultFalseRecursively { | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 583 | 		return false, packagePath | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 584 | 	} | 
 | 585 |  | 
| Jingwen Chen | 91220d7 | 2021-03-24 02:18:33 -0400 | [diff] [blame] | 586 | 	// If not, check for the config recursively. | 
| MarkDacek | 756b296 | 2022-10-13 17:50:17 +0000 | [diff] [blame] | 587 | 	packagePrefix := packagePath | 
 | 588 |  | 
 | 589 | 	// e.g. for x/y/z, iterate over x/y, then x, taking the most-specific value from the allowlist. | 
 | 590 | 	for strings.Contains(packagePrefix, "/") { | 
 | 591 | 		dirIndex := strings.LastIndex(packagePrefix, "/") | 
 | 592 | 		packagePrefix = packagePrefix[:dirIndex] | 
 | 593 | 		switch value := config[packagePrefix]; value { | 
 | 594 | 		case allowlists.Bp2BuildDefaultTrueRecursively: | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 595 | 			// package contains this prefix and this prefix should convert all modules | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 596 | 			return true, packagePrefix | 
| MarkDacek | 756b296 | 2022-10-13 17:50:17 +0000 | [diff] [blame] | 597 | 		case allowlists.Bp2BuildDefaultFalseRecursively: | 
 | 598 | 			//package contains this prefix and this prefix should NOT convert any modules | 
 | 599 | 			return false, packagePrefix | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 600 | 		} | 
 | 601 | 		// Continue to the next part of the package dir. | 
| MarkDacek | 756b296 | 2022-10-13 17:50:17 +0000 | [diff] [blame] | 602 |  | 
| Jingwen Chen | 12b4c27 | 2021-03-10 02:05:59 -0500 | [diff] [blame] | 603 | 	} | 
 | 604 |  | 
| Sam Delmerico | 24c5603 | 2022-03-28 19:53:03 +0000 | [diff] [blame] | 605 | 	return false, packagePath | 
| Liz Kammer | ea6666f | 2021-02-17 10:17:28 -0500 | [diff] [blame] | 606 | } | 
| Liz Kammer | ba3ea16 | 2021-02-17 13:22:03 -0500 | [diff] [blame] | 607 |  | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 608 | func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) { | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 609 | 	ctx.TopDown("bp2build_conversion", bp2buildConversionMutator).Parallel() | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 610 | } | 
 | 611 |  | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 612 | func bp2buildConversionMutator(ctx TopDownMutatorContext) { | 
| Chris Parsons | 8152a94 | 2023-06-06 16:17:50 +0000 | [diff] [blame] | 613 | 	if ctx.Config().HasBazelBuildTargetInSource(ctx) { | 
 | 614 | 		// Defer to the BUILD target. Generating an additional target would | 
 | 615 | 		// cause a BUILD file conflict. | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 616 | 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "") | 
| Chris Parsons | 8152a94 | 2023-06-06 16:17:50 +0000 | [diff] [blame] | 617 | 		return | 
 | 618 | 	} | 
 | 619 |  | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 620 | 	bModule, ok := ctx.Module().(Bazelable) | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 621 | 	if !ok { | 
 | 622 | 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 623 | 		return | 
 | 624 | 	} | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 625 | 	// There may be cases where the target is created by a macro rather than in a BUILD file, those | 
 | 626 | 	// should be captured as well. | 
 | 627 | 	if bModule.HasHandcraftedLabel() { | 
 | 628 | 		// Defer to the BUILD target. Generating an additional target would | 
 | 629 | 		// cause a BUILD file conflict. | 
 | 630 | 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "") | 
 | 631 | 		return | 
 | 632 | 	} | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 633 | 	// TODO: b/285631638 - Differentiate between denylisted modules and missing bp2build capabilities. | 
| Liz Kammer | c86e094 | 2023-08-11 16:15:12 -0400 | [diff] [blame] | 634 | 	if !bModule.shouldConvertWithBp2build(ctx, shouldConvertParams{ | 
 | 635 | 		module:     ctx.Module(), | 
 | 636 | 		moduleDir:  ctx.ModuleDir(), | 
 | 637 | 		moduleName: ctx.ModuleName(), | 
 | 638 | 		moduleType: ctx.ModuleType(), | 
 | 639 | 	}) { | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 640 | 		ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "") | 
 | 641 | 		return | 
 | 642 | 	} | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 643 | 	bModule.ConvertWithBp2build(ctx) | 
| Chris Parsons | 39a1697 | 2023-06-08 14:28:51 +0000 | [diff] [blame] | 644 |  | 
 | 645 | 	if !ctx.Module().base().IsConvertedByBp2build() && ctx.Module().base().GetUnconvertedReason() == nil { | 
 | 646 | 		panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName())) | 
 | 647 | 	} | 
| Liz Kammer | be46fcc | 2021-11-01 15:32:43 -0400 | [diff] [blame] | 648 | } | 
| Wei Li | bafb6d6 | 2021-12-10 03:14:59 -0800 | [diff] [blame] | 649 |  | 
| Spandan Das | 5af0bd3 | 2022-09-28 20:43:08 +0000 | [diff] [blame] | 650 | func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) { | 
 | 651 | 	ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel() | 
 | 652 | } | 
 | 653 |  | 
 | 654 | // Generate API contribution targets if the Soong module provides APIs | 
 | 655 | func convertWithApiBp2build(ctx TopDownMutatorContext) { | 
 | 656 | 	if m, ok := ctx.Module().(ApiProvider); ok { | 
 | 657 | 		m.ConvertWithApiBp2build(ctx) | 
 | 658 | 	} | 
 | 659 | } | 
 | 660 |  | 
| Wei Li | bafb6d6 | 2021-12-10 03:14:59 -0800 | [diff] [blame] | 661 | // GetMainClassInManifest scans the manifest file specified in filepath and returns | 
 | 662 | // the value of attribute Main-Class in the manifest file if it exists, or returns error. | 
 | 663 | // WARNING: this is for bp2build converters of java_* modules only. | 
 | 664 | func GetMainClassInManifest(c Config, filepath string) (string, error) { | 
 | 665 | 	file, err := c.fs.Open(filepath) | 
 | 666 | 	if err != nil { | 
 | 667 | 		return "", err | 
 | 668 | 	} | 
| Liz Kammer | 0fe123d | 2022-02-07 10:17:35 -0500 | [diff] [blame] | 669 | 	defer file.Close() | 
| Wei Li | bafb6d6 | 2021-12-10 03:14:59 -0800 | [diff] [blame] | 670 | 	scanner := bufio.NewScanner(file) | 
 | 671 | 	for scanner.Scan() { | 
 | 672 | 		line := scanner.Text() | 
 | 673 | 		if strings.HasPrefix(line, "Main-Class:") { | 
 | 674 | 			return strings.TrimSpace(line[len("Main-Class:"):]), nil | 
 | 675 | 		} | 
 | 676 | 	} | 
 | 677 |  | 
 | 678 | 	return "", errors.New("Main-Class is not found.") | 
 | 679 | } | 
| Sam Delmerico | 4ed95e2 | 2023-02-03 18:12:15 -0500 | [diff] [blame] | 680 |  | 
 | 681 | func AttachValidationActions(ctx ModuleContext, outputFilePath Path, validations Paths) ModuleOutPath { | 
 | 682 | 	validatedOutputFilePath := PathForModuleOut(ctx, "validated", outputFilePath.Base()) | 
 | 683 | 	ctx.Build(pctx, BuildParams{ | 
 | 684 | 		Rule:        CpNoPreserveSymlink, | 
 | 685 | 		Description: "run validations " + outputFilePath.Base(), | 
 | 686 | 		Output:      validatedOutputFilePath, | 
 | 687 | 		Input:       outputFilePath, | 
 | 688 | 		Validations: validations, | 
 | 689 | 	}) | 
 | 690 | 	return validatedOutputFilePath | 
 | 691 | } | 
| yike | fdca7fe | 2023-08-17 01:03:37 +0000 | [diff] [blame] | 692 |  | 
 | 693 | func RunsOn(hostSupported bool, deviceSupported bool, unitTest bool) []string { | 
 | 694 | 	var runsOn []string | 
 | 695 |  | 
 | 696 | 	if hostSupported && deviceSupported { | 
 | 697 | 		runsOn = []string{"host_without_device", "device"} | 
 | 698 | 	} else if hostSupported { | 
 | 699 | 		if unitTest { | 
 | 700 | 			runsOn = []string{"host_without_device"} | 
 | 701 | 		} else { | 
 | 702 | 			runsOn = []string{"host_with_device"} | 
 | 703 | 		} | 
 | 704 | 	} else if deviceSupported { | 
 | 705 | 		runsOn = []string{"device"} | 
 | 706 | 	} | 
 | 707 |  | 
 | 708 | 	return runsOn | 
 | 709 | } |