blob: 7355ac7d39d6202791c53091ca3d45622d219708 [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 Cross528d67e2021-07-23 22:23:07 +000046 osArchLinuxMuslX86 = "linux_musl_x86"
47 osArchLinuxMuslX86_64 = "linux_musl_x86_64"
Liz Kammer9abd62d2021-05-21 08:37:59 -040048 osArchLinuxBionicArm64 = "linux_bionic_arm64"
49 osArchLinuxBionicX86_64 = "linux_bionic_x86_64"
50 osArchWindowsX86 = "windows_x86"
51 osArchWindowsX86_64 = "windows_x86_64"
52
53 // This is the string representation of the default condition wherever a
54 // configurable attribute is used in a select statement, i.e.
55 // //conditions:default for Bazel.
56 //
57 // This is consistently named "conditions_default" to mirror the Soong
58 // config variable default key in an Android.bp file, although there's no
59 // integration with Soong config variables (yet).
Chris Parsons51f8c392021-08-03 21:01:05 -040060 ConditionsDefaultConfigKey = "conditions_default"
Liz Kammer9abd62d2021-05-21 08:37:59 -040061
62 ConditionsDefaultSelectKey = "//conditions:default"
63
64 productVariableBazelPackage = "//build/bazel/product_variables"
65)
66
67var (
68 // These are the list of OSes and architectures with a Bazel config_setting
69 // and constraint value equivalent. These exist in arch.go, but the android
70 // package depends on the bazel package, so a cyclic dependency prevents
71 // using those variables here.
72
73 // A map of architectures to the Bazel label of the constraint_value
74 // for the @platforms//cpu:cpu constraint_setting
75 platformArchMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -040076 archArm: "//build/bazel/platforms/arch:arm",
77 archArm64: "//build/bazel/platforms/arch:arm64",
78 archX86: "//build/bazel/platforms/arch:x86",
79 archX86_64: "//build/bazel/platforms/arch:x86_64",
80 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of as arch select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -040081 }
82
83 // A map of target operating systems to the Bazel label of the
84 // constraint_value for the @platforms//os:os constraint_setting
85 platformOsMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -040086 osAndroid: "//build/bazel/platforms/os:android",
87 osDarwin: "//build/bazel/platforms/os:darwin",
88 osLinux: "//build/bazel/platforms/os:linux",
89 osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
90 osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
91 osWindows: "//build/bazel/platforms/os:windows",
92 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -040093 }
94
95 platformOsArchMap = map[string]string{
Chris Parsons51f8c392021-08-03 21:01:05 -040096 osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
97 osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
98 osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
99 osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
Dan Willemsen8528f4e2021-10-19 00:22:06 -0700100 osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
Chris Parsons51f8c392021-08-03 21:01:05 -0400101 osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
102 osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
103 osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
104 osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
105 osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
106 osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
107 osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
108 osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
109 osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
110 ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
Liz Kammer9abd62d2021-05-21 08:37:59 -0400111 }
Chris Parsons58852a02021-12-09 18:10:18 -0500112
113 // Map where keys are OsType names, and values are slices containing the archs
114 // that that OS supports.
115 // These definitions copied from arch.go.
116 // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
117 // in a cyclic dependency.
118 osToArchMap = map[string][]string{
119 osAndroid: {archArm, archArm64, archX86, archX86_64},
120 osLinux: {archX86, archX86_64},
121 osLinuxMusl: {archX86, archX86_64},
122 osDarwin: {archArm64, archX86_64},
123 osLinuxBionic: {archArm64, archX86_64},
124 // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
125 osWindows: {archX86, archX86_64},
126 }
Liz Kammer9abd62d2021-05-21 08:37:59 -0400127)
128
129// basic configuration types
130type configurationType int
131
132const (
133 noConfig configurationType = iota
134 arch
135 os
136 osArch
137 productVariables
138)
139
Chris Parsons58852a02021-12-09 18:10:18 -0500140func osArchString(os string, arch string) string {
141 return fmt.Sprintf("%s_%s", os, arch)
142}
143
Liz Kammer9abd62d2021-05-21 08:37:59 -0400144func (ct configurationType) String() string {
145 return map[configurationType]string{
146 noConfig: "no_config",
147 arch: "arch",
148 os: "os",
149 osArch: "arch_os",
150 productVariables: "product_variables",
151 }[ct]
152}
153
154func (ct configurationType) validateConfig(config string) {
155 switch ct {
156 case noConfig:
157 if config != "" {
158 panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
159 }
160 case arch:
161 if _, ok := platformArchMap[config]; !ok {
162 panic(fmt.Errorf("Unknown arch: %s", config))
163 }
164 case os:
165 if _, ok := platformOsMap[config]; !ok {
166 panic(fmt.Errorf("Unknown os: %s", config))
167 }
168 case osArch:
169 if _, ok := platformOsArchMap[config]; !ok {
170 panic(fmt.Errorf("Unknown os+arch: %s", config))
171 }
172 case productVariables:
173 // do nothing
174 default:
175 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
176 }
177}
178
179// SelectKey returns the Bazel select key for a given configurationType and config string.
Jingwen Chena47f28d2021-11-02 16:43:57 +0000180func (ca ConfigurationAxis) SelectKey(config string) string {
181 ca.validateConfig(config)
182 switch ca.configurationType {
Liz Kammer9abd62d2021-05-21 08:37:59 -0400183 case noConfig:
184 panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
185 case arch:
186 return platformArchMap[config]
187 case os:
188 return platformOsMap[config]
189 case osArch:
190 return platformOsArchMap[config]
191 case productVariables:
Jingwen Chena47f28d2021-11-02 16:43:57 +0000192 if strings.HasSuffix(config, ConditionsDefaultConfigKey) {
193 // e.g. "acme__feature1__conditions_default" or "android__board__conditions_default"
Liz Kammer9abd62d2021-05-21 08:37:59 -0400194 return ConditionsDefaultSelectKey
195 }
Jingwen Chena47f28d2021-11-02 16:43:57 +0000196 return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
Liz Kammer9abd62d2021-05-21 08:37:59 -0400197 default:
Jingwen Chena47f28d2021-11-02 16:43:57 +0000198 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
Liz Kammer9abd62d2021-05-21 08:37:59 -0400199 }
200}
201
202var (
203 // Indicating there is no configuration axis
204 NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
205 // An axis for architecture-specific configurations
206 ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
207 // An axis for os-specific configurations
208 OsConfigurationAxis = ConfigurationAxis{configurationType: os}
209 // An axis for arch+os-specific configurations
210 OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
Liz Kammer9abd62d2021-05-21 08:37:59 -0400211)
212
213// ProductVariableConfigurationAxis returns an axis for the given product variable
214func ProductVariableConfigurationAxis(variable string) ConfigurationAxis {
215 return ConfigurationAxis{
216 configurationType: productVariables,
217 subType: variable,
218 }
219}
220
221// ConfigurationAxis is an independent axis for configuration, there should be no overlap between
222// elements within an axis.
223type ConfigurationAxis struct {
224 configurationType
225 // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
226 // distinguish between them without needing to list all 17 product variables.
227 subType string
228}
229
230func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
231 if ca.configurationType < other.configurationType {
232 return true
233 }
234 return ca.subType < other.subType
235}