blob: 3a65614da2a5535c1df51ba4f16b074a8ddcaa60 [file] [log] [blame]
Liz Kammer9abd62d2021-05-21 08:37:59 -04001// 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
15package bazel
16
17import (
18 "fmt"
Cole Faustc843b992022-08-02 18:06:50 -070019 "math"
20 "sort"
Liz Kammer9abd62d2021-05-21 08:37:59 -040021 "strings"
22)
23
24const (
25 // ArchType names in arch.go
Colin Crossf05b0d32022-07-14 18:10:34 -070026 archArm = "arm"
27 archArm64 = "arm64"
28 archRiscv64 = "riscv64"
29 archX86 = "x86"
30 archX86_64 = "x86_64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040031
32 // OsType names in arch.go
Wei Li81852ca2022-07-27 00:22:06 -070033 OsAndroid = "android"
Spandan Dasfb04c412023-05-15 18:35:36 +000034 OsDarwin = "darwin"
35 OsLinux = "linux_glibc"
Colin Cross528d67e2021-07-23 22:23:07 +000036 osLinuxMusl = "linux_musl"
Liz Kammer9abd62d2021-05-21 08:37:59 -040037 osLinuxBionic = "linux_bionic"
Spandan Dasfb04c412023-05-15 18:35:36 +000038 OsWindows = "windows"
Liz Kammer9abd62d2021-05-21 08:37:59 -040039
40 // Targets in arch.go
41 osArchAndroidArm = "android_arm"
Yu Liu7ece4aa2023-08-25 16:56:33 -070042 OsArchAndroidArm64 = "android_arm64"
Colin Crossf05b0d32022-07-14 18:10:34 -070043 osArchAndroidRiscv64 = "android_riscv64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040044 osArchAndroidX86 = "android_x86"
45 osArchAndroidX86_64 = "android_x86_64"
Dan Willemsen8528f4e2021-10-19 00:22:06 -070046 osArchDarwinArm64 = "darwin_arm64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040047 osArchDarwinX86_64 = "darwin_x86_64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040048 osArchLinuxX86 = "linux_glibc_x86"
49 osArchLinuxX86_64 = "linux_glibc_x86_64"
Colin Crossa9b2aac2022-06-15 17:25:51 -070050 osArchLinuxMuslArm = "linux_musl_arm"
51 osArchLinuxMuslArm64 = "linux_musl_arm64"
Colin Cross528d67e2021-07-23 22:23:07 +000052 osArchLinuxMuslX86 = "linux_musl_x86"
53 osArchLinuxMuslX86_64 = "linux_musl_x86_64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040054 osArchLinuxBionicArm64 = "linux_bionic_arm64"
55 osArchLinuxBionicX86_64 = "linux_bionic_x86_64"
56 osArchWindowsX86 = "windows_x86"
57 osArchWindowsX86_64 = "windows_x86_64"
58
59 // This is the string representation of the default condition wherever a
60 // configurable attribute is used in a select statement, i.e.
61 // //conditions:default for Bazel.
62 //
63 // This is consistently named "conditions_default" to mirror the Soong
64 // config variable default key in an Android.bp file, although there's no
65 // integration with Soong config variables (yet).
Chris Parsons51f8c392021-08-03 21:01:05 -040066 ConditionsDefaultConfigKey = "conditions_default"
Liz Kammer9abd62d2021-05-21 08:37:59 -040067
68 ConditionsDefaultSelectKey = "//conditions:default"
69
Cole Faust87c0c332023-07-31 12:10:12 -070070 productVariableBazelPackage = "//build/bazel/product_config/config_settings"
Wei Li81852ca2022-07-27 00:22:06 -070071
Spandan Das6d4d9da2023-04-18 06:20:40 +000072 AndroidAndInApex = "android-in_apex"
73 AndroidPlatform = "system"
Spandan Das1f65f9e2023-09-15 01:08:23 +000074 Unbundled_app = "unbundled_app"
Vinh Tran85fb07c2022-09-16 16:17:48 -040075
76 InApex = "in_apex"
77 NonApex = "non_apex"
Alixc0dac522023-05-04 21:20:16 +000078
79 ErrorproneDisabled = "errorprone_disabled"
Trevor Radcliffed9b7f172023-08-09 22:21:38 +000080 // TODO: b/294868620 - Remove when completing the bug
81 SanitizersEnabled = "sanitizers_enabled"
Liz Kammer9abd62d2021-05-21 08:37:59 -040082)
83
Cole Faustc843b992022-08-02 18:06:50 -070084func PowerSetWithoutEmptySet[T any](items []T) [][]T {
85 resultSize := int(math.Pow(2, float64(len(items))))
86 powerSet := make([][]T, 0, resultSize-1)
87 for i := 1; i < resultSize; i++ {
88 combination := make([]T, 0)
89 for j := 0; j < len(items); j++ {
90 if (i>>j)%2 == 1 {
91 combination = append(combination, items[j])
92 }
93 }
94 powerSet = append(powerSet, combination)
95 }
96 return powerSet
97}
98
99func createPlatformArchMap() map[string]string {
100 // Copy of archFeatures from android/arch_list.go because the bazel
101 // package can't access the android package
102 archFeatures := map[string][]string{
Elliott Hughese9c49d52024-09-27 15:29:57 +0000103 "arm": {},
Cole Faustc843b992022-08-02 18:06:50 -0700104 "arm64": {
105 "dotprod",
106 },
Colin Crossf05b0d32022-07-14 18:10:34 -0700107 "riscv64": {},
Cole Faustc843b992022-08-02 18:06:50 -0700108 "x86": {
109 "ssse3",
110 "sse4",
111 "sse4_1",
112 "sse4_2",
113 "aes_ni",
114 "avx",
115 "avx2",
116 "avx512",
117 "popcnt",
118 "movbe",
119 },
120 "x86_64": {
121 "ssse3",
122 "sse4",
123 "sse4_1",
124 "sse4_2",
125 "aes_ni",
126 "avx",
127 "avx2",
128 "avx512",
129 "popcnt",
130 },
131 }
132 result := make(map[string]string)
133 for arch, allFeatures := range archFeatures {
Jingwen Chen9c2e3ee2023-10-11 10:51:28 +0000134 result[arch] = "//build/bazel_common_rules/platforms/arch:" + arch
Cole Faustc843b992022-08-02 18:06:50 -0700135 // Sometimes we want to select on multiple features being active, so
136 // add the power set of all possible features to the map. More details
137 // in android.ModuleBase.GetArchVariantProperties
138 for _, features := range PowerSetWithoutEmptySet(allFeatures) {
139 sort.Strings(features)
140 archFeaturesName := arch + "-" + strings.Join(features, "-")
141 result[archFeaturesName] = "//build/bazel/platforms/arch/variants:" + archFeaturesName
142 }
143 }
144 result[ConditionsDefaultConfigKey] = ConditionsDefaultSelectKey
145 return result
146}
147
Liz Kammer9abd62d2021-05-21 08:37:59 -0400148var (
149 // These are the list of OSes and architectures with a Bazel config_setting
150 // and constraint value equivalent. These exist in arch.go, but the android
151 // package depends on the bazel package, so a cyclic dependency prevents
152 // using those variables here.
153
154 // A map of architectures to the Bazel label of the constraint_value
155 // for the @platforms//cpu:cpu constraint_setting
Cole Faustc843b992022-08-02 18:06:50 -0700156 platformArchMap = createPlatformArchMap()
Liz Kammer9abd62d2021-05-21 08:37:59 -0400157
158 // A map of target operating systems to the Bazel label of the
159 // constraint_value for the @platforms//os:os constraint_setting
160 platformOsMap = map[string]string{
Jingwen Chen9c2e3ee2023-10-11 10:51:28 +0000161 OsAndroid: "//build/bazel_common_rules/platforms/os:android",
162 OsDarwin: "//build/bazel_common_rules/platforms/os:darwin",
163 OsLinux: "//build/bazel_common_rules/platforms/os:linux_glibc",
164 osLinuxMusl: "//build/bazel_common_rules/platforms/os:linux_musl",
165 osLinuxBionic: "//build/bazel_common_rules/platforms/os:linux_bionic",
166 OsWindows: "//build/bazel_common_rules/platforms/os:windows",
Chris Parsons51f8c392021-08-03 21:01:05 -0400167 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -0400168 }
169
170 platformOsArchMap = map[string]string{
Jingwen Chen9c2e3ee2023-10-11 10:51:28 +0000171 osArchAndroidArm: "//build/bazel_common_rules/platforms/os_arch:android_arm",
172 OsArchAndroidArm64: "//build/bazel_common_rules/platforms/os_arch:android_arm64",
173 osArchAndroidRiscv64: "//build/bazel_common_rules/platforms/os_arch:android_riscv64",
174 osArchAndroidX86: "//build/bazel_common_rules/platforms/os_arch:android_x86",
175 osArchAndroidX86_64: "//build/bazel_common_rules/platforms/os_arch:android_x86_64",
176 osArchDarwinArm64: "//build/bazel_common_rules/platforms/os_arch:darwin_arm64",
177 osArchDarwinX86_64: "//build/bazel_common_rules/platforms/os_arch:darwin_x86_64",
178 osArchLinuxX86: "//build/bazel_common_rules/platforms/os_arch:linux_glibc_x86",
179 osArchLinuxX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_glibc_x86_64",
180 osArchLinuxMuslArm: "//build/bazel_common_rules/platforms/os_arch:linux_musl_arm",
181 osArchLinuxMuslArm64: "//build/bazel_common_rules/platforms/os_arch:linux_musl_arm64",
182 osArchLinuxMuslX86: "//build/bazel_common_rules/platforms/os_arch:linux_musl_x86",
183 osArchLinuxMuslX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_musl_x86_64",
184 osArchLinuxBionicArm64: "//build/bazel_common_rules/platforms/os_arch:linux_bionic_arm64",
185 osArchLinuxBionicX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_bionic_x86_64",
186 osArchWindowsX86: "//build/bazel_common_rules/platforms/os_arch:windows_x86",
187 osArchWindowsX86_64: "//build/bazel_common_rules/platforms/os_arch:windows_x86_64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400188 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -0400189 }
Chris Parsons58852a02021-12-09 18:10:18 -0500190
191 // Map where keys are OsType names, and values are slices containing the archs
192 // that that OS supports.
193 // These definitions copied from arch.go.
194 // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
195 // in a cyclic dependency.
196 osToArchMap = map[string][]string{
Colin Crossf05b0d32022-07-14 18:10:34 -0700197 OsAndroid: {archArm, archArm64, archRiscv64, archX86, archX86_64},
Spandan Dasfb04c412023-05-15 18:35:36 +0000198 OsLinux: {archX86, archX86_64},
Chris Parsons58852a02021-12-09 18:10:18 -0500199 osLinuxMusl: {archX86, archX86_64},
Spandan Dasfb04c412023-05-15 18:35:36 +0000200 OsDarwin: {archArm64, archX86_64},
Chris Parsons58852a02021-12-09 18:10:18 -0500201 osLinuxBionic: {archArm64, archX86_64},
202 // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
Spandan Dasfb04c412023-05-15 18:35:36 +0000203 OsWindows: {archX86, archX86_64},
Chris Parsons58852a02021-12-09 18:10:18 -0500204 }
Wei Li81852ca2022-07-27 00:22:06 -0700205
206 osAndInApexMap = map[string]string{
207 AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
Spandan Das6d4d9da2023-04-18 06:20:40 +0000208 AndroidPlatform: "//build/bazel/rules/apex:system",
Spandan Das1f65f9e2023-09-15 01:08:23 +0000209 Unbundled_app: "//build/bazel/rules/apex:unbundled_app",
Jingwen Chen9c2e3ee2023-10-11 10:51:28 +0000210 OsDarwin: "//build/bazel_common_rules/platforms/os:darwin",
211 OsLinux: "//build/bazel_common_rules/platforms/os:linux_glibc",
212 osLinuxMusl: "//build/bazel_common_rules/platforms/os:linux_musl",
213 osLinuxBionic: "//build/bazel_common_rules/platforms/os:linux_bionic",
214 OsWindows: "//build/bazel_common_rules/platforms/os:windows",
Wei Li81852ca2022-07-27 00:22:06 -0700215 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
216 }
Vinh Tran85fb07c2022-09-16 16:17:48 -0400217
218 inApexMap = map[string]string{
219 InApex: "//build/bazel/rules/apex:in_apex",
220 NonApex: "//build/bazel/rules/apex:non_apex",
221 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
222 }
Alixc0dac522023-05-04 21:20:16 +0000223
224 errorProneMap = map[string]string{
225 ErrorproneDisabled: "//build/bazel/rules/java/errorprone:errorprone_globally_disabled",
226 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
227 }
Trevor Radcliffed9b7f172023-08-09 22:21:38 +0000228
229 // TODO: b/294868620 - Remove when completing the bug
230 sanitizersEnabledMap = map[string]string{
231 SanitizersEnabled: "//build/bazel/rules/cc:sanitizers_enabled",
232 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
233 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400234)
235
236// basic configuration types
237type configurationType int
238
239const (
240 noConfig configurationType = iota
241 arch
242 os
243 osArch
244 productVariables
Wei Li81852ca2022-07-27 00:22:06 -0700245 osAndInApex
Vinh Tran85fb07c2022-09-16 16:17:48 -0400246 inApex
Alixc0dac522023-05-04 21:20:16 +0000247 errorProneDisabled
Trevor Radcliffed9b7f172023-08-09 22:21:38 +0000248 // TODO: b/294868620 - Remove when completing the bug
249 sanitizersEnabled
Liz Kammer9abd62d2021-05-21 08:37:59 -0400250)
251
Chris Parsons58852a02021-12-09 18:10:18 -0500252func osArchString(os string, arch string) string {
253 return fmt.Sprintf("%s_%s", os, arch)
254}
255
Liz Kammer9abd62d2021-05-21 08:37:59 -0400256func (ct configurationType) String() string {
257 return map[configurationType]string{
Alixc0dac522023-05-04 21:20:16 +0000258 noConfig: "no_config",
259 arch: "arch",
260 os: "os",
261 osArch: "arch_os",
262 productVariables: "product_variables",
263 osAndInApex: "os_in_apex",
264 inApex: "in_apex",
265 errorProneDisabled: "errorprone_disabled",
Trevor Radcliffed9b7f172023-08-09 22:21:38 +0000266 // TODO: b/294868620 - Remove when completing the bug
267 sanitizersEnabled: "sanitizers_enabled",
Liz Kammer9abd62d2021-05-21 08:37:59 -0400268 }[ct]
269}
270
271func (ct configurationType) validateConfig(config string) {
272 switch ct {
273 case noConfig:
274 if config != "" {
275 panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
276 }
277 case arch:
278 if _, ok := platformArchMap[config]; !ok {
279 panic(fmt.Errorf("Unknown arch: %s", config))
280 }
281 case os:
282 if _, ok := platformOsMap[config]; !ok {
283 panic(fmt.Errorf("Unknown os: %s", config))
284 }
285 case osArch:
286 if _, ok := platformOsArchMap[config]; !ok {
287 panic(fmt.Errorf("Unknown os+arch: %s", config))
288 }
289 case productVariables:
290 // do nothing
Wei Li81852ca2022-07-27 00:22:06 -0700291 case osAndInApex:
Spandan Das4242f102023-04-19 22:31:54 +0000292 // do nothing
293 // this axis can contain additional per-apex keys
Vinh Tran85fb07c2022-09-16 16:17:48 -0400294 case inApex:
295 if _, ok := inApexMap[config]; !ok {
296 panic(fmt.Errorf("Unknown in_apex config: %s", config))
297 }
Alixc0dac522023-05-04 21:20:16 +0000298 case errorProneDisabled:
299 if _, ok := errorProneMap[config]; !ok {
300 panic(fmt.Errorf("Unknown errorprone config: %s", config))
301 }
Trevor Radcliffed9b7f172023-08-09 22:21:38 +0000302 // TODO: b/294868620 - Remove when completing the bug
303 case sanitizersEnabled:
304 if _, ok := sanitizersEnabledMap[config]; !ok {
305 panic(fmt.Errorf("Unknown sanitizers_enabled config: %s", config))
306 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400307 default:
308 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
309 }
310}
311
312// SelectKey returns the Bazel select key for a given configurationType and config string.
Jingwen Chena47f28d2021-11-02 16:43:57 +0000313func (ca ConfigurationAxis) SelectKey(config string) string {
314 ca.validateConfig(config)
315 switch ca.configurationType {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400316 case noConfig:
317 panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
318 case arch:
319 return platformArchMap[config]
320 case os:
321 return platformOsMap[config]
322 case osArch:
323 return platformOsArchMap[config]
324 case productVariables:
Cole Faust150f9a52023-04-26 10:52:24 -0700325 if config == ConditionsDefaultConfigKey {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400326 return ConditionsDefaultSelectKey
327 }
Jingwen Chena47f28d2021-11-02 16:43:57 +0000328 return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
Wei Li81852ca2022-07-27 00:22:06 -0700329 case osAndInApex:
Spandan Das4242f102023-04-19 22:31:54 +0000330 if ret, exists := osAndInApexMap[config]; exists {
331 return ret
332 }
333 return config
Vinh Tran85fb07c2022-09-16 16:17:48 -0400334 case inApex:
335 return inApexMap[config]
Alixc0dac522023-05-04 21:20:16 +0000336 case errorProneDisabled:
337 return errorProneMap[config]
Trevor Radcliffed9b7f172023-08-09 22:21:38 +0000338 // TODO: b/294868620 - Remove when completing the bug
339 case sanitizersEnabled:
340 return sanitizersEnabledMap[config]
Liz Kammer9abd62d2021-05-21 08:37:59 -0400341 default:
Jingwen Chena47f28d2021-11-02 16:43:57 +0000342 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400343 }
344}
345
346var (
347 // Indicating there is no configuration axis
348 NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
349 // An axis for architecture-specific configurations
350 ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
351 // An axis for os-specific configurations
352 OsConfigurationAxis = ConfigurationAxis{configurationType: os}
353 // An axis for arch+os-specific configurations
354 OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
Wei Li81852ca2022-07-27 00:22:06 -0700355 // An axis for os+in_apex-specific configurations
356 OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
Vinh Tran85fb07c2022-09-16 16:17:48 -0400357 // An axis for in_apex-specific configurations
358 InApexAxis = ConfigurationAxis{configurationType: inApex}
Alixc0dac522023-05-04 21:20:16 +0000359
360 ErrorProneAxis = ConfigurationAxis{configurationType: errorProneDisabled}
Trevor Radcliffed9b7f172023-08-09 22:21:38 +0000361
362 // TODO: b/294868620 - Remove when completing the bug
363 SanitizersEnabledAxis = ConfigurationAxis{configurationType: sanitizersEnabled}
Liz Kammer9abd62d2021-05-21 08:37:59 -0400364)
365
366// ProductVariableConfigurationAxis returns an axis for the given product variable
Cole Faust150f9a52023-04-26 10:52:24 -0700367func ProductVariableConfigurationAxis(archVariant bool, variable string) ConfigurationAxis {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400368 return ConfigurationAxis{
369 configurationType: productVariables,
370 subType: variable,
Cole Faust150f9a52023-04-26 10:52:24 -0700371 archVariant: archVariant,
Liz Kammer9abd62d2021-05-21 08:37:59 -0400372 }
373}
374
375// ConfigurationAxis is an independent axis for configuration, there should be no overlap between
376// elements within an axis.
377type ConfigurationAxis struct {
378 configurationType
379 // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
380 // distinguish between them without needing to list all 17 product variables.
381 subType string
Cole Faust150f9a52023-04-26 10:52:24 -0700382
383 archVariant bool
Liz Kammer9abd62d2021-05-21 08:37:59 -0400384}
385
386func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
Chris Parsons7b3289b2023-01-26 17:30:44 -0500387 if ca.configurationType == other.configurationType {
388 return ca.subType < other.subType
Liz Kammer9abd62d2021-05-21 08:37:59 -0400389 }
Chris Parsons7b3289b2023-01-26 17:30:44 -0500390 return ca.configurationType < other.configurationType
Liz Kammer9abd62d2021-05-21 08:37:59 -0400391}