123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- // Copyright 2021 Google Inc. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- package bazel
- import (
- "fmt"
- "math"
- "sort"
- "strings"
- )
- const (
- // ArchType names in arch.go
- archArm = "arm"
- archArm64 = "arm64"
- archRiscv64 = "riscv64"
- archX86 = "x86"
- archX86_64 = "x86_64"
- // OsType names in arch.go
- OsAndroid = "android"
- OsDarwin = "darwin"
- OsLinux = "linux_glibc"
- osLinuxMusl = "linux_musl"
- osLinuxBionic = "linux_bionic"
- OsWindows = "windows"
- // Targets in arch.go
- osArchAndroidArm = "android_arm"
- osArchAndroidArm64 = "android_arm64"
- osArchAndroidRiscv64 = "android_riscv64"
- osArchAndroidX86 = "android_x86"
- osArchAndroidX86_64 = "android_x86_64"
- osArchDarwinArm64 = "darwin_arm64"
- osArchDarwinX86_64 = "darwin_x86_64"
- osArchLinuxX86 = "linux_glibc_x86"
- osArchLinuxX86_64 = "linux_glibc_x86_64"
- osArchLinuxMuslArm = "linux_musl_arm"
- osArchLinuxMuslArm64 = "linux_musl_arm64"
- osArchLinuxMuslX86 = "linux_musl_x86"
- osArchLinuxMuslX86_64 = "linux_musl_x86_64"
- osArchLinuxBionicArm64 = "linux_bionic_arm64"
- osArchLinuxBionicX86_64 = "linux_bionic_x86_64"
- osArchWindowsX86 = "windows_x86"
- osArchWindowsX86_64 = "windows_x86_64"
- // This is the string representation of the default condition wherever a
- // configurable attribute is used in a select statement, i.e.
- // //conditions:default for Bazel.
- //
- // This is consistently named "conditions_default" to mirror the Soong
- // config variable default key in an Android.bp file, although there's no
- // integration with Soong config variables (yet).
- ConditionsDefaultConfigKey = "conditions_default"
- ConditionsDefaultSelectKey = "//conditions:default"
- productVariableBazelPackage = "//build/bazel/product_variables"
- AndroidAndInApex = "android-in_apex"
- AndroidPlatform = "system"
- InApex = "in_apex"
- NonApex = "non_apex"
- )
- func PowerSetWithoutEmptySet[T any](items []T) [][]T {
- resultSize := int(math.Pow(2, float64(len(items))))
- powerSet := make([][]T, 0, resultSize-1)
- for i := 1; i < resultSize; i++ {
- combination := make([]T, 0)
- for j := 0; j < len(items); j++ {
- if (i>>j)%2 == 1 {
- combination = append(combination, items[j])
- }
- }
- powerSet = append(powerSet, combination)
- }
- return powerSet
- }
- func createPlatformArchMap() map[string]string {
- // Copy of archFeatures from android/arch_list.go because the bazel
- // package can't access the android package
- archFeatures := map[string][]string{
- "arm": {
- "neon",
- },
- "arm64": {
- "dotprod",
- },
- "riscv64": {},
- "x86": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "avx512",
- "popcnt",
- "movbe",
- },
- "x86_64": {
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "aes_ni",
- "avx",
- "avx2",
- "avx512",
- "popcnt",
- },
- }
- result := make(map[string]string)
- for arch, allFeatures := range archFeatures {
- result[arch] = "//build/bazel/platforms/arch:" + arch
- // Sometimes we want to select on multiple features being active, so
- // add the power set of all possible features to the map. More details
- // in android.ModuleBase.GetArchVariantProperties
- for _, features := range PowerSetWithoutEmptySet(allFeatures) {
- sort.Strings(features)
- archFeaturesName := arch + "-" + strings.Join(features, "-")
- result[archFeaturesName] = "//build/bazel/platforms/arch/variants:" + archFeaturesName
- }
- }
- result[ConditionsDefaultConfigKey] = ConditionsDefaultSelectKey
- return result
- }
- var (
- // These are the list of OSes and architectures with a Bazel config_setting
- // and constraint value equivalent. These exist in arch.go, but the android
- // package depends on the bazel package, so a cyclic dependency prevents
- // using those variables here.
- // A map of architectures to the Bazel label of the constraint_value
- // for the @platforms//cpu:cpu constraint_setting
- platformArchMap = createPlatformArchMap()
- // A map of target operating systems to the Bazel label of the
- // constraint_value for the @platforms//os:os constraint_setting
- platformOsMap = map[string]string{
- OsAndroid: "//build/bazel/platforms/os:android",
- OsDarwin: "//build/bazel/platforms/os:darwin",
- OsLinux: "//build/bazel/platforms/os:linux_glibc",
- osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
- OsWindows: "//build/bazel/platforms/os:windows",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
- }
- platformOsArchMap = map[string]string{
- osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
- osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
- osArchAndroidRiscv64: "//build/bazel/platforms/os_arch:android_riscv64",
- osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
- osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
- osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
- osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
- osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
- osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
- osArchLinuxMuslArm: "//build/bazel/platforms/os_arch:linux_musl_arm",
- osArchLinuxMuslArm64: "//build/bazel/platforms/os_arch:linux_musl_arm64",
- osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
- osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
- osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
- osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
- osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
- osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
- }
- // Map where keys are OsType names, and values are slices containing the archs
- // that that OS supports.
- // These definitions copied from arch.go.
- // TODO(cparsons): Source from arch.go; this task is nontrivial, as it currently results
- // in a cyclic dependency.
- osToArchMap = map[string][]string{
- OsAndroid: {archArm, archArm64, archRiscv64, archX86, archX86_64},
- OsLinux: {archX86, archX86_64},
- osLinuxMusl: {archX86, archX86_64},
- OsDarwin: {archArm64, archX86_64},
- osLinuxBionic: {archArm64, archX86_64},
- // TODO(cparsons): According to arch.go, this should contain archArm, archArm64, as well.
- OsWindows: {archX86, archX86_64},
- }
- osAndInApexMap = map[string]string{
- AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
- AndroidPlatform: "//build/bazel/rules/apex:system",
- OsDarwin: "//build/bazel/platforms/os:darwin",
- OsLinux: "//build/bazel/platforms/os:linux_glibc",
- osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
- OsWindows: "//build/bazel/platforms/os:windows",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
- }
- inApexMap = map[string]string{
- InApex: "//build/bazel/rules/apex:in_apex",
- NonApex: "//build/bazel/rules/apex:non_apex",
- ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
- }
- )
- // basic configuration types
- type configurationType int
- const (
- noConfig configurationType = iota
- arch
- os
- osArch
- productVariables
- osAndInApex
- inApex
- )
- func osArchString(os string, arch string) string {
- return fmt.Sprintf("%s_%s", os, arch)
- }
- func (ct configurationType) String() string {
- return map[configurationType]string{
- noConfig: "no_config",
- arch: "arch",
- os: "os",
- osArch: "arch_os",
- productVariables: "product_variables",
- osAndInApex: "os_in_apex",
- inApex: "in_apex",
- }[ct]
- }
- func (ct configurationType) validateConfig(config string) {
- switch ct {
- case noConfig:
- if config != "" {
- panic(fmt.Errorf("Cannot specify config with %s, but got %s", ct, config))
- }
- case arch:
- if _, ok := platformArchMap[config]; !ok {
- panic(fmt.Errorf("Unknown arch: %s", config))
- }
- case os:
- if _, ok := platformOsMap[config]; !ok {
- panic(fmt.Errorf("Unknown os: %s", config))
- }
- case osArch:
- if _, ok := platformOsArchMap[config]; !ok {
- panic(fmt.Errorf("Unknown os+arch: %s", config))
- }
- case productVariables:
- // do nothing
- case osAndInApex:
- // do nothing
- // this axis can contain additional per-apex keys
- case inApex:
- if _, ok := inApexMap[config]; !ok {
- panic(fmt.Errorf("Unknown in_apex config: %s", config))
- }
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
- }
- }
- // SelectKey returns the Bazel select key for a given configurationType and config string.
- func (ca ConfigurationAxis) SelectKey(config string) string {
- ca.validateConfig(config)
- switch ca.configurationType {
- case noConfig:
- panic(fmt.Errorf("SelectKey is unnecessary for noConfig ConfigurationType "))
- case arch:
- return platformArchMap[config]
- case os:
- return platformOsMap[config]
- case osArch:
- return platformOsArchMap[config]
- case productVariables:
- if config == ConditionsDefaultConfigKey {
- return ConditionsDefaultSelectKey
- }
- return fmt.Sprintf("%s:%s", productVariableBazelPackage, config)
- case osAndInApex:
- if ret, exists := osAndInApexMap[config]; exists {
- return ret
- }
- return config
- case inApex:
- return inApexMap[config]
- default:
- panic(fmt.Errorf("Unrecognized ConfigurationType %d", ca.configurationType))
- }
- }
- var (
- // Indicating there is no configuration axis
- NoConfigAxis = ConfigurationAxis{configurationType: noConfig}
- // An axis for architecture-specific configurations
- ArchConfigurationAxis = ConfigurationAxis{configurationType: arch}
- // An axis for os-specific configurations
- OsConfigurationAxis = ConfigurationAxis{configurationType: os}
- // An axis for arch+os-specific configurations
- OsArchConfigurationAxis = ConfigurationAxis{configurationType: osArch}
- // An axis for os+in_apex-specific configurations
- OsAndInApexAxis = ConfigurationAxis{configurationType: osAndInApex}
- // An axis for in_apex-specific configurations
- InApexAxis = ConfigurationAxis{configurationType: inApex}
- )
- // ProductVariableConfigurationAxis returns an axis for the given product variable
- func ProductVariableConfigurationAxis(archVariant bool, variable string) ConfigurationAxis {
- return ConfigurationAxis{
- configurationType: productVariables,
- subType: variable,
- archVariant: archVariant,
- }
- }
- // ConfigurationAxis is an independent axis for configuration, there should be no overlap between
- // elements within an axis.
- type ConfigurationAxis struct {
- configurationType
- // some configuration types (e.g. productVariables) have multiple independent axes, subType helps
- // distinguish between them without needing to list all 17 product variables.
- subType string
- archVariant bool
- }
- func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
- if ca.configurationType == other.configurationType {
- return ca.subType < other.subType
- }
- return ca.configurationType < other.configurationType
- }
|