Loading android/arch.go +87 −0 Original line number Diff line number Diff line Loading @@ -1709,3 +1709,90 @@ func (m *ModuleBase) GetArchProperties(dst interface{}) map[ArchType]interface{} } return archToProp } // GetTargetProperties returns a map of OS target (e.g. android, windows) to the // values of the properties of the 'dst' struct that are specific to that OS // target. // // For example, passing a struct { Foo bool, Bar string } will return an // interface{} that can be type asserted back into the same struct, containing // the os-specific property value specified by the module if defined. // // While this looks similar to GetArchProperties, the internal representation of // the properties have a slightly different layout to warrant a standalone // lookup function. func (m *ModuleBase) GetTargetProperties(dst interface{}) map[OsType]interface{} { // Return value of the arch types to the prop values for that arch. osToProp := map[OsType]interface{}{} // Nothing to do for non-OS/arch-specific modules. if !m.ArchSpecific() { return osToProp } // archProperties has the type of [][]interface{}. Looks complicated, so // let's explain this step by step. // // Loop over the outer index, which determines the property struct that // contains a matching set of properties in dst that we're interested in. // For example, BaseCompilerProperties or BaseLinkerProperties. for i := range m.archProperties { if m.archProperties[i] == nil { continue } // Iterate over the supported OS types for _, os := range OsTypeList { // e.g android, linux_bionic field := os.Field // If it's not nil, loop over the inner index, which determines the arch variant // of the prop type. In an Android.bp file, this is like looping over: // // target: { android: { key: value, ... }, linux_bionic: { key: value, ... } } for _, archProperties := range m.archProperties[i] { archPropValues := reflect.ValueOf(archProperties).Elem() // This is the archPropRoot struct. Traverse into the Targetnested struct. src := archPropValues.FieldByName("Target").Elem() // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { continue } src = src.Elem() } // Find the requested field (e.g. android, linux_bionic) in the src struct. src = src.FieldByName(field) // Validation steps. We want valid non-nil pointers to structs. if !src.IsValid() || src.IsNil() { continue } if src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct { continue } // Clone the destination prop, since we want a unique prop struct per arch. dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface() // Copy the located property struct into the cloned destination property struct. err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace) if err != nil { // This is fine, it just means the src struct doesn't match. continue } // Found the prop for the os, you have. osToProp[os] = dstClone // Go to the next prop. break } } } return osToProp } android/bazel.go +10 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,11 @@ type Bp2BuildConfig map[string]BazelConversionConfigEntry type BazelConversionConfigEntry int const ( // A sentinel value to be used as a key in Bp2BuildConfig for modules with // no package path. This is also the module dir for top level Android.bp // modules. BP2BUILD_TOPLEVEL = "." // iota + 1 ensures that the int value is not 0 when used in the Bp2buildAllowlist map, // which can also mean that the key doesn't exist in a lookup. Loading Loading @@ -224,10 +229,15 @@ func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bo func bp2buildDefaultTrueRecursively(packagePath string, config Bp2BuildConfig) bool { ret := false // Return exact matches in the config. if config[packagePath] == Bp2BuildDefaultTrueRecursively { return true } if config[packagePath] == Bp2BuildDefaultFalse { return false } // If not, check for the config recursively. packagePrefix := "" // e.g. for x/y/z, iterate over x, x/y, then x/y/z, taking the final value from the allowlist. for _, part := range strings.Split(packagePath, "/") { Loading android/bazel_handler.go +18 −8 Original line number Diff line number Diff line Loading @@ -270,13 +270,23 @@ func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command st cmdFlags = append(cmdFlags, labels...) cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir()) cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(context, runName)) // Set default platforms to canonicalized values for mixed builds requests. If these are set // in the bazelrc, they will have values that are non-canonicalized, and thus be invalid. // The actual platform values here may be overridden by configuration transitions from the buildroot. // Set default platforms to canonicalized values for mixed builds requests. // If these are set in the bazelrc, they will have values that are // non-canonicalized to @sourceroot labels, and thus be invalid when // referenced from the buildroot. // // The actual platform values here may be overridden by configuration // transitions from the buildroot. cmdFlags = append(cmdFlags, fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:generic_x86_64"))) fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:android_x86_64"))) cmdFlags = append(cmdFlags, fmt.Sprintf("--extra_toolchains=%s", canonicalizeLabel("//prebuilts/clang/host/linux-x86:all"))) // This should be parameterized on the host OS, but let's restrict to linux // to keep things simple for now. cmdFlags = append(cmdFlags, fmt.Sprintf("--host_platform=%s", canonicalizeLabel("//build/bazel/platforms:linux_x86_64"))) // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network. cmdFlags = append(cmdFlags, "--experimental_repository_disable_download") cmdFlags = append(cmdFlags, extraFlags...) Loading Loading @@ -328,7 +338,7 @@ func (context *bazelContext) mainBzlFileContents() []byte { def _config_node_transition_impl(settings, attr): return { "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_%s" % attr.arch, "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:android_%s" % attr.arch, } _config_node_transition = transition( Loading Loading @@ -504,10 +514,10 @@ def get_arch(target): platform_name = build_options(target)["//command_line_option:platforms"][0].name if platform_name == "host": return "HOST" elif not platform_name.startswith("generic_"): fail("expected platform name of the form 'generic_<arch>', but was " + str(platforms)) elif not platform_name.startswith("android_"): fail("expected platform name of the form 'android_<arch>', but was " + str(platforms)) return "UNKNOWN" return platform_name[len("generic_"):] return platform_name[len("android_"):] def format(target): id_string = str(target.label) + "|" + get_arch(target) Loading bazel/properties.go +126 −50 Original line number Diff line number Diff line Loading @@ -80,10 +80,19 @@ func UniqueBazelLabelList(originalLabelList LabelList) LabelList { } const ( ARCH_X86 = "x86" ARCH_X86_64 = "x86_64" // ArchType names in arch.go ARCH_ARM = "arm" ARCH_ARM64 = "arm64" ARCH_X86 = "x86" ARCH_X86_64 = "x86_64" // OsType names in arch.go OS_ANDROID = "android" OS_DARWIN = "darwin" OS_FUCHSIA = "fuchsia" OS_LINUX = "linux_glibc" OS_LINUX_BIONIC = "linux_bionic" OS_WINDOWS = "windows" ) var ( Loading @@ -92,6 +101,36 @@ var ( // android package depends on the bazel package, so a cyclic dependency // prevents using that here. selectableArchs = []string{ARCH_X86, ARCH_X86_64, ARCH_ARM, ARCH_ARM64} // Likewise, this is the list of target operating systems. selectableTargetOs = []string{ OS_ANDROID, OS_DARWIN, OS_FUCHSIA, OS_LINUX, OS_LINUX_BIONIC, OS_WINDOWS, } // A map of architectures to the Bazel label of the constraint_value // for the @platforms//cpu:cpu constraint_setting PlatformArchMap = map[string]string{ ARCH_ARM: "//build/bazel/platforms/arch:arm", ARCH_ARM64: "//build/bazel/platforms/arch:arm64", ARCH_X86: "//build/bazel/platforms/arch:x86", ARCH_X86_64: "//build/bazel/platforms/arch:x86_64", } // 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{ OS_ANDROID: "//build/bazel/platforms/os:android", OS_DARWIN: "//build/bazel/platforms/os:darwin", OS_FUCHSIA: "//build/bazel/platforms/os:fuchsia", OS_LINUX: "//build/bazel/platforms/os:linux", OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic", OS_WINDOWS: "//build/bazel/platforms/os:windows", } ) // Arch-specific label_list typed Bazel attribute values. This should correspond Loading @@ -101,8 +140,16 @@ type labelListArchValues struct { X86_64 LabelList Arm LabelList Arm64 LabelList // TODO(b/181299724): this is currently missing the "common" arch, which // doesn't have an equivalent platform() definition yet. Common LabelList } type labelListOsValues struct { Android LabelList Darwin LabelList Fuchsia LabelList Linux LabelList LinuxBionic LabelList Windows LabelList } // LabelListAttribute is used to represent a list of Bazel labels as an Loading @@ -115,6 +162,11 @@ type LabelListAttribute struct { // are generated in a select statement and appended to the non-arch specific // label list Value. ArchValues labelListArchValues // The os-specific attribute label list values. Optional. If used, these // are generated in a select statement and appended to the non-os specific // label list Value. OsValues labelListOsValues } // MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value. Loading @@ -124,45 +176,75 @@ func MakeLabelListAttribute(value LabelList) LabelListAttribute { // HasArchSpecificValues returns true if the attribute contains // architecture-specific label_list values. func (attrs *LabelListAttribute) HasArchSpecificValues() bool { func (attrs *LabelListAttribute) HasConfigurableValues() bool { for _, arch := range selectableArchs { if len(attrs.GetValueForArch(arch).Includes) > 0 || len(attrs.GetValueForArch(arch).Excludes) > 0 { if len(attrs.GetValueForArch(arch).Includes) > 0 { return true } } for _, os := range selectableTargetOs { if len(attrs.GetValueForOS(os).Includes) > 0 { return true } } return false } func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList { return map[string]*LabelList{ ARCH_X86: &attrs.ArchValues.X86, ARCH_X86_64: &attrs.ArchValues.X86_64, ARCH_ARM: &attrs.ArchValues.Arm, ARCH_ARM64: &attrs.ArchValues.Arm64, } } // GetValueForArch returns the label_list attribute value for an architecture. func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList { switch arch { case ARCH_X86: return attrs.ArchValues.X86 case ARCH_X86_64: return attrs.ArchValues.X86_64 case ARCH_ARM: return attrs.ArchValues.Arm case ARCH_ARM64: return attrs.ArchValues.Arm64 default: var v *LabelList if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } return *v } // SetValueForArch sets the label_list attribute value for an architecture. func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) { switch arch { case "x86": attrs.ArchValues.X86 = value case "x86_64": attrs.ArchValues.X86_64 = value case "arm": attrs.ArchValues.Arm = value case "arm64": attrs.ArchValues.Arm64 = value default: var v *LabelList if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } *v = value } func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList { return map[string]*LabelList{ OS_ANDROID: &attrs.OsValues.Android, OS_DARWIN: &attrs.OsValues.Darwin, OS_FUCHSIA: &attrs.OsValues.Fuchsia, OS_LINUX: &attrs.OsValues.Linux, OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic, OS_WINDOWS: &attrs.OsValues.Windows, } } // GetValueForOS returns the label_list attribute value for an OS target. func (attrs *LabelListAttribute) GetValueForOS(os string) LabelList { var v *LabelList if v = attrs.osValuePtrs()[os]; v == nil { panic(fmt.Errorf("Unknown os: %s", os)) } return *v } // SetValueForArch sets the label_list attribute value for an OS target. func (attrs *LabelListAttribute) SetValueForOS(os string, value LabelList) { var v *LabelList if v = attrs.osValuePtrs()[os]; v == nil { panic(fmt.Errorf("Unknown os: %s", os)) } *v = value } // StringListAttribute corresponds to the string_list Bazel attribute type with Loading @@ -182,13 +264,12 @@ type stringListArchValues struct { X86_64 []string Arm []string Arm64 []string // TODO(b/181299724): this is currently missing the "common" arch, which // doesn't have an equivalent platform() definition yet. Common []string } // HasArchSpecificValues returns true if the attribute contains // HasConfigurableValues returns true if the attribute contains // architecture-specific string_list values. func (attrs *StringListAttribute) HasArchSpecificValues() bool { func (attrs *StringListAttribute) HasConfigurableValues() bool { for _, arch := range selectableArchs { if len(attrs.GetValueForArch(arch)) > 0 { return true Loading @@ -197,36 +278,31 @@ func (attrs *StringListAttribute) HasArchSpecificValues() bool { return false } func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string { return map[string]*[]string{ ARCH_X86: &attrs.ArchValues.X86, ARCH_X86_64: &attrs.ArchValues.X86_64, ARCH_ARM: &attrs.ArchValues.Arm, ARCH_ARM64: &attrs.ArchValues.Arm64, } } // GetValueForArch returns the string_list attribute value for an architecture. func (attrs *StringListAttribute) GetValueForArch(arch string) []string { switch arch { case ARCH_X86: return attrs.ArchValues.X86 case ARCH_X86_64: return attrs.ArchValues.X86_64 case ARCH_ARM: return attrs.ArchValues.Arm case ARCH_ARM64: return attrs.ArchValues.Arm64 default: var v *[]string if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } return *v } // SetValueForArch sets the string_list attribute value for an architecture. func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) { switch arch { case ARCH_X86: attrs.ArchValues.X86 = value case ARCH_X86_64: attrs.ArchValues.X86_64 = value case ARCH_ARM: attrs.ArchValues.Arm = value case ARCH_ARM64: attrs.ArchValues.Arm64 = value default: var v *[]string if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } *v = value } // TryVariableSubstitution, replace string substitution formatting within each string in slice with Loading bp2build/build_conversion.go +2 −54 Original line number Diff line number Diff line Loading @@ -416,63 +416,11 @@ func prettyPrint(propertyValue reflect.Value, indent int) (string, error) { // Special cases where the bp2build sends additional information to the codegenerator // by wrapping the attributes in a custom struct type. if labels, ok := propertyValue.Interface().(bazel.LabelListAttribute); ok { // TODO(b/165114590): convert glob syntax ret, err := prettyPrint(reflect.ValueOf(labels.Value.Includes), indent) if err != nil { return ret, err } if !labels.HasArchSpecificValues() { // Select statement not needed. return ret, nil } ret += " + " + "select({\n" for _, arch := range android.ArchTypeList() { value := labels.GetValueForArch(arch.Name) if len(value.Includes) > 0 { ret += makeIndent(indent + 1) list, _ := prettyPrint(reflect.ValueOf(value.Includes), indent+1) ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list) } } ret += makeIndent(indent + 1) ret += fmt.Sprintf("\"%s\": [],\n", "//conditions:default") ret += makeIndent(indent) ret += "})" return ret, err return prettyPrintLabelListAttribute(labels, indent) } else if label, ok := propertyValue.Interface().(bazel.Label); ok { return fmt.Sprintf("%q", label.Label), nil } else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok { // A Bazel string_list attribute that may contain a select statement. ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent) if err != nil { return ret, err } if !stringList.HasArchSpecificValues() { // Select statement not needed. return ret, nil } ret += " + " + "select({\n" for _, arch := range android.ArchTypeList() { value := stringList.GetValueForArch(arch.Name) if len(value) > 0 { ret += makeIndent(indent + 1) list, _ := prettyPrint(reflect.ValueOf(value), indent+1) ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list) } } ret += makeIndent(indent + 1) ret += fmt.Sprintf("\"%s\": [],\n", "//conditions:default") ret += makeIndent(indent) ret += "})" return ret, err return prettyPrintStringListAttribute(stringList, indent) } ret = "{\n" Loading Loading
android/arch.go +87 −0 Original line number Diff line number Diff line Loading @@ -1709,3 +1709,90 @@ func (m *ModuleBase) GetArchProperties(dst interface{}) map[ArchType]interface{} } return archToProp } // GetTargetProperties returns a map of OS target (e.g. android, windows) to the // values of the properties of the 'dst' struct that are specific to that OS // target. // // For example, passing a struct { Foo bool, Bar string } will return an // interface{} that can be type asserted back into the same struct, containing // the os-specific property value specified by the module if defined. // // While this looks similar to GetArchProperties, the internal representation of // the properties have a slightly different layout to warrant a standalone // lookup function. func (m *ModuleBase) GetTargetProperties(dst interface{}) map[OsType]interface{} { // Return value of the arch types to the prop values for that arch. osToProp := map[OsType]interface{}{} // Nothing to do for non-OS/arch-specific modules. if !m.ArchSpecific() { return osToProp } // archProperties has the type of [][]interface{}. Looks complicated, so // let's explain this step by step. // // Loop over the outer index, which determines the property struct that // contains a matching set of properties in dst that we're interested in. // For example, BaseCompilerProperties or BaseLinkerProperties. for i := range m.archProperties { if m.archProperties[i] == nil { continue } // Iterate over the supported OS types for _, os := range OsTypeList { // e.g android, linux_bionic field := os.Field // If it's not nil, loop over the inner index, which determines the arch variant // of the prop type. In an Android.bp file, this is like looping over: // // target: { android: { key: value, ... }, linux_bionic: { key: value, ... } } for _, archProperties := range m.archProperties[i] { archPropValues := reflect.ValueOf(archProperties).Elem() // This is the archPropRoot struct. Traverse into the Targetnested struct. src := archPropValues.FieldByName("Target").Elem() // Step into non-nil pointers to structs in the src value. if src.Kind() == reflect.Ptr { if src.IsNil() { continue } src = src.Elem() } // Find the requested field (e.g. android, linux_bionic) in the src struct. src = src.FieldByName(field) // Validation steps. We want valid non-nil pointers to structs. if !src.IsValid() || src.IsNil() { continue } if src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct { continue } // Clone the destination prop, since we want a unique prop struct per arch. dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface() // Copy the located property struct into the cloned destination property struct. err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace) if err != nil { // This is fine, it just means the src struct doesn't match. continue } // Found the prop for the os, you have. osToProp[os] = dstClone // Go to the next prop. break } } } return osToProp }
android/bazel.go +10 −0 Original line number Diff line number Diff line Loading @@ -108,6 +108,11 @@ type Bp2BuildConfig map[string]BazelConversionConfigEntry type BazelConversionConfigEntry int const ( // A sentinel value to be used as a key in Bp2BuildConfig for modules with // no package path. This is also the module dir for top level Android.bp // modules. BP2BUILD_TOPLEVEL = "." // iota + 1 ensures that the int value is not 0 when used in the Bp2buildAllowlist map, // which can also mean that the key doesn't exist in a lookup. Loading Loading @@ -224,10 +229,15 @@ func (b *BazelModuleBase) ConvertWithBp2build(ctx BazelConversionPathContext) bo func bp2buildDefaultTrueRecursively(packagePath string, config Bp2BuildConfig) bool { ret := false // Return exact matches in the config. if config[packagePath] == Bp2BuildDefaultTrueRecursively { return true } if config[packagePath] == Bp2BuildDefaultFalse { return false } // If not, check for the config recursively. packagePrefix := "" // e.g. for x/y/z, iterate over x, x/y, then x/y/z, taking the final value from the allowlist. for _, part := range strings.Split(packagePath, "/") { Loading
android/bazel_handler.go +18 −8 Original line number Diff line number Diff line Loading @@ -270,13 +270,23 @@ func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command st cmdFlags = append(cmdFlags, labels...) cmdFlags = append(cmdFlags, "--package_path=%workspace%/"+context.intermediatesDir()) cmdFlags = append(cmdFlags, "--profile="+shared.BazelMetricsFilename(context, runName)) // Set default platforms to canonicalized values for mixed builds requests. If these are set // in the bazelrc, they will have values that are non-canonicalized, and thus be invalid. // The actual platform values here may be overridden by configuration transitions from the buildroot. // Set default platforms to canonicalized values for mixed builds requests. // If these are set in the bazelrc, they will have values that are // non-canonicalized to @sourceroot labels, and thus be invalid when // referenced from the buildroot. // // The actual platform values here may be overridden by configuration // transitions from the buildroot. cmdFlags = append(cmdFlags, fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:generic_x86_64"))) fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:android_x86_64"))) cmdFlags = append(cmdFlags, fmt.Sprintf("--extra_toolchains=%s", canonicalizeLabel("//prebuilts/clang/host/linux-x86:all"))) // This should be parameterized on the host OS, but let's restrict to linux // to keep things simple for now. cmdFlags = append(cmdFlags, fmt.Sprintf("--host_platform=%s", canonicalizeLabel("//build/bazel/platforms:linux_x86_64"))) // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network. cmdFlags = append(cmdFlags, "--experimental_repository_disable_download") cmdFlags = append(cmdFlags, extraFlags...) Loading Loading @@ -328,7 +338,7 @@ func (context *bazelContext) mainBzlFileContents() []byte { def _config_node_transition_impl(settings, attr): return { "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_%s" % attr.arch, "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:android_%s" % attr.arch, } _config_node_transition = transition( Loading Loading @@ -504,10 +514,10 @@ def get_arch(target): platform_name = build_options(target)["//command_line_option:platforms"][0].name if platform_name == "host": return "HOST" elif not platform_name.startswith("generic_"): fail("expected platform name of the form 'generic_<arch>', but was " + str(platforms)) elif not platform_name.startswith("android_"): fail("expected platform name of the form 'android_<arch>', but was " + str(platforms)) return "UNKNOWN" return platform_name[len("generic_"):] return platform_name[len("android_"):] def format(target): id_string = str(target.label) + "|" + get_arch(target) Loading
bazel/properties.go +126 −50 Original line number Diff line number Diff line Loading @@ -80,10 +80,19 @@ func UniqueBazelLabelList(originalLabelList LabelList) LabelList { } const ( ARCH_X86 = "x86" ARCH_X86_64 = "x86_64" // ArchType names in arch.go ARCH_ARM = "arm" ARCH_ARM64 = "arm64" ARCH_X86 = "x86" ARCH_X86_64 = "x86_64" // OsType names in arch.go OS_ANDROID = "android" OS_DARWIN = "darwin" OS_FUCHSIA = "fuchsia" OS_LINUX = "linux_glibc" OS_LINUX_BIONIC = "linux_bionic" OS_WINDOWS = "windows" ) var ( Loading @@ -92,6 +101,36 @@ var ( // android package depends on the bazel package, so a cyclic dependency // prevents using that here. selectableArchs = []string{ARCH_X86, ARCH_X86_64, ARCH_ARM, ARCH_ARM64} // Likewise, this is the list of target operating systems. selectableTargetOs = []string{ OS_ANDROID, OS_DARWIN, OS_FUCHSIA, OS_LINUX, OS_LINUX_BIONIC, OS_WINDOWS, } // A map of architectures to the Bazel label of the constraint_value // for the @platforms//cpu:cpu constraint_setting PlatformArchMap = map[string]string{ ARCH_ARM: "//build/bazel/platforms/arch:arm", ARCH_ARM64: "//build/bazel/platforms/arch:arm64", ARCH_X86: "//build/bazel/platforms/arch:x86", ARCH_X86_64: "//build/bazel/platforms/arch:x86_64", } // 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{ OS_ANDROID: "//build/bazel/platforms/os:android", OS_DARWIN: "//build/bazel/platforms/os:darwin", OS_FUCHSIA: "//build/bazel/platforms/os:fuchsia", OS_LINUX: "//build/bazel/platforms/os:linux", OS_LINUX_BIONIC: "//build/bazel/platforms/os:linux_bionic", OS_WINDOWS: "//build/bazel/platforms/os:windows", } ) // Arch-specific label_list typed Bazel attribute values. This should correspond Loading @@ -101,8 +140,16 @@ type labelListArchValues struct { X86_64 LabelList Arm LabelList Arm64 LabelList // TODO(b/181299724): this is currently missing the "common" arch, which // doesn't have an equivalent platform() definition yet. Common LabelList } type labelListOsValues struct { Android LabelList Darwin LabelList Fuchsia LabelList Linux LabelList LinuxBionic LabelList Windows LabelList } // LabelListAttribute is used to represent a list of Bazel labels as an Loading @@ -115,6 +162,11 @@ type LabelListAttribute struct { // are generated in a select statement and appended to the non-arch specific // label list Value. ArchValues labelListArchValues // The os-specific attribute label list values. Optional. If used, these // are generated in a select statement and appended to the non-os specific // label list Value. OsValues labelListOsValues } // MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value. Loading @@ -124,45 +176,75 @@ func MakeLabelListAttribute(value LabelList) LabelListAttribute { // HasArchSpecificValues returns true if the attribute contains // architecture-specific label_list values. func (attrs *LabelListAttribute) HasArchSpecificValues() bool { func (attrs *LabelListAttribute) HasConfigurableValues() bool { for _, arch := range selectableArchs { if len(attrs.GetValueForArch(arch).Includes) > 0 || len(attrs.GetValueForArch(arch).Excludes) > 0 { if len(attrs.GetValueForArch(arch).Includes) > 0 { return true } } for _, os := range selectableTargetOs { if len(attrs.GetValueForOS(os).Includes) > 0 { return true } } return false } func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList { return map[string]*LabelList{ ARCH_X86: &attrs.ArchValues.X86, ARCH_X86_64: &attrs.ArchValues.X86_64, ARCH_ARM: &attrs.ArchValues.Arm, ARCH_ARM64: &attrs.ArchValues.Arm64, } } // GetValueForArch returns the label_list attribute value for an architecture. func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList { switch arch { case ARCH_X86: return attrs.ArchValues.X86 case ARCH_X86_64: return attrs.ArchValues.X86_64 case ARCH_ARM: return attrs.ArchValues.Arm case ARCH_ARM64: return attrs.ArchValues.Arm64 default: var v *LabelList if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } return *v } // SetValueForArch sets the label_list attribute value for an architecture. func (attrs *LabelListAttribute) SetValueForArch(arch string, value LabelList) { switch arch { case "x86": attrs.ArchValues.X86 = value case "x86_64": attrs.ArchValues.X86_64 = value case "arm": attrs.ArchValues.Arm = value case "arm64": attrs.ArchValues.Arm64 = value default: var v *LabelList if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } *v = value } func (attrs *LabelListAttribute) osValuePtrs() map[string]*LabelList { return map[string]*LabelList{ OS_ANDROID: &attrs.OsValues.Android, OS_DARWIN: &attrs.OsValues.Darwin, OS_FUCHSIA: &attrs.OsValues.Fuchsia, OS_LINUX: &attrs.OsValues.Linux, OS_LINUX_BIONIC: &attrs.OsValues.LinuxBionic, OS_WINDOWS: &attrs.OsValues.Windows, } } // GetValueForOS returns the label_list attribute value for an OS target. func (attrs *LabelListAttribute) GetValueForOS(os string) LabelList { var v *LabelList if v = attrs.osValuePtrs()[os]; v == nil { panic(fmt.Errorf("Unknown os: %s", os)) } return *v } // SetValueForArch sets the label_list attribute value for an OS target. func (attrs *LabelListAttribute) SetValueForOS(os string, value LabelList) { var v *LabelList if v = attrs.osValuePtrs()[os]; v == nil { panic(fmt.Errorf("Unknown os: %s", os)) } *v = value } // StringListAttribute corresponds to the string_list Bazel attribute type with Loading @@ -182,13 +264,12 @@ type stringListArchValues struct { X86_64 []string Arm []string Arm64 []string // TODO(b/181299724): this is currently missing the "common" arch, which // doesn't have an equivalent platform() definition yet. Common []string } // HasArchSpecificValues returns true if the attribute contains // HasConfigurableValues returns true if the attribute contains // architecture-specific string_list values. func (attrs *StringListAttribute) HasArchSpecificValues() bool { func (attrs *StringListAttribute) HasConfigurableValues() bool { for _, arch := range selectableArchs { if len(attrs.GetValueForArch(arch)) > 0 { return true Loading @@ -197,36 +278,31 @@ func (attrs *StringListAttribute) HasArchSpecificValues() bool { return false } func (attrs *StringListAttribute) archValuePtrs() map[string]*[]string { return map[string]*[]string{ ARCH_X86: &attrs.ArchValues.X86, ARCH_X86_64: &attrs.ArchValues.X86_64, ARCH_ARM: &attrs.ArchValues.Arm, ARCH_ARM64: &attrs.ArchValues.Arm64, } } // GetValueForArch returns the string_list attribute value for an architecture. func (attrs *StringListAttribute) GetValueForArch(arch string) []string { switch arch { case ARCH_X86: return attrs.ArchValues.X86 case ARCH_X86_64: return attrs.ArchValues.X86_64 case ARCH_ARM: return attrs.ArchValues.Arm case ARCH_ARM64: return attrs.ArchValues.Arm64 default: var v *[]string if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } return *v } // SetValueForArch sets the string_list attribute value for an architecture. func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) { switch arch { case ARCH_X86: attrs.ArchValues.X86 = value case ARCH_X86_64: attrs.ArchValues.X86_64 = value case ARCH_ARM: attrs.ArchValues.Arm = value case ARCH_ARM64: attrs.ArchValues.Arm64 = value default: var v *[]string if v = attrs.archValuePtrs()[arch]; v == nil { panic(fmt.Errorf("Unknown arch: %s", arch)) } *v = value } // TryVariableSubstitution, replace string substitution formatting within each string in slice with Loading
bp2build/build_conversion.go +2 −54 Original line number Diff line number Diff line Loading @@ -416,63 +416,11 @@ func prettyPrint(propertyValue reflect.Value, indent int) (string, error) { // Special cases where the bp2build sends additional information to the codegenerator // by wrapping the attributes in a custom struct type. if labels, ok := propertyValue.Interface().(bazel.LabelListAttribute); ok { // TODO(b/165114590): convert glob syntax ret, err := prettyPrint(reflect.ValueOf(labels.Value.Includes), indent) if err != nil { return ret, err } if !labels.HasArchSpecificValues() { // Select statement not needed. return ret, nil } ret += " + " + "select({\n" for _, arch := range android.ArchTypeList() { value := labels.GetValueForArch(arch.Name) if len(value.Includes) > 0 { ret += makeIndent(indent + 1) list, _ := prettyPrint(reflect.ValueOf(value.Includes), indent+1) ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list) } } ret += makeIndent(indent + 1) ret += fmt.Sprintf("\"%s\": [],\n", "//conditions:default") ret += makeIndent(indent) ret += "})" return ret, err return prettyPrintLabelListAttribute(labels, indent) } else if label, ok := propertyValue.Interface().(bazel.Label); ok { return fmt.Sprintf("%q", label.Label), nil } else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok { // A Bazel string_list attribute that may contain a select statement. ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent) if err != nil { return ret, err } if !stringList.HasArchSpecificValues() { // Select statement not needed. return ret, nil } ret += " + " + "select({\n" for _, arch := range android.ArchTypeList() { value := stringList.GetValueForArch(arch.Name) if len(value) > 0 { ret += makeIndent(indent + 1) list, _ := prettyPrint(reflect.ValueOf(value), indent+1) ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list) } } ret += makeIndent(indent + 1) ret += fmt.Sprintf("\"%s\": [],\n", "//conditions:default") ret += makeIndent(indent) ret += "})" return ret, err return prettyPrintStringListAttribute(stringList, indent) } ret = "{\n" Loading