blob: df9c9bfbd9dd0ed4715ab10e68dc403e9ddfa394 [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"
32 osFuchsia = "fuchsia"
33 osLinux = "linux_glibc"
34 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"
42 osArchDarwinX86_64 = "darwin_x86_64"
43 osArchFuchsiaArm64 = "fuchsia_arm64"
44 osArchFuchsiaX86_64 = "fuchsia_x86_64"
45 osArchLinuxX86 = "linux_glibc_x86"
46 osArchLinuxX86_64 = "linux_glibc_x86_64"
47 osArchLinuxBionicArm64 = "linux_bionic_arm64"
48 osArchLinuxBionicX86_64 = "linux_bionic_x86_64"
49 osArchWindowsX86 = "windows_x86"
50 osArchWindowsX86_64 = "windows_x86_64"
51
52 // This is the string representation of the default condition wherever a
53 // configurable attribute is used in a select statement, i.e.
54 // //conditions:default for Bazel.
55 //
56 // This is consistently named "conditions_default" to mirror the Soong
57 // config variable default key in an Android.bp file, although there's no
58 // integration with Soong config variables (yet).
59 ConditionsDefault = "conditions_default"
60
61 ConditionsDefaultSelectKey = "//conditions:default"
62
63 productVariableBazelPackage = "//build/bazel/product_variables"
64)
65
66var (
67 // These are the list of OSes and architectures with a Bazel config_setting
68 // and constraint value equivalent. These exist in arch.go, but the android
69 // package depends on the bazel package, so a cyclic dependency prevents
70 // using those variables here.
71
72 // A map of architectures to the Bazel label of the constraint_value
73 // for the @platforms//cpu:cpu constraint_setting
74 platformArchMap = map[string]string{
75 archArm: "//build/bazel/platforms/arch:arm",
76 archArm64: "//build/bazel/platforms/arch:arm64",
77 archX86: "//build/bazel/platforms/arch:x86",
78 archX86_64: "//build/bazel/platforms/arch:x86_64",
79 ConditionsDefault: ConditionsDefaultSelectKey, // The default condition of as arch select map.
80 }
81
82 // A map of target operating systems to the Bazel label of the
83 // constraint_value for the @platforms//os:os constraint_setting
84 platformOsMap = map[string]string{
85 osAndroid: "//build/bazel/platforms/os:android",
86 osDarwin: "//build/bazel/platforms/os:darwin",
87 osFuchsia: "//build/bazel/platforms/os:fuchsia",
88 osLinux: "//build/bazel/platforms/os:linux",
89 osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
90 osWindows: "//build/bazel/platforms/os:windows",
91 ConditionsDefault: ConditionsDefaultSelectKey, // The default condition of an os select map.
92 }
93
94 platformOsArchMap = map[string]string{
95 osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
96 osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
97 osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
98 osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
99 osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
100 osArchFuchsiaArm64: "//build/bazel/platforms/os_arch:fuchsia_arm64",
101 osArchFuchsiaX86_64: "//build/bazel/platforms/os_arch:fuchsia_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 osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
105 osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
106 osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
107 osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
108 ConditionsDefault: ConditionsDefaultSelectKey, // The default condition of an os select map.
109 }
110)
111
112// basic configuration types
113type configurationType int
114
115const (
116 noConfig configurationType = iota
117 arch
118 os
119 osArch
120 productVariables
121)
122
123func (ct configurationType) String() string {
124 return map[configurationType]string{
125 noConfig: "no_config",
126 arch: "arch",
127 os: "os",
128 osArch: "arch_os",
129 productVariables: "product_variables",
130 }[ct]
131}
132
133func (ct configurationType) validateConfig(config string) {
134 switch ct {
135 case noConfig:
136 if config != "" {
137 panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
138 }
139 case arch:
140 if _, ok := platformArchMap[config]; !ok {
141 panic(fmt.Errorf("Unknown arch: %s", config))
142 }
143 case os:
144 if _, ok := platformOsMap[config]; !ok {
145 panic(fmt.Errorf("Unknown os: %s", config))
146 }
147 case osArch:
148 if _, ok := platformOsArchMap[config]; !ok {
149 panic(fmt.Errorf("Unknown os+arch: %s", config))
150 }
151 case productVariables:
152 // do nothing
153 default:
154 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
155 }
156}
157
158// SelectKey returns the Bazel select key for a given configurationType and config string.
159func (ct configurationType) SelectKey(config string) string {
160 ct.validateConfig(config)
161 switch ct {
162 case noConfig:
163 panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
164 case arch:
165 return platformArchMap[config]
166 case os:
167 return platformOsMap[config]
168 case osArch:
169 return platformOsArchMap[config]
170 case productVariables:
171 if config == ConditionsDefault {
172 return ConditionsDefaultSelectKey
173 }
174 return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(config))
175 default:
176 panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
177 }
178}
179
180var (
181 // Indicating there is no configuration axis
182 NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
183 // An axis for architecture-specific configurations
184 ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
185 // An axis for os-specific configurations
186 OsConfigurationAxis = ConfigurationAxis{configurationType: os}
187 // An axis for arch+os-specific configurations
188 OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
189)
190
191// ProductVariableConfigurationAxis returns an axis for the given product variable
192func ProductVariableConfigurationAxis(variable string) ConfigurationAxis {
193 return ConfigurationAxis{
194 configurationType: productVariables,
195 subType: variable,
196 }
197}
198
199// ConfigurationAxis is an independent axis for configuration, there should be no overlap between
200// elements within an axis.
201type ConfigurationAxis struct {
202 configurationType
203 // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
204 // distinguish between them without needing to list all 17 product variables.
205 subType string
206}
207
208func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
209 if ca.configurationType < other.configurationType {
210 return true
211 }
212 return ca.subType < other.subType
213}