blob: 671e5c14193e510444f9f7025ebb23abb7f40e78 [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"
42 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"
Vinh Tran85fb07c2022-09-16 16:17:48 -040074
75 InApex = "in_apex"
76 NonApex = "non_apex"
Alixc0dac522023-05-04 21:20:16 +000077
78 ErrorproneDisabled = "errorprone_disabled"
Liz Kammer9abd62d2021-05-21 08:37:59 -040079)
80
Cole Faustc843b992022-08-02 18:06:50 -070081func PowerSetWithoutEmptySet[T any](items []T) [][]T {
82 resultSize := int(math.Pow(2, float64(len(items))))
83 powerSet := make([][]T, 0, resultSize-1)
84 for i := 1; i < resultSize; i++ {
85 combination := make([]T, 0)
86 for j := 0; j < len(items); j++ {
87 if (i>>j)%2 == 1 {
88 combination = append(combination, items[j])
89 }
90 }
91 powerSet = append(powerSet, combination)
92 }
93 return powerSet
94}
95
96func createPlatformArchMap() map[string]string {
97 // Copy of archFeatures from android/arch_list.go because the bazel
98 // package can't access the android package
99 archFeatures := map[string][]string{
100 "arm": {
101 "neon",
102 },
103 "arm64": {
104 "dotprod",
105 },
Colin Crossf05b0d32022-07-14 18:10:34 -0700106 "riscv64": {},
Cole Faustc843b992022-08-02 18:06:50 -0700107 "x86": {
108 "ssse3",
109 "sse4",
110 "sse4_1",
111 "sse4_2",
112 "aes_ni",
113 "avx",
114 "avx2",
115 "avx512",
116 "popcnt",
117 "movbe",
118 },
119 "x86_64": {
120 "ssse3",
121 "sse4",
122 "sse4_1",
123 "sse4_2",
124 "aes_ni",
125 "avx",
126 "avx2",
127 "avx512",
128 "popcnt",
129 },
130 }
131 result := make(map[string]string)
132 for arch, allFeatures := range archFeatures {
133 result[arch] = "//build/bazel/platforms/arch:" + arch
134 // Sometimes we want to select on multiple features being active, so
135 // add the power set of all possible features to the map. More details
136 // in android.ModuleBase.GetArchVariantProperties
137 for _, features := range PowerSetWithoutEmptySet(allFeatures) {
138 sort.Strings(features)
139 archFeaturesName := arch + "-" + strings.Join(features, "-")
140 result[archFeaturesName] = "//build/bazel/platforms/arch/variants:" + archFeaturesName
141 }
142 }
143 result[ConditionsDefaultConfigKey] = ConditionsDefaultSelectKey
144 return result
145}
146
Liz Kammer9abd62d2021-05-21 08:37:59 -0400147var (
148 // These are the list of OSes and architectures with a Bazel config_setting
149 // and constraint value equivalent. These exist in arch.go, but the android
150 // package depends on the bazel package, so a cyclic dependency prevents
151 // using those variables here.
152
153 // A map of architectures to the Bazel label of the constraint_value
154 // for the @platforms//cpu:cpu constraint_setting
Cole Faustc843b992022-08-02 18:06:50 -0700155 platformArchMap = createPlatformArchMap()
Liz Kammer9abd62d2021-05-21 08:37:59 -0400156
157 // A map of target operating systems to the Bazel label of the
158 // constraint_value for the @platforms//os:os constraint_setting
159 platformOsMap = map[string]string{
Wei Li81852ca2022-07-27 00:22:06 -0700160 OsAndroid: "//build/bazel/platforms/os:android",
Spandan Dasfb04c412023-05-15 18:35:36 +0000161 OsDarwin: "//build/bazel/platforms/os:darwin",
162 OsLinux: "//build/bazel/platforms/os:linux_glibc",
Chris Parsons51f8c392021-08-03 21:01:05 -0400163 osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
164 osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
Spandan Dasfb04c412023-05-15 18:35:36 +0000165 OsWindows: "//build/bazel/platforms/os:windows",
Chris Parsons51f8c392021-08-03 21:01:05 -0400166 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -0400167 }
168
169 platformOsArchMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -0400170 osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
171 osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
Colin Crossf05b0d32022-07-14 18:10:34 -0700172 osArchAndroidRiscv64: "//build/bazel/platforms/os_arch:android_riscv64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400173 osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
174 osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
Dan Willemsen8528f4e2021-10-19 00:22:06 -0700175 osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400176 osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
177 osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
178 osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
Colin Crossa9b2aac2022-06-15 17:25:51 -0700179 osArchLinuxMuslArm: "//build/bazel/platforms/os_arch:linux_musl_arm",
180 osArchLinuxMuslArm64: "//build/bazel/platforms/os_arch:linux_musl_arm64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400181 osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
182 osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
183 osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
184 osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
185 osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
186 osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
187 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -0400188 }
Chris Parsons58852a02021-12-09 18:10:18 -0500189
190 // Map where keys are OsType names, and values are slices containing the archs
191 // that that OS supports.
192 // These definitions copied from arch.go.
193 // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
194 // in a cyclic dependency.
195 osToArchMap = map[string][]string{
Colin Crossf05b0d32022-07-14 18:10:34 -0700196 OsAndroid: {archArm, archArm64, archRiscv64, archX86, archX86_64},
Spandan Dasfb04c412023-05-15 18:35:36 +0000197 OsLinux: {archX86, archX86_64},
Chris Parsons58852a02021-12-09 18:10:18 -0500198 osLinuxMusl: {archX86, archX86_64},
Spandan Dasfb04c412023-05-15 18:35:36 +0000199 OsDarwin: {archArm64, archX86_64},
Chris Parsons58852a02021-12-09 18:10:18 -0500200 osLinuxBionic: {archArm64, archX86_64},
201 // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
Spandan Dasfb04c412023-05-15 18:35:36 +0000202 OsWindows: {archX86, archX86_64},
Chris Parsons58852a02021-12-09 18:10:18 -0500203 }
Wei Li81852ca2022-07-27 00:22:06 -0700204
205 osAndInApexMap = map[string]string{
206 AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
Spandan Das6d4d9da2023-04-18 06:20:40 +0000207 AndroidPlatform: "//build/bazel/rules/apex:system",
Spandan Dasfb04c412023-05-15 18:35:36 +0000208 OsDarwin: "//build/bazel/platforms/os:darwin",
209 OsLinux: "//build/bazel/platforms/os:linux_glibc",
Liz Kammerffc17e42022-11-23 09:42:05 -0500210 osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
211 osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
Spandan Dasfb04c412023-05-15 18:35:36 +0000212 OsWindows: "//build/bazel/platforms/os:windows",
Wei Li81852ca2022-07-27 00:22:06 -0700213 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
214 }
Vinh Tran85fb07c2022-09-16 16:17:48 -0400215
216 inApexMap = map[string]string{
217 InApex: "//build/bazel/rules/apex:in_apex",
218 NonApex: "//build/bazel/rules/apex:non_apex",
219 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
220 }
Alixc0dac522023-05-04 21:20:16 +0000221
222 errorProneMap = map[string]string{
223 ErrorproneDisabled: "//build/bazel/rules/java/errorprone:errorprone_globally_disabled",
224 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
225 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400226)
227
228// basic configuration types
229type configurationType int
230
231const (
232 noConfig configurationType = iota
233 arch
234 os
235 osArch
236 productVariables
Wei Li81852ca2022-07-27 00:22:06 -0700237 osAndInApex
Vinh Tran85fb07c2022-09-16 16:17:48 -0400238 inApex
Alixc0dac522023-05-04 21:20:16 +0000239 errorProneDisabled
Liz Kammer9abd62d2021-05-21 08:37:59 -0400240)
241
Chris Parsons58852a02021-12-09 18:10:18 -0500242func osArchString(os string, arch string) string {
243 return fmt.Sprintf("%s_%s", os, arch)
244}
245
Liz Kammer9abd62d2021-05-21 08:37:59 -0400246func (ct configurationType) String() string {
247 return map[configurationType]string{
Alixc0dac522023-05-04 21:20:16 +0000248 noConfig: "no_config",
249 arch: "arch",
250 os: "os",
251 osArch: "arch_os",
252 productVariables: "product_variables",
253 osAndInApex: "os_in_apex",
254 inApex: "in_apex",
255 errorProneDisabled: "errorprone_disabled",
Liz Kammer9abd62d2021-05-21 08:37:59 -0400256 }[ct]
257}
258
259func (ct configurationType) validateConfig(config string) {
260 switch ct {
261 case noConfig:
262 if config != "" {
263 panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
264 }
265 case arch:
266 if _, ok := platformArchMap[config]; !ok {
267 panic(fmt.Errorf("Unknown arch: %s", config))
268 }
269 case os:
270 if _, ok := platformOsMap[config]; !ok {
271 panic(fmt.Errorf("Unknown os: %s", config))
272 }
273 case osArch:
274 if _, ok := platformOsArchMap[config]; !ok {
275 panic(fmt.Errorf("Unknown os+arch: %s", config))
276 }
277 case productVariables:
278 // do nothing
Wei Li81852ca2022-07-27 00:22:06 -0700279 case osAndInApex:
Spandan Das4242f102023-04-19 22:31:54 +0000280 // do nothing
281 // this axis can contain additional per-apex keys
Vinh Tran85fb07c2022-09-16 16:17:48 -0400282 case inApex:
283 if _, ok := inApexMap[config]; !ok {
284 panic(fmt.Errorf("Unknown in_apex config: %s", config))
285 }
Alixc0dac522023-05-04 21:20:16 +0000286 case errorProneDisabled:
287 if _, ok := errorProneMap[config]; !ok {
288 panic(fmt.Errorf("Unknown errorprone config: %s", config))
289 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400290 default:
291 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
292 }
293}
294
295// SelectKey returns the Bazel select key for a given configurationType and config string.
Jingwen Chena47f28d2021-11-02 16:43:57 +0000296func (ca ConfigurationAxis) SelectKey(config string) string {
297 ca.validateConfig(config)
298 switch ca.configurationType {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400299 case noConfig:
300 panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
301 case arch:
302 return platformArchMap[config]
303 case os:
304 return platformOsMap[config]
305 case osArch:
306 return platformOsArchMap[config]
307 case productVariables:
Cole Faust150f9a52023-04-26 10:52:24 -0700308 if config == ConditionsDefaultConfigKey {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400309 return ConditionsDefaultSelectKey
310 }
Jingwen Chena47f28d2021-11-02 16:43:57 +0000311 return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
Wei Li81852ca2022-07-27 00:22:06 -0700312 case osAndInApex:
Spandan Das4242f102023-04-19 22:31:54 +0000313 if ret, exists := osAndInApexMap[config]; exists {
314 return ret
315 }
316 return config
Vinh Tran85fb07c2022-09-16 16:17:48 -0400317 case inApex:
318 return inApexMap[config]
Alixc0dac522023-05-04 21:20:16 +0000319 case errorProneDisabled:
320 return errorProneMap[config]
Liz Kammer9abd62d2021-05-21 08:37:59 -0400321 default:
Jingwen Chena47f28d2021-11-02 16:43:57 +0000322 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400323 }
324}
325
326var (
327 // Indicating there is no configuration axis
328 NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
329 // An axis for architecture-specific configurations
330 ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
331 // An axis for os-specific configurations
332 OsConfigurationAxis = ConfigurationAxis{configurationType: os}
333 // An axis for arch+os-specific configurations
334 OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
Wei Li81852ca2022-07-27 00:22:06 -0700335 // An axis for os+in_apex-specific configurations
336 OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
Vinh Tran85fb07c2022-09-16 16:17:48 -0400337 // An axis for in_apex-specific configurations
338 InApexAxis = ConfigurationAxis{configurationType: inApex}
Alixc0dac522023-05-04 21:20:16 +0000339
340 ErrorProneAxis = ConfigurationAxis{configurationType: errorProneDisabled}
Liz Kammer9abd62d2021-05-21 08:37:59 -0400341)
342
343// ProductVariableConfigurationAxis returns an axis for the given product variable
Cole Faust150f9a52023-04-26 10:52:24 -0700344func ProductVariableConfigurationAxis(archVariant bool, variable string) ConfigurationAxis {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400345 return ConfigurationAxis{
346 configurationType: productVariables,
347 subType: variable,
Cole Faust150f9a52023-04-26 10:52:24 -0700348 archVariant: archVariant,
Liz Kammer9abd62d2021-05-21 08:37:59 -0400349 }
350}
351
352// ConfigurationAxis is an independent axis for configuration, there should be no overlap between
353// elements within an axis.
354type ConfigurationAxis struct {
355 configurationType
356 // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
357 // distinguish between them without needing to list all 17 product variables.
358 subType string
Cole Faust150f9a52023-04-26 10:52:24 -0700359
360 archVariant bool
Liz Kammer9abd62d2021-05-21 08:37:59 -0400361}
362
363func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
Chris Parsons7b3289b2023-01-26 17:30:44 -0500364 if ca.configurationType == other.configurationType {
365 return ca.subType < other.subType
Liz Kammer9abd62d2021-05-21 08:37:59 -0400366 }
Chris Parsons7b3289b2023-01-26 17:30:44 -0500367 return ca.configurationType < other.configurationType
Liz Kammer9abd62d2021-05-21 08:37:59 -0400368}