blob: 0ab49eb1295d8ebbdc7867e23547593e1d740f33 [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"
19 "strings"
20)
21
22const (
23 // ArchType names in arch.go
24 archArm = "arm"
25 archArm64 = "arm64"
26 archX86 = "x86"
27 archX86_64 = "x86_64"
28
29 // OsType names in arch.go
30 osAndroid = "android"
31 osDarwin = "darwin"
Liz Kammer9abd62d2021-05-21 08:37:59 -040032 osLinux = "linux_glibc"
Colin Cross528d67e2021-07-23 22:23:07 +000033 osLinuxMusl = "linux_musl"
Liz Kammer9abd62d2021-05-21 08:37:59 -040034 osLinuxBionic = "linux_bionic"
35 osWindows = "windows"
36
37 // Targets in arch.go
38 osArchAndroidArm = "android_arm"
39 osArchAndroidArm64 = "android_arm64"
40 osArchAndroidX86 = "android_x86"
41 osArchAndroidX86_64 = "android_x86_64"
Dan Willemsen8528f4e2021-10-19 00:22:06 -070042 osArchDarwinArm64 = "darwin_arm64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040043 osArchDarwinX86_64 = "darwin_x86_64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040044 osArchLinuxX86 = "linux_glibc_x86"
45 osArchLinuxX86_64 = "linux_glibc_x86_64"
Colin Crossa9b2aac2022-06-15 17:25:51 -070046 osArchLinuxMuslArm = "linux_musl_arm"
47 osArchLinuxMuslArm64 = "linux_musl_arm64"
Colin Cross528d67e2021-07-23 22:23:07 +000048 osArchLinuxMuslX86 = "linux_musl_x86"
49 osArchLinuxMuslX86_64 = "linux_musl_x86_64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040050 osArchLinuxBionicArm64 = "linux_bionic_arm64"
51 osArchLinuxBionicX86_64 = "linux_bionic_x86_64"
52 osArchWindowsX86 = "windows_x86"
53 osArchWindowsX86_64 = "windows_x86_64"
54
55 // This is the string representation of the default condition wherever a
56 // configurable attribute is used in a select statement, i.e.
57 // //conditions:default for Bazel.
58 //
59 // This is consistently named "conditions_default" to mirror the Soong
60 // config variable default key in an Android.bp file, although there's no
61 // integration with Soong config variables (yet).
Chris Parsons51f8c392021-08-03 21:01:05 -040062 ConditionsDefaultConfigKey = "conditions_default"
Liz Kammer9abd62d2021-05-21 08:37:59 -040063
64 ConditionsDefaultSelectKey = "//conditions:default"
65
66 productVariableBazelPackage = "//build/bazel/product_variables"
67)
68
69var (
70 // These are the list of OSes and architectures with a Bazel config_setting
71 // and constraint value equivalent. These exist in arch.go, but the android
72 // package depends on the bazel package, so a cyclic dependency prevents
73 // using those variables here.
74
75 // A map of architectures to the Bazel label of the constraint_value
76 // for the @platforms//cpu:cpu constraint_setting
77 platformArchMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -040078 archArm: "//build/bazel/platforms/arch:arm",
79 archArm64: "//build/bazel/platforms/arch:arm64",
80 archX86: "//build/bazel/platforms/arch:x86",
81 archX86_64: "//build/bazel/platforms/arch:x86_64",
82 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of as arch select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -040083 }
84
85 // A map of target operating systems to the Bazel label of the
86 // constraint_value for the @platforms//os:os constraint_setting
87 platformOsMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -040088 osAndroid: "//build/bazel/platforms/os:android",
89 osDarwin: "//build/bazel/platforms/os:darwin",
90 osLinux: "//build/bazel/platforms/os:linux",
91 osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
92 osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
93 osWindows: "//build/bazel/platforms/os:windows",
94 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -040095 }
96
97 platformOsArchMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -040098 osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
99 osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
100 osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
101 osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
Dan Willemsen8528f4e2021-10-19 00:22:06 -0700102 osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400103 osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
104 osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
105 osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
Colin Crossa9b2aac2022-06-15 17:25:51 -0700106 osArchLinuxMuslArm: "//build/bazel/platforms/os_arch:linux_musl_arm",
107 osArchLinuxMuslArm64: "//build/bazel/platforms/os_arch:linux_musl_arm64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400108 osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
109 osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
110 osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
111 osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
112 osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
113 osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
114 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -0400115 }
Chris Parsons58852a02021-12-09 18:10:18 -0500116
117 // Map where keys are OsType names, and values are slices containing the archs
118 // that that OS supports.
119 // These definitions copied from arch.go.
120 // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
121 // in a cyclic dependency.
122 osToArchMap = map[string][]string{
123 osAndroid: {archArm, archArm64, archX86, archX86_64},
124 osLinux: {archX86, archX86_64},
125 osLinuxMusl: {archX86, archX86_64},
126 osDarwin: {archArm64, archX86_64},
127 osLinuxBionic: {archArm64, archX86_64},
128 // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
129 osWindows: {archX86, archX86_64},
130 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400131)
132
133// basic configuration types
134type configurationType int
135
136const (
137 noConfig configurationType = iota
138 arch
139 os
140 osArch
141 productVariables
142)
143
Chris Parsons58852a02021-12-09 18:10:18 -0500144func osArchString(os string, arch string) string {
145 return fmt.Sprintf("%s_%s", os, arch)
146}
147
Liz Kammer9abd62d2021-05-21 08:37:59 -0400148func (ct configurationType) String() string {
149 return map[configurationType]string{
150 noConfig: "no_config",
151 arch: "arch",
152 os: "os",
153 osArch: "arch_os",
154 productVariables: "product_variables",
155 }[ct]
156}
157
158func (ct configurationType) validateConfig(config string) {
159 switch ct {
160 case noConfig:
161 if config != "" {
162 panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
163 }
164 case arch:
165 if _, ok := platformArchMap[config]; !ok {
166 panic(fmt.Errorf("Unknown arch: %s", config))
167 }
168 case os:
169 if _, ok := platformOsMap[config]; !ok {
170 panic(fmt.Errorf("Unknown os: %s", config))
171 }
172 case osArch:
173 if _, ok := platformOsArchMap[config]; !ok {
174 panic(fmt.Errorf("Unknown os+arch: %s", config))
175 }
176 case productVariables:
177 // do nothing
178 default:
179 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
180 }
181}
182
183// SelectKey returns the Bazel select key for a given configurationType and config string.
Jingwen Chena47f28d2021-11-02 16:43:57 +0000184func (ca ConfigurationAxis) SelectKey(config string) string {
185 ca.validateConfig(config)
186 switch ca.configurationType {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400187 case noConfig:
188 panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
189 case arch:
190 return platformArchMap[config]
191 case os:
192 return platformOsMap[config]
193 case osArch:
194 return platformOsArchMap[config]
195 case productVariables:
Jingwen Chena47f28d2021-11-02 16:43:57 +0000196 if strings.HasSuffix(config, ConditionsDefaultConfigKey) {
197 // e.g. "acme__feature1__conditions_default" or "android__board__conditions_default"
Liz Kammer9abd62d2021-05-21 08:37:59 -0400198 return ConditionsDefaultSelectKey
199 }
Jingwen Chena47f28d2021-11-02 16:43:57 +0000200 return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
Liz Kammer9abd62d2021-05-21 08:37:59 -0400201 default:
Jingwen Chena47f28d2021-11-02 16:43:57 +0000202 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400203 }
204}
205
206var (
207 // Indicating there is no configuration axis
208 NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
209 // An axis for architecture-specific configurations
210 ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
211 // An axis for os-specific configurations
212 OsConfigurationAxis = ConfigurationAxis{configurationType: os}
213 // An axis for arch+os-specific configurations
214 OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
Liz Kammer9abd62d2021-05-21 08:37:59 -0400215)
216
217// ProductVariableConfigurationAxis returns an axis for the given product variable
218func ProductVariableConfigurationAxis(variable string) ConfigurationAxis {
219 return ConfigurationAxis{
220 configurationType: productVariables,
221 subType: variable,
222 }
223}
224
225// ConfigurationAxis is an independent axis for configuration, there should be no overlap between
226// elements within an axis.
227type ConfigurationAxis struct {
228 configurationType
229 // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
230 // distinguish between them without needing to list all 17 product variables.
231 subType string
232}
233
234func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
235 if ca.configurationType < other.configurationType {
236 return true
237 }
238 return ca.subType < other.subType
239}