Merge "cc/sabi.go: Propagate ShouldCreateSourceAbiDump to reuseObjTag deps"
diff --git a/android/arch.go b/android/arch.go
index 9ff439c..1fbba19 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -15,6 +15,7 @@
package android
import (
+ "android/soong/bazel"
"encoding"
"fmt"
"reflect"
@@ -897,7 +898,7 @@
// Add the OS/Arch combinations, e.g. "android_arm64".
for _, archType := range osArchTypeMap[os] {
- targets = append(targets, GetCompoundTargetName(os, archType))
+ targets = append(targets, GetCompoundTargetField(os, archType))
// Also add the special "linux_<arch>" and "bionic_<arch>" property structs.
if os.Linux() {
@@ -1217,7 +1218,7 @@
return getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib)
}
-func GetCompoundTargetName(os OsType, arch ArchType) string {
+func GetCompoundTargetField(os OsType, arch ArchType) string {
return os.Field + "_" + arch.Name
}
@@ -1327,7 +1328,7 @@
// key: value,
// },
// },
- field := GetCompoundTargetName(os, archType)
+ field := GetCompoundTargetField(os, archType)
userFriendlyField := "target." + os.Name + "_" + archType.Name
if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
result = append(result, osArchProperties)
@@ -1565,7 +1566,10 @@
abi []string
}
-// getNdkAbisConfig returns a list of archConfigs for the ABIs supported by the NDK.
+// getNdkAbisConfig returns the list of archConfigs that are used for bulding
+// the API stubs and static libraries that are included in the NDK. These are
+// built *without Neon*, because non-Neon is still supported and building these
+// with Neon will break those users.
func getNdkAbisConfig() []archConfig {
return []archConfig{
{"arm", "armv7-a", "", []string{"armeabi-v7a"}},
@@ -1882,27 +1886,38 @@
PropertyErrorf(property, fmt string, args ...interface{})
}
-// GetArchProperties returns a map of architectures to the values of the
-// properties of the 'propertySet' struct that are specific to that architecture.
+// ArchVariantProperties represents a map of arch-variant config strings to a property interface{}.
+type ArchVariantProperties map[string]interface{}
+
+// ConfigurationAxisToArchVariantProperties represents a map of bazel.ConfigurationAxis to
+// ArchVariantProperties, such that each independent arch-variant axis maps to the
+// configs/properties for that axis.
+type ConfigurationAxisToArchVariantProperties map[bazel.ConfigurationAxis]ArchVariantProperties
+
+// GetArchVariantProperties returns a ConfigurationAxisToArchVariantProperties where the
+// arch-variant properties correspond to the values of the properties of the 'propertySet' struct
+// that are specific to that axis/configuration. Each axis is independent, containing
+// non-overlapping configs that correspond to the various "arch-variant" support, at this time:
+// arches (including multilib)
+// oses
+// arch+os combinations
//
-// 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 arch specific property value specified by the module if defined.
+// 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 config-specific property value specified
+// by the module if defined.
//
// Arch-specific properties may come from an arch stanza or a multilib stanza; properties
// in these stanzas are combined.
// For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }`
// will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given
// propertyset contains `Foo []string`.
-//
-// Implemented in a way very similar to GetTargetProperties().
-func (m *ModuleBase) GetArchProperties(ctx ArchVariantContext, propertySet interface{}) map[ArchType]interface{} {
+func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySet interface{}) ConfigurationAxisToArchVariantProperties {
// Return value of the arch types to the prop values for that arch.
- archToProp := map[ArchType]interface{}{}
+ axisToProps := ConfigurationAxisToArchVariantProperties{}
// Nothing to do for non-arch-specific modules.
if !m.ArchSpecific() {
- return archToProp
+ return axisToProps
}
dstType := reflect.ValueOf(propertySet).Type()
@@ -1920,9 +1935,10 @@
if archProperties == nil {
// This module does not have the property set requested
- return archToProp
+ return axisToProps
}
+ archToProp := ArchVariantProperties{}
// For each arch type (x86, arm64, etc.)
for _, arch := range ArchTypeList() {
// Arch properties are sometimes sharded (see createArchPropTypeDesc() ).
@@ -1948,10 +1964,30 @@
mergePropertyStruct(ctx, value, propertyStruct)
}
- archToProp[arch] = value
+ archToProp[arch.Name] = value
}
+ axisToProps[bazel.ArchConfigurationAxis] = archToProp
- return archToProp
+ osToProp := ArchVariantProperties{}
+ archOsToProp := ArchVariantProperties{}
+ // For android, linux, ...
+ for _, os := range osTypeList {
+ if os == CommonOS {
+ // It looks like this OS value is not used in Blueprint files
+ continue
+ }
+ osToProp[os.Name] = getTargetStruct(ctx, propertySet, archProperties, os.Field)
+ // For arm, x86, ...
+ for _, arch := range osArchTypeMap[os] {
+ targetField := GetCompoundTargetField(os, arch)
+ targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name)
+ archOsToProp[targetName] = getTargetStruct(ctx, propertySet, archProperties, targetField)
+ }
+ }
+ axisToProps[bazel.OsConfigurationAxis] = osToProp
+ axisToProps[bazel.OsArchConfigurationAxis] = archOsToProp
+
+ return axisToProps
}
// Returns a struct matching the propertySet interface, containing properties specific to the targetName
@@ -1989,69 +2025,3 @@
return value
}
-
-// Properties corresponds to e.g. Target: android: {...}
-// ArchProperties corresponds to e.g. Target: android_arm: {...}, android_arm64: {...}, ...
-type TargetProperties struct {
- Properties interface{}
- ArchProperties map[ArchType]interface{}
-}
-
-// GetTargetProperties returns a map of OS target (e.g. android, windows) to the
-// values of the properties of the 'propertySet' 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.
-//
-// Implemented in a way very similar to GetArchProperties().
-//
-// NOTE: "Target" == OS
-func (m *ModuleBase) GetTargetProperties(ctx ArchVariantContext, propertySet interface{}) map[OsType]TargetProperties {
- // Return value of the target types to the prop values for that target.
- targetToProp := map[OsType]TargetProperties{}
-
- // Nothing to do for non-target-specific modules.
- if !m.ArchSpecific() {
- return targetToProp
- }
-
- dstType := reflect.ValueOf(propertySet).Type()
- var archProperties []interface{}
-
- // First find the property set in the module that corresponds to the requested
- // one. m.archProperties[i] corresponds to m.generalProperties[i].
- for i, generalProp := range m.generalProperties {
- srcType := reflect.ValueOf(generalProp).Type()
- if srcType == dstType {
- archProperties = m.archProperties[i]
- break
- }
- }
-
- if archProperties == nil {
- // This module does not have the property set requested
- return targetToProp
- }
-
- // For android, linux, ...
- for _, os := range osTypeList {
- if os == CommonOS {
- // It looks like this OS value is not used in Blueprint files
- continue
- }
- targetProperties := TargetProperties{
- Properties: getTargetStruct(ctx, propertySet, archProperties, os.Field),
- ArchProperties: make(map[ArchType]interface{}),
- }
- // For arm, x86, ...
- for _, arch := range osArchTypeMap[os] {
- targetName := GetCompoundTargetName(os, arch)
- targetProperties.ArchProperties[arch] = getTargetStruct(ctx, propertySet, archProperties, targetName)
- }
- targetToProp[os] = targetProperties
- }
-
- return targetToProp
-}
diff --git a/android/bazel.go b/android/bazel.go
index 8c68055..d396561 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -221,6 +221,8 @@
// still be generated via bp2build.
mixedBuildsDisabledList = []string{
// Currently empty, though should remain present to facilitate granular bp2build migration.
+ "libdl", // missing libbionic_Slinker_Slibld-android_Ubp2build_Ucc_Ulibrary_Ushared.so
+ "libdl_android", // missing libbionic_Slinker_Slibld-android_Ubp2build_Ucc_Ulibrary_Ushared.so
}
// Used for quicker lookups
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index f4b2a7c..f93fe2b 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -100,6 +100,22 @@
return labels
}
+// BazelLabelForModuleDeps expects two lists: modules (containing modules to include in the list),
+// and excludes (modules to exclude from the list). Both of these should contain references to other
+// modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label list which corresponds
+// to dependencies on the module within the given ctx, and the excluded dependencies.
+func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
+ moduleLabels := BazelLabelForModuleDeps(ctx, RemoveListFromList(modules, excludes))
+ if len(excludes) == 0 {
+ return moduleLabels
+ }
+ excludeLabels := BazelLabelForModuleDeps(ctx, excludes)
+ return bazel.LabelList{
+ Includes: moduleLabels.Includes,
+ Excludes: excludeLabels.Includes,
+ }
+}
+
func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
return BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes[0]
}
diff --git a/android/override_module.go b/android/override_module.go
index 0a7e294..e72cb78 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -213,7 +213,6 @@
// to keep them in this order and not put any order mutators between them.
func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
- ctx.TopDown("register_override", registerOverrideMutator).Parallel()
ctx.BottomUp("perform_override", performOverrideMutator).Parallel()
// overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
// add deps from overridable properties.
@@ -253,20 +252,11 @@
return
}
})
- ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)
- }
-}
-
-// Visits the base module added as a dependency above, checks the module type, and registers the
-// overriding module.
-func registerOverrideMutator(ctx TopDownMutatorContext) {
- ctx.VisitDirectDepsWithTag(overrideBaseDepTag, func(base Module) {
- if o, ok := base.(OverridableModule); ok {
+ baseModule := ctx.AddDependency(ctx.Module(), overrideBaseDepTag, *module.getOverrideModuleProperties().Base)[0]
+ if o, ok := baseModule.(OverridableModule); ok {
o.addOverride(ctx.Module().(OverrideModule))
- } else {
- ctx.PropertyErrorf("base", "unsupported base module type")
}
- })
+ }
}
// Now, goes through all overridable modules, finds all modules overriding them, creates a local
diff --git a/android/variable.go b/android/variable.go
index 7658cdd..c766120 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -458,12 +458,13 @@
// with the appropriate ProductConfigVariable.
type ProductConfigProperty struct {
ProductConfigVariable string
+ FullConfig string
Property interface{}
}
// ProductConfigProperties is a map of property name to a slice of ProductConfigProperty such that
// all it all product variable-specific versions of a property are easily accessed together
-type ProductConfigProperties map[string][]ProductConfigProperty
+type ProductConfigProperties map[string]map[string]ProductConfigProperty
// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
// have been set for the module in the given context.
@@ -479,18 +480,11 @@
productVariableValues(moduleBase.variableProperties, "", &productConfigProperties)
- for arch, targetProps := range moduleBase.GetArchProperties(ctx, moduleBase.variableProperties) {
- // GetArchProperties is creating an instance of the requested type
- // and productVariablesValues expects an interface, so no need to cast
- productVariableValues(targetProps, arch.Name, &productConfigProperties)
- }
-
- for os, targetProps := range moduleBase.GetTargetProperties(ctx, moduleBase.variableProperties) {
- // GetTargetProperties is creating an instance of the requested type
- // and productVariablesValues expects an interface, so no need to cast
- productVariableValues(targetProps.Properties, os.Name, &productConfigProperties)
- for arch, archProperties := range targetProps.ArchProperties {
- productVariableValues(archProperties, os.Name+"_"+arch.Name, &productConfigProperties)
+ for _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
+ for config, props := range configToProps {
+ // GetArchVariantProperties is creating an instance of the requested type
+ // and productVariablesValues expects an interface, so no need to cast
+ productVariableValues(props, config, &productConfigProperties)
}
}
@@ -519,11 +513,15 @@
// e.g. Asflags, Cflags, Enabled, etc.
propertyName := variableValue.Type().Field(j).Name
- (*productConfigProperties)[propertyName] = append((*productConfigProperties)[propertyName],
- ProductConfigProperty{
- ProductConfigVariable: productVariableName + suffix,
- Property: property.Interface(),
- })
+ if (*productConfigProperties)[propertyName] == nil {
+ (*productConfigProperties)[propertyName] = make(map[string]ProductConfigProperty)
+ }
+ config := productVariableName + suffix
+ (*productConfigProperties)[propertyName][config] = ProductConfigProperty{
+ ProductConfigVariable: productVariableName,
+ FullConfig: config,
+ Property: property.Interface(),
+ }
}
}
}
diff --git a/bazel/Android.bp b/bazel/Android.bp
index b7c185a..b68d65b 100644
--- a/bazel/Android.bp
+++ b/bazel/Android.bp
@@ -7,6 +7,7 @@
pkgPath: "android/soong/bazel",
srcs: [
"aquery.go",
+ "configurability.go",
"constants.go",
"properties.go",
],
diff --git a/bazel/aquery.go b/bazel/aquery.go
index bda3a1a..d1119cb 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -247,7 +247,7 @@
func shouldSkipAction(a action) bool {
// TODO(b/180945121): Handle symlink actions.
- if a.Mnemonic == "Symlink" || a.Mnemonic == "SourceSymlinkManifest" || a.Mnemonic == "SymlinkTree" {
+ if a.Mnemonic == "Symlink" || a.Mnemonic == "SourceSymlinkManifest" || a.Mnemonic == "SymlinkTree" || a.Mnemonic == "SolibSymlink" {
return true
}
// Middleman actions are not handled like other actions; they are handled separately as a
diff --git a/bazel/configurability.go b/bazel/configurability.go
new file mode 100644
index 0000000..282c606
--- /dev/null
+++ b/bazel/configurability.go
@@ -0,0 +1,213 @@
+// 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"
+ "strings"
+)
+
+const (
+ // ArchType names in arch.go
+ archArm = "arm"
+ archArm64 = "arm64"
+ archX86 = "x86"
+ archX86_64 = "x86_64"
+
+ // OsType names in arch.go
+ osAndroid = "android"
+ osDarwin = "darwin"
+ osFuchsia = "fuchsia"
+ osLinux = "linux_glibc"
+ osLinuxBionic = "linux_bionic"
+ osWindows = "windows"
+
+ // Targets in arch.go
+ osArchAndroidArm = "android_arm"
+ osArchAndroidArm64 = "android_arm64"
+ osArchAndroidX86 = "android_x86"
+ osArchAndroidX86_64 = "android_x86_64"
+ osArchDarwinX86_64 = "darwin_x86_64"
+ osArchFuchsiaArm64 = "fuchsia_arm64"
+ osArchFuchsiaX86_64 = "fuchsia_x86_64"
+ osArchLinuxX86 = "linux_glibc_x86"
+ osArchLinuxX86_64 = "linux_glibc_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).
+ conditionsDefault = "conditions_default"
+
+ ConditionsDefaultSelectKey = "//conditions:default"
+
+ productVariableBazelPackage = "//build/bazel/product_variables"
+)
+
+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 = map[string]string{
+ archArm: "//build/bazel/platforms/arch:arm",
+ archArm64: "//build/bazel/platforms/arch:arm64",
+ archX86: "//build/bazel/platforms/arch:x86",
+ archX86_64: "//build/bazel/platforms/arch:x86_64",
+ conditionsDefault: ConditionsDefaultSelectKey, // The default condition of as arch select map.
+ }
+
+ // 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",
+ osFuchsia: "//build/bazel/platforms/os:fuchsia",
+ osLinux: "//build/bazel/platforms/os:linux",
+ osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
+ osWindows: "//build/bazel/platforms/os:windows",
+ conditionsDefault: 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",
+ osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
+ osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
+ osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
+ osArchFuchsiaArm64: "//build/bazel/platforms/os_arch:fuchsia_arm64",
+ osArchFuchsiaX86_64: "//build/bazel/platforms/os_arch:fuchsia_x86_64",
+ osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
+ osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_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",
+ conditionsDefault: ConditionsDefaultSelectKey, // The default condition of an os select map.
+ }
+)
+
+// basic configuration types
+type configurationType int
+
+const (
+ noConfig configurationType = iota
+ arch
+ os
+ osArch
+ productVariables
+)
+
+func (ct configurationType) String() string {
+ return map[configurationType]string{
+ noConfig: "no_config",
+ arch: "arch",
+ os: "os",
+ osArch: "arch_os",
+ productVariables: "product_variables",
+ }[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
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
+ }
+}
+
+// SelectKey returns the Bazel select key for a given configurationType and config string.
+func (ct configurationType) SelectKey(config string) string {
+ ct.validateConfig(config)
+ switch ct {
+ 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 == conditionsDefault {
+ return ConditionsDefaultSelectKey
+ }
+ return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(config))
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationType %d", ct))
+ }
+}
+
+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}
+)
+
+// ProductVariableConfigurationAxis returns an axis for the given product variable
+func ProductVariableConfigurationAxis(variable string) ConfigurationAxis {
+ return ConfigurationAxis{
+ configurationType: productVariables,
+ subType: variable,
+ }
+}
+
+// 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
+}
+
+func (ca *ConfigurationAxis) less(other ConfigurationAxis) bool {
+ if ca.configurationType < other.configurationType {
+ return true
+ }
+ return ca.subType < other.subType
+}
diff --git a/bazel/cquery/request_type.go b/bazel/cquery/request_type.go
index c30abeb..92135c6 100644
--- a/bazel/cquery/request_type.go
+++ b/bazel/cquery/request_type.go
@@ -16,6 +16,10 @@
CcStaticLibraryFiles []string
Includes []string
SystemIncludes []string
+ // Archives owned by the current target (not by its dependencies). These will
+ // be a subset of OutputFiles. (or static libraries, this will be equal to OutputFiles,
+ // but general cc_library will also have dynamic libraries in output files).
+ RootStaticArchives []string
}
type getOutputFilesRequestType struct{}
@@ -70,6 +74,7 @@
ccObjectFiles = []
staticLibraries = []
+rootStaticArchives = []
linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
for linker_input in linker_inputs:
@@ -78,6 +83,8 @@
ccObjectFiles += [object.path]
if library.static_library:
staticLibraries.append(library.static_library.path)
+ if linker_input.owner == target.label:
+ rootStaticArchives.append(library.static_library.path)
returns = [
outputFiles,
@@ -85,6 +92,7 @@
ccObjectFiles,
includes,
system_includes,
+ rootStaticArchives
]
return "|".join([", ".join(r) for r in returns])`
@@ -98,7 +106,7 @@
var ccObjects []string
splitString := strings.Split(rawString, "|")
- if expectedLen := 5; len(splitString) != expectedLen {
+ if expectedLen := 6; len(splitString) != expectedLen {
return CcInfo{}, fmt.Errorf("Expected %d items, got %q", expectedLen, splitString)
}
outputFilesString := splitString[0]
@@ -109,12 +117,14 @@
ccObjects = splitOrEmpty(ccObjectsString, ", ")
includes := splitOrEmpty(splitString[3], ", ")
systemIncludes := splitOrEmpty(splitString[4], ", ")
+ rootStaticArchives := splitOrEmpty(splitString[5], ", ")
return CcInfo{
OutputFiles: outputFiles,
CcObjectFiles: ccObjects,
CcStaticLibraryFiles: ccStaticLibraries,
Includes: includes,
SystemIncludes: systemIncludes,
+ RootStaticArchives: rootStaticArchives,
}, nil
}
diff --git a/bazel/cquery/request_type_test.go b/bazel/cquery/request_type_test.go
index 6369999..602849e 100644
--- a/bazel/cquery/request_type_test.go
+++ b/bazel/cquery/request_type_test.go
@@ -46,48 +46,51 @@
}{
{
description: "no result",
- input: "||||",
+ input: "|||||",
expectedOutput: CcInfo{
OutputFiles: []string{},
CcObjectFiles: []string{},
CcStaticLibraryFiles: []string{},
Includes: []string{},
SystemIncludes: []string{},
+ RootStaticArchives: []string{},
},
},
{
description: "only output",
- input: "test||||",
+ input: "test|||||",
expectedOutput: CcInfo{
OutputFiles: []string{"test"},
CcObjectFiles: []string{},
CcStaticLibraryFiles: []string{},
Includes: []string{},
SystemIncludes: []string{},
+ RootStaticArchives: []string{},
},
},
{
description: "all items set",
- input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir",
+ input: "out1, out2|static_lib1, static_lib2|object1, object2|., dir/subdir|system/dir, system/other/dir|rootstaticarchive1",
expectedOutput: CcInfo{
OutputFiles: []string{"out1", "out2"},
CcObjectFiles: []string{"object1", "object2"},
CcStaticLibraryFiles: []string{"static_lib1", "static_lib2"},
Includes: []string{".", "dir/subdir"},
SystemIncludes: []string{"system/dir", "system/other/dir"},
+ RootStaticArchives: []string{"rootstaticarchive1"},
},
},
{
description: "too few result splits",
input: "|",
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 5, []string{"", ""}),
+ expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 6, []string{"", ""}),
},
{
description: "too many result splits",
input: strings.Repeat("|", 8),
expectedOutput: CcInfo{},
- expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 5, make([]string, 9)),
+ expectedErrorMessage: fmt.Sprintf("Expected %d items, got %q", 6, make([]string, 9)),
},
}
for _, tc := range testCases {
diff --git a/bazel/properties.go b/bazel/properties.go
index 951081c..99119cd 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -19,7 +19,6 @@
"path/filepath"
"regexp"
"sort"
- "strings"
)
// BazelTargetModuleProperties contain properties and metadata used for
@@ -65,6 +64,17 @@
Excludes []Label
}
+func (ll *LabelList) IsNil() bool {
+ return ll.Includes == nil && ll.Excludes == nil
+}
+
+func (ll *LabelList) deepCopy() LabelList {
+ return LabelList{
+ Includes: ll.Includes[:],
+ Excludes: ll.Excludes[:],
+ }
+}
+
// uniqueParentDirectories returns a list of the unique parent directories for
// all files in ll.Includes.
func (ll *LabelList) uniqueParentDirectories() []string {
@@ -106,7 +116,27 @@
return uniqueLabels
}
-func UniqueBazelLabelList(originalLabelList LabelList) LabelList {
+func FirstUniqueBazelLabels(originalLabels []Label) []Label {
+ var labels []Label
+ found := make(map[Label]bool, len(originalLabels))
+ for _, l := range originalLabels {
+ if _, ok := found[l]; ok {
+ continue
+ }
+ labels = append(labels, l)
+ found[l] = true
+ }
+ return labels
+}
+
+func FirstUniqueBazelLabelList(originalLabelList LabelList) LabelList {
+ var uniqueLabelList LabelList
+ uniqueLabelList.Includes = FirstUniqueBazelLabels(originalLabelList.Includes)
+ uniqueLabelList.Excludes = FirstUniqueBazelLabels(originalLabelList.Excludes)
+ return uniqueLabelList
+}
+
+func UniqueSortedBazelLabelList(originalLabelList LabelList) LabelList {
var uniqueLabelList LabelList
uniqueLabelList.Includes = UniqueSortedBazelLabels(originalLabelList.Includes)
uniqueLabelList.Excludes = UniqueSortedBazelLabels(originalLabelList.Excludes)
@@ -154,16 +184,9 @@
result.Value = MapLabelList(mapOver.Value, mapFn)
- for arch := range PlatformArchMap {
- result.SetValueForArch(arch, MapLabelList(mapOver.GetValueForArch(arch), mapFn))
- }
-
- for os := range PlatformOsMap {
- result.SetOsValueForTarget(os, MapLabelList(mapOver.GetOsValueForTarget(os), mapFn))
-
- // TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
- for _, arch := range AllArches {
- result.SetOsArchValueForTarget(os, arch, MapLabelList(mapOver.GetOsArchValueForTarget(os, arch), mapFn))
+ for axis, configToLabels := range mapOver.ConfigurableValues {
+ for config, value := range configToLabels {
+ result.SetSelectValue(axis, config, MapLabelList(value, mapFn))
}
}
@@ -184,21 +207,14 @@
// Return all needles in a given haystack, where needleFn is true for needles.
func FilterLabelListAttribute(haystack LabelListAttribute, needleFn func(string) bool) LabelListAttribute {
- var result LabelListAttribute
+ result := MakeLabelListAttribute(FilterLabelList(haystack.Value, needleFn))
- result.Value = FilterLabelList(haystack.Value, needleFn)
-
- for arch := range PlatformArchMap {
- result.SetValueForArch(arch, FilterLabelList(haystack.GetValueForArch(arch), needleFn))
- }
-
- for os := range PlatformOsMap {
- result.SetOsValueForTarget(os, FilterLabelList(haystack.GetOsValueForTarget(os), needleFn))
-
- // TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
- for _, arch := range AllArches {
- result.SetOsArchValueForTarget(os, arch, FilterLabelList(haystack.GetOsArchValueForTarget(os, arch), needleFn))
+ for config, selects := range haystack.ConfigurableValues {
+ newSelects := make(labelListSelectValues, len(selects))
+ for k, v := range selects {
+ newSelects[k] = FilterLabelList(v, needleFn)
}
+ result.ConfigurableValues[config] = newSelects
}
return result
@@ -206,24 +222,18 @@
// Subtract needle from haystack
func SubtractBazelLabelListAttribute(haystack LabelListAttribute, needle LabelListAttribute) LabelListAttribute {
- var result LabelListAttribute
+ result := MakeLabelListAttribute(SubtractBazelLabelList(haystack.Value, needle.Value))
- for arch := range PlatformArchMap {
- result.SetValueForArch(arch,
- SubtractBazelLabelList(haystack.GetValueForArch(arch), needle.GetValueForArch(arch)))
- }
+ for config, selects := range haystack.ConfigurableValues {
+ newSelects := make(labelListSelectValues, len(selects))
+ needleSelects := needle.ConfigurableValues[config]
- for os := range PlatformOsMap {
- result.SetOsValueForTarget(os, SubtractBazelLabelList(haystack.GetOsValueForTarget(os), needle.GetOsValueForTarget(os)))
-
- // TODO(b/187530594): Should we handle arch=CONDITIONS_DEFAULT here? (not in ArchValues)
- for _, arch := range AllArches {
- result.SetOsArchValueForTarget(os, arch, SubtractBazelLabelList(haystack.GetOsArchValueForTarget(os, arch), needle.GetOsArchValueForTarget(os, arch)))
+ for k, v := range selects {
+ newSelects[k] = SubtractBazelLabelList(v, needleSelects[k])
}
+ result.ConfigurableValues[config] = newSelects
}
- result.Value = SubtractBazelLabelList(haystack.Value, needle.Value)
-
return result
}
@@ -268,489 +278,235 @@
return result
}
-const (
- // 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"
-
- // Targets in arch.go
- TARGET_ANDROID_ARM = "android_arm"
- TARGET_ANDROID_ARM64 = "android_arm64"
- TARGET_ANDROID_X86 = "android_x86"
- TARGET_ANDROID_X86_64 = "android_x86_64"
- TARGET_DARWIN_X86_64 = "darwin_x86_64"
- TARGET_FUCHSIA_ARM64 = "fuchsia_arm64"
- TARGET_FUCHSIA_X86_64 = "fuchsia_x86_64"
- TARGET_LINUX_X86 = "linux_glibc_x86"
- TARGET_LINUX_x86_64 = "linux_glibc_x86_64"
- TARGET_LINUX_BIONIC_ARM64 = "linux_bionic_arm64"
- TARGET_LINUX_BIONIC_X86_64 = "linux_bionic_x86_64"
- TARGET_WINDOWS_X86 = "windows_x86"
- TARGET_WINDOWS_X86_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).
- CONDITIONS_DEFAULT = "conditions_default"
-
- ConditionsDefaultSelectKey = "//conditions:default"
-
- productVariableBazelPackage = "//build/bazel/product_variables"
-)
-
-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 = 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",
- CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of as arch select map.
- }
-
- // 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",
- CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
- }
-
- PlatformTargetMap = map[string]string{
- TARGET_ANDROID_ARM: "//build/bazel/platforms/os_arch:android_arm",
- TARGET_ANDROID_ARM64: "//build/bazel/platforms/os_arch:android_arm64",
- TARGET_ANDROID_X86: "//build/bazel/platforms/os_arch:android_x86",
- TARGET_ANDROID_X86_64: "//build/bazel/platforms/os_arch:android_x86_64",
- TARGET_DARWIN_X86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
- TARGET_FUCHSIA_ARM64: "//build/bazel/platforms/os_arch:fuchsia_arm64",
- TARGET_FUCHSIA_X86_64: "//build/bazel/platforms/os_arch:fuchsia_x86_64",
- TARGET_LINUX_X86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
- TARGET_LINUX_x86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
- TARGET_LINUX_BIONIC_ARM64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
- TARGET_LINUX_BIONIC_X86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
- TARGET_WINDOWS_X86: "//build/bazel/platforms/os_arch:windows_x86",
- TARGET_WINDOWS_X86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
- CONDITIONS_DEFAULT: ConditionsDefaultSelectKey, // The default condition of an os select map.
- }
-
- // TODO(b/187530594): Should we add CONDITIONS_DEFAULT here?
- AllArches = []string{ARCH_ARM, ARCH_ARM64, ARCH_X86, ARCH_X86_64}
-)
-
type Attribute interface {
HasConfigurableValues() bool
}
-type labelArchValues struct {
- X86 Label
- X86_64 Label
- Arm Label
- Arm64 Label
+type labelSelectValues map[string]*Label
- ConditionsDefault Label
-}
+type configurableLabels map[ConfigurationAxis]labelSelectValues
-type labelTargetValue struct {
- // E.g. for android
- OsValue Label
-
- // E.g. for android_arm, android_arm64, ...
- ArchValues labelArchValues
-}
-
-type labelTargetValues struct {
- Android labelTargetValue
- Darwin labelTargetValue
- Fuchsia labelTargetValue
- Linux labelTargetValue
- LinuxBionic labelTargetValue
- Windows labelTargetValue
-
- ConditionsDefault labelTargetValue
+func (cl configurableLabels) setValueForAxis(axis ConfigurationAxis, config string, value *Label) {
+ if cl[axis] == nil {
+ cl[axis] = make(labelSelectValues)
+ }
+ cl[axis][config] = value
}
// Represents an attribute whose value is a single label
type LabelAttribute struct {
- Value Label
+ Value *Label
- ArchValues labelArchValues
-
- TargetValues labelTargetValues
+ ConfigurableValues configurableLabels
}
-func (attr *LabelAttribute) GetValueForArch(arch string) Label {
- var v *Label
- if v = attr.archValuePtrs()[arch]; v == nil {
- panic(fmt.Errorf("Unknown arch: %s", arch))
- }
- return *v
+// HasConfigurableValues returns whether there are configurable values set for this label.
+func (la LabelAttribute) HasConfigurableValues() bool {
+ return len(la.ConfigurableValues) > 0
}
-func (attr *LabelAttribute) SetValueForArch(arch string, value Label) {
- var v *Label
- if v = attr.archValuePtrs()[arch]; v == nil {
- panic(fmt.Errorf("Unknown arch: %s", arch))
- }
- *v = value
+// SetValue sets the base, non-configured value for the Label
+func (la *LabelAttribute) SetValue(value Label) {
+ la.SetSelectValue(NoConfigAxis, "", value)
}
-func (attr *LabelAttribute) archValuePtrs() map[string]*Label {
- return map[string]*Label{
- ARCH_X86: &attr.ArchValues.X86,
- ARCH_X86_64: &attr.ArchValues.X86_64,
- ARCH_ARM: &attr.ArchValues.Arm,
- ARCH_ARM64: &attr.ArchValues.Arm64,
- CONDITIONS_DEFAULT: &attr.ArchValues.ConditionsDefault,
- }
-}
-
-func (attr LabelAttribute) HasConfigurableValues() bool {
- for arch := range PlatformArchMap {
- if attr.GetValueForArch(arch).Label != "" {
- return true
+// SetSelectValue set a value for a bazel select for the given axis, config and value.
+func (la *LabelAttribute) SetSelectValue(axis ConfigurationAxis, config string, value Label) {
+ axis.validateConfig(config)
+ switch axis.configurationType {
+ case noConfig:
+ la.Value = &value
+ case arch, os, osArch, productVariables:
+ if la.ConfigurableValues == nil {
+ la.ConfigurableValues = make(configurableLabels)
}
+ la.ConfigurableValues.setValueForAxis(axis, config, &value)
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+ }
+}
+
+// SelectValue gets a value for a bazel select for the given axis and config.
+func (la *LabelAttribute) SelectValue(axis ConfigurationAxis, config string) Label {
+ axis.validateConfig(config)
+ switch axis.configurationType {
+ case noConfig:
+ return *la.Value
+ case arch, os, osArch, productVariables:
+ return *la.ConfigurableValues[axis][config]
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+ }
+}
+
+// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
+func (la *LabelAttribute) SortedConfigurationAxes() []ConfigurationAxis {
+ keys := make([]ConfigurationAxis, 0, len(la.ConfigurableValues))
+ for k := range la.ConfigurableValues {
+ keys = append(keys, k)
}
- for os := range PlatformOsMap {
- if attr.GetOsValueForTarget(os).Label != "" {
+ sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
+ return keys
+}
+
+// labelListSelectValues supports config-specific label_list typed Bazel attribute values.
+type labelListSelectValues map[string]LabelList
+
+func (ll labelListSelectValues) appendSelects(other labelListSelectValues) {
+ for k, v := range other {
+ l := ll[k]
+ (&l).Append(v)
+ ll[k] = l
+ }
+}
+
+// HasConfigurableValues returns whether there are configurable values within this set of selects.
+func (ll labelListSelectValues) HasConfigurableValues() bool {
+ for _, v := range ll {
+ if len(v.Includes) > 0 {
return true
}
- // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT (not in AllArches)
- for _, arch := range AllArches {
- if attr.GetOsArchValueForTarget(os, arch).Label != "" {
- return true
- }
- }
}
return false
}
-func (attr *LabelAttribute) getValueForTarget(os string) labelTargetValue {
- var v *labelTargetValue
- if v = attr.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- return *v
-}
-
-func (attr *LabelAttribute) GetOsValueForTarget(os string) Label {
- var v *labelTargetValue
- if v = attr.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- return v.OsValue
-}
-
-func (attr *LabelAttribute) GetOsArchValueForTarget(os string, arch string) Label {
- var v *labelTargetValue
- if v = attr.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- switch arch {
- case ARCH_X86:
- return v.ArchValues.X86
- case ARCH_X86_64:
- return v.ArchValues.X86_64
- case ARCH_ARM:
- return v.ArchValues.Arm
- case ARCH_ARM64:
- return v.ArchValues.Arm64
- case CONDITIONS_DEFAULT:
- return v.ArchValues.ConditionsDefault
- default:
- panic(fmt.Errorf("Unknown arch: %s\n", arch))
- }
-}
-
-func (attr *LabelAttribute) setValueForTarget(os string, value labelTargetValue) {
- var v *labelTargetValue
- if v = attr.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- *v = value
-}
-
-func (attr *LabelAttribute) SetOsValueForTarget(os string, value Label) {
- var v *labelTargetValue
- if v = attr.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- v.OsValue = value
-}
-
-func (attr *LabelAttribute) SetOsArchValueForTarget(os string, arch string, value Label) {
- var v *labelTargetValue
- if v = attr.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- switch arch {
- case ARCH_X86:
- v.ArchValues.X86 = value
- case ARCH_X86_64:
- v.ArchValues.X86_64 = value
- case ARCH_ARM:
- v.ArchValues.Arm = value
- case ARCH_ARM64:
- v.ArchValues.Arm64 = value
- case CONDITIONS_DEFAULT:
- v.ArchValues.ConditionsDefault = value
- default:
- panic(fmt.Errorf("Unknown arch: %s\n", arch))
- }
-}
-
-func (attr *LabelAttribute) targetValuePtrs() map[string]*labelTargetValue {
- return map[string]*labelTargetValue{
- OS_ANDROID: &attr.TargetValues.Android,
- OS_DARWIN: &attr.TargetValues.Darwin,
- OS_FUCHSIA: &attr.TargetValues.Fuchsia,
- OS_LINUX: &attr.TargetValues.Linux,
- OS_LINUX_BIONIC: &attr.TargetValues.LinuxBionic,
- OS_WINDOWS: &attr.TargetValues.Windows,
- CONDITIONS_DEFAULT: &attr.TargetValues.ConditionsDefault,
- }
-}
-
-// Arch-specific label_list typed Bazel attribute values. This should correspond
-// to the types of architectures supported for compilation in arch.go.
-type labelListArchValues struct {
- X86 LabelList
- X86_64 LabelList
- Arm LabelList
- Arm64 LabelList
-
- ConditionsDefault LabelList
-}
-
-type labelListTargetValue struct {
- // E.g. for android
- OsValue LabelList
-
- // E.g. for android_arm, android_arm64, ...
- ArchValues labelListArchValues
-}
-
-func (target *labelListTargetValue) Append(other labelListTargetValue) {
- target.OsValue.Append(other.OsValue)
- target.ArchValues.X86.Append(other.ArchValues.X86)
- target.ArchValues.X86_64.Append(other.ArchValues.X86_64)
- target.ArchValues.Arm.Append(other.ArchValues.Arm)
- target.ArchValues.Arm64.Append(other.ArchValues.Arm64)
- target.ArchValues.ConditionsDefault.Append(other.ArchValues.ConditionsDefault)
-}
-
-type labelListTargetValues struct {
- Android labelListTargetValue
- Darwin labelListTargetValue
- Fuchsia labelListTargetValue
- Linux labelListTargetValue
- LinuxBionic labelListTargetValue
- Windows labelListTargetValue
-
- ConditionsDefault labelListTargetValue
-}
-
// LabelListAttribute is used to represent a list of Bazel labels as an
// attribute.
type LabelListAttribute struct {
- // The non-arch specific attribute label list Value. Required.
+ // The non-configured attribute label list Value. Required.
Value LabelList
- // The arch-specific attribute label list values. Optional. If used, these
- // are generated in a select statement and appended to the non-arch specific
- // label list Value.
- ArchValues labelListArchValues
+ // The configured attribute label list Values. Optional
+ // a map of independent configurability axes
+ ConfigurableValues configurableLabelLists
+}
- // 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.
- TargetValues labelListTargetValues
+type configurableLabelLists map[ConfigurationAxis]labelListSelectValues
+
+func (cll configurableLabelLists) setValueForAxis(axis ConfigurationAxis, config string, list LabelList) {
+ if list.IsNil() {
+ if _, ok := cll[axis][config]; ok {
+ delete(cll[axis], config)
+ }
+ return
+ }
+ if cll[axis] == nil {
+ cll[axis] = make(labelListSelectValues)
+ }
+
+ cll[axis][config] = list
+}
+
+func (cll configurableLabelLists) Append(other configurableLabelLists) {
+ for axis, otherSelects := range other {
+ selects := cll[axis]
+ if selects == nil {
+ selects = make(labelListSelectValues, len(otherSelects))
+ }
+ selects.appendSelects(otherSelects)
+ cll[axis] = selects
+ }
}
// MakeLabelListAttribute initializes a LabelListAttribute with the non-arch specific value.
func MakeLabelListAttribute(value LabelList) LabelListAttribute {
- return LabelListAttribute{Value: UniqueBazelLabelList(value)}
+ return LabelListAttribute{
+ Value: value,
+ ConfigurableValues: make(configurableLabelLists),
+ }
+}
+
+func (lla *LabelListAttribute) SetValue(list LabelList) {
+ lla.SetSelectValue(NoConfigAxis, "", list)
+}
+
+// SetSelectValue set a value for a bazel select for the given axis, config and value.
+func (lla *LabelListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list LabelList) {
+ axis.validateConfig(config)
+ switch axis.configurationType {
+ case noConfig:
+ lla.Value = list
+ case arch, os, osArch, productVariables:
+ if lla.ConfigurableValues == nil {
+ lla.ConfigurableValues = make(configurableLabelLists)
+ }
+ lla.ConfigurableValues.setValueForAxis(axis, config, list)
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+ }
+}
+
+// SelectValue gets a value for a bazel select for the given axis and config.
+func (lla *LabelListAttribute) SelectValue(axis ConfigurationAxis, config string) LabelList {
+ axis.validateConfig(config)
+ switch axis.configurationType {
+ case noConfig:
+ return lla.Value
+ case arch, os, osArch, productVariables:
+ return lla.ConfigurableValues[axis][config]
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+ }
+}
+
+// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
+func (lla *LabelListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
+ keys := make([]ConfigurationAxis, 0, len(lla.ConfigurableValues))
+ for k := range lla.ConfigurableValues {
+ keys = append(keys, k)
+ }
+
+ sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
+ return keys
}
// Append all values, including os and arch specific ones, from another
// LabelListAttribute to this LabelListAttribute.
-func (attrs *LabelListAttribute) Append(other LabelListAttribute) {
- for arch := range PlatformArchMap {
- this := attrs.GetValueForArch(arch)
- that := other.GetValueForArch(arch)
- this.Append(that)
- attrs.SetValueForArch(arch, this)
+func (lla *LabelListAttribute) Append(other LabelListAttribute) {
+ lla.Value.Append(other.Value)
+ if lla.ConfigurableValues == nil {
+ lla.ConfigurableValues = make(configurableLabelLists)
}
-
- for os := range PlatformOsMap {
- this := attrs.getValueForTarget(os)
- that := other.getValueForTarget(os)
- this.Append(that)
- attrs.setValueForTarget(os, this)
- }
-
- attrs.Value.Append(other.Value)
+ lla.ConfigurableValues.Append(other.ConfigurableValues)
}
-// HasArchSpecificValues returns true if the attribute contains
-// architecture-specific label_list values.
-func (attrs LabelListAttribute) HasConfigurableValues() bool {
- for arch := range PlatformArchMap {
- if len(attrs.GetValueForArch(arch).Includes) > 0 {
- return true
+// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
+func (lla LabelListAttribute) HasConfigurableValues() bool {
+ return len(lla.ConfigurableValues) > 0
+}
+
+// ResolveExcludes handles excludes across the various axes, ensuring that items are removed from
+// the base value and included in default values as appropriate.
+func (lla *LabelListAttribute) ResolveExcludes() {
+ for axis, configToLabels := range lla.ConfigurableValues {
+ baseLabels := lla.Value.deepCopy()
+ for config, val := range configToLabels {
+ // Exclude config-specific excludes from base value
+ lla.Value = SubtractBazelLabelList(lla.Value, LabelList{Includes: val.Excludes})
+
+ // add base values to config specific to add labels excluded by others in this axis
+ // then remove all config-specific excludes
+ allLabels := baseLabels.deepCopy()
+ allLabels.Append(val)
+ lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(allLabels, LabelList{Includes: val.Excludes})
}
- }
- for os := range PlatformOsMap {
- if len(attrs.GetOsValueForTarget(os).Includes) > 0 {
- return true
+ // After going through all configs, delete the duplicates in the config
+ // values that are already in the base Value.
+ for config, val := range configToLabels {
+ lla.ConfigurableValues[axis][config] = SubtractBazelLabelList(val, lla.Value)
}
- // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT (not in AllArches)
- for _, arch := range AllArches {
- if len(attrs.GetOsArchValueForTarget(os, arch).Includes) > 0 {
- return true
- }
+
+ // Now that the Value list is finalized for this axis, compare it with the original
+ // list, and put the difference into the default condition for the axis.
+ lla.ConfigurableValues[axis][conditionsDefault] = SubtractBazelLabelList(baseLabels, lla.Value)
+
+ // if everything ends up without includes, just delete the axis
+ if !lla.ConfigurableValues[axis].HasConfigurableValues() {
+ delete(lla.ConfigurableValues, axis)
}
}
- 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,
- CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
- }
-}
-
-// GetValueForArch returns the label_list attribute value for an architecture.
-func (attrs *LabelListAttribute) GetValueForArch(arch string) LabelList {
- 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) {
- var v *LabelList
- if v = attrs.archValuePtrs()[arch]; v == nil {
- panic(fmt.Errorf("Unknown arch: %s", arch))
- }
- *v = value
-}
-
-func (attrs *LabelListAttribute) targetValuePtrs() map[string]*labelListTargetValue {
- return map[string]*labelListTargetValue{
- OS_ANDROID: &attrs.TargetValues.Android,
- OS_DARWIN: &attrs.TargetValues.Darwin,
- OS_FUCHSIA: &attrs.TargetValues.Fuchsia,
- OS_LINUX: &attrs.TargetValues.Linux,
- OS_LINUX_BIONIC: &attrs.TargetValues.LinuxBionic,
- OS_WINDOWS: &attrs.TargetValues.Windows,
- CONDITIONS_DEFAULT: &attrs.TargetValues.ConditionsDefault,
- }
-}
-
-func (attrs *LabelListAttribute) getValueForTarget(os string) labelListTargetValue {
- var v *labelListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- return *v
-}
-
-func (attrs *LabelListAttribute) GetOsValueForTarget(os string) LabelList {
- var v *labelListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- return v.OsValue
-}
-
-func (attrs *LabelListAttribute) GetOsArchValueForTarget(os string, arch string) LabelList {
- var v *labelListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- switch arch {
- case ARCH_X86:
- return v.ArchValues.X86
- case ARCH_X86_64:
- return v.ArchValues.X86_64
- case ARCH_ARM:
- return v.ArchValues.Arm
- case ARCH_ARM64:
- return v.ArchValues.Arm64
- case CONDITIONS_DEFAULT:
- return v.ArchValues.ConditionsDefault
- default:
- panic(fmt.Errorf("Unknown arch: %s\n", arch))
- }
-}
-
-func (attrs *LabelListAttribute) setValueForTarget(os string, value labelListTargetValue) {
- var v *labelListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- *v = value
-}
-
-func (attrs *LabelListAttribute) SetOsValueForTarget(os string, value LabelList) {
- var v *labelListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- v.OsValue = value
-}
-
-func (attrs *LabelListAttribute) SetOsArchValueForTarget(os string, arch string, value LabelList) {
- var v *labelListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- switch arch {
- case ARCH_X86:
- v.ArchValues.X86 = value
- case ARCH_X86_64:
- v.ArchValues.X86_64 = value
- case ARCH_ARM:
- v.ArchValues.Arm = value
- case ARCH_ARM64:
- v.ArchValues.Arm64 = value
- case CONDITIONS_DEFAULT:
- v.ArchValues.ConditionsDefault = value
- default:
- panic(fmt.Errorf("Unknown arch: %s\n", arch))
- }
}
// StringListAttribute corresponds to the string_list Bazel attribute type with
@@ -759,256 +515,110 @@
// The base value of the string list attribute.
Value []string
- // The arch-specific attribute string list values. Optional. If used, these
- // are generated in a select statement and appended to the non-arch specific
- // label list Value.
- ArchValues stringListArchValues
+ // The configured attribute label list Values. Optional
+ // a map of independent configurability axes
+ ConfigurableValues configurableStringLists
+}
- // The os-specific attribute string list values. Optional. If used, these
- // are generated in a select statement and appended to the non-os specific
- // label list Value.
- TargetValues stringListTargetValues
+type configurableStringLists map[ConfigurationAxis]stringListSelectValues
- // list of product-variable string list values. Optional. if used, each will generate a select
- // statement appended to the label list Value.
- ProductValues []ProductVariableValues
+func (csl configurableStringLists) Append(other configurableStringLists) {
+ for axis, otherSelects := range other {
+ selects := csl[axis]
+ if selects == nil {
+ selects = make(stringListSelectValues, len(otherSelects))
+ }
+ selects.appendSelects(otherSelects)
+ csl[axis] = selects
+ }
+}
+
+func (csl configurableStringLists) setValueForAxis(axis ConfigurationAxis, config string, list []string) {
+ if csl[axis] == nil {
+ csl[axis] = make(stringListSelectValues)
+ }
+ csl[axis][config] = list
+}
+
+type stringListSelectValues map[string][]string
+
+func (sl stringListSelectValues) appendSelects(other stringListSelectValues) {
+ for k, v := range other {
+ sl[k] = append(sl[k], v...)
+ }
+}
+
+func (sl stringListSelectValues) hasConfigurableValues(other stringListSelectValues) bool {
+ for _, val := range sl {
+ if len(val) > 0 {
+ return true
+ }
+ }
+ return false
}
// MakeStringListAttribute initializes a StringListAttribute with the non-arch specific value.
func MakeStringListAttribute(value []string) StringListAttribute {
// NOTE: These strings are not necessarily unique or sorted.
- return StringListAttribute{Value: value}
-}
-
-// Arch-specific string_list typed Bazel attribute values. This should correspond
-// to the types of architectures supported for compilation in arch.go.
-type stringListArchValues struct {
- X86 []string
- X86_64 []string
- Arm []string
- Arm64 []string
-
- ConditionsDefault []string
-}
-
-type stringListTargetValue struct {
- // E.g. for android
- OsValue []string
-
- // E.g. for android_arm, android_arm64, ...
- ArchValues stringListArchValues
-}
-
-func (target *stringListTargetValue) Append(other stringListTargetValue) {
- target.OsValue = append(target.OsValue, other.OsValue...)
- target.ArchValues.X86 = append(target.ArchValues.X86, other.ArchValues.X86...)
- target.ArchValues.X86_64 = append(target.ArchValues.X86_64, other.ArchValues.X86_64...)
- target.ArchValues.Arm = append(target.ArchValues.Arm, other.ArchValues.Arm...)
- target.ArchValues.Arm64 = append(target.ArchValues.Arm64, other.ArchValues.Arm64...)
- target.ArchValues.ConditionsDefault = append(target.ArchValues.ConditionsDefault, other.ArchValues.ConditionsDefault...)
-}
-
-type stringListTargetValues struct {
- Android stringListTargetValue
- Darwin stringListTargetValue
- Fuchsia stringListTargetValue
- Linux stringListTargetValue
- LinuxBionic stringListTargetValue
- Windows stringListTargetValue
-
- ConditionsDefault stringListTargetValue
-}
-
-// Product Variable values for StringListAttribute
-type ProductVariableValues struct {
- ProductVariable string
-
- Values []string
-}
-
-// SelectKey returns the appropriate select key for the receiving ProductVariableValues.
-func (p ProductVariableValues) SelectKey() string {
- return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(p.ProductVariable))
-}
-
-// HasConfigurableValues returns true if the attribute contains
-// architecture-specific string_list values.
-func (attrs StringListAttribute) HasConfigurableValues() bool {
- for arch := range PlatformArchMap {
- if len(attrs.GetValueForArch(arch)) > 0 {
- return true
- }
- }
-
- for os := range PlatformOsMap {
- if len(attrs.GetOsValueForTarget(os)) > 0 {
- return true
- }
- // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (Not in AllArches)
- for _, arch := range AllArches {
- if len(attrs.GetOsArchValueForTarget(os, arch)) > 0 {
- return true
- }
-
- }
- }
-
- return len(attrs.ProductValues) > 0
-}
-
-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,
- CONDITIONS_DEFAULT: &attrs.ArchValues.ConditionsDefault,
+ return StringListAttribute{
+ Value: value,
+ ConfigurableValues: make(configurableStringLists),
}
}
-// GetValueForArch returns the string_list attribute value for an architecture.
-func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
- 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) {
- var v *[]string
- if v = attrs.archValuePtrs()[arch]; v == nil {
- panic(fmt.Errorf("Unknown arch: %s", arch))
- }
- *v = value
-}
-
-func (attrs *StringListAttribute) targetValuePtrs() map[string]*stringListTargetValue {
- return map[string]*stringListTargetValue{
- OS_ANDROID: &attrs.TargetValues.Android,
- OS_DARWIN: &attrs.TargetValues.Darwin,
- OS_FUCHSIA: &attrs.TargetValues.Fuchsia,
- OS_LINUX: &attrs.TargetValues.Linux,
- OS_LINUX_BIONIC: &attrs.TargetValues.LinuxBionic,
- OS_WINDOWS: &attrs.TargetValues.Windows,
- CONDITIONS_DEFAULT: &attrs.TargetValues.ConditionsDefault,
- }
-}
-
-func (attrs *StringListAttribute) getValueForTarget(os string) stringListTargetValue {
- var v *stringListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- return *v
-}
-
-func (attrs *StringListAttribute) GetOsValueForTarget(os string) []string {
- var v *stringListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- return v.OsValue
-}
-
-func (attrs *StringListAttribute) GetOsArchValueForTarget(os string, arch string) []string {
- var v *stringListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- switch arch {
- case ARCH_X86:
- return v.ArchValues.X86
- case ARCH_X86_64:
- return v.ArchValues.X86_64
- case ARCH_ARM:
- return v.ArchValues.Arm
- case ARCH_ARM64:
- return v.ArchValues.Arm64
- case CONDITIONS_DEFAULT:
- return v.ArchValues.ConditionsDefault
- default:
- panic(fmt.Errorf("Unknown arch: %s\n", arch))
- }
-}
-
-func (attrs *StringListAttribute) setValueForTarget(os string, value stringListTargetValue) {
- var v *stringListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- *v = value
-}
-
-func (attrs *StringListAttribute) SortedProductVariables() []ProductVariableValues {
- vals := attrs.ProductValues[:]
- sort.Slice(vals, func(i, j int) bool { return vals[i].ProductVariable < vals[j].ProductVariable })
- return vals
-}
-
-func (attrs *StringListAttribute) SetOsValueForTarget(os string, value []string) {
- var v *stringListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- v.OsValue = value
-}
-
-func (attrs *StringListAttribute) SetOsArchValueForTarget(os string, arch string, value []string) {
- var v *stringListTargetValue
- if v = attrs.targetValuePtrs()[os]; v == nil {
- panic(fmt.Errorf("Unknown os: %s", os))
- }
- switch arch {
- case ARCH_X86:
- v.ArchValues.X86 = value
- case ARCH_X86_64:
- v.ArchValues.X86_64 = value
- case ARCH_ARM:
- v.ArchValues.Arm = value
- case ARCH_ARM64:
- v.ArchValues.Arm64 = value
- case CONDITIONS_DEFAULT:
- v.ArchValues.ConditionsDefault = value
- default:
- panic(fmt.Errorf("Unknown arch: %s\n", arch))
- }
+// HasConfigurableValues returns true if the attribute contains axis-specific string_list values.
+func (sla StringListAttribute) HasConfigurableValues() bool {
+ return len(sla.ConfigurableValues) > 0
}
// Append appends all values, including os and arch specific ones, from another
// StringListAttribute to this StringListAttribute
-func (attrs *StringListAttribute) Append(other StringListAttribute) {
- for arch := range PlatformArchMap {
- this := attrs.GetValueForArch(arch)
- that := other.GetValueForArch(arch)
- this = append(this, that...)
- attrs.SetValueForArch(arch, this)
+func (sla *StringListAttribute) Append(other StringListAttribute) {
+ sla.Value = append(sla.Value, other.Value...)
+ if sla.ConfigurableValues == nil {
+ sla.ConfigurableValues = make(configurableStringLists)
+ }
+ sla.ConfigurableValues.Append(other.ConfigurableValues)
+}
+
+// SetSelectValue set a value for a bazel select for the given axis, config and value.
+func (sla *StringListAttribute) SetSelectValue(axis ConfigurationAxis, config string, list []string) {
+ axis.validateConfig(config)
+ switch axis.configurationType {
+ case noConfig:
+ sla.Value = list
+ case arch, os, osArch, productVariables:
+ if sla.ConfigurableValues == nil {
+ sla.ConfigurableValues = make(configurableStringLists)
+ }
+ sla.ConfigurableValues.setValueForAxis(axis, config, list)
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+ }
+}
+
+// SelectValue gets a value for a bazel select for the given axis and config.
+func (sla *StringListAttribute) SelectValue(axis ConfigurationAxis, config string) []string {
+ axis.validateConfig(config)
+ switch axis.configurationType {
+ case noConfig:
+ return sla.Value
+ case arch, os, osArch, productVariables:
+ return sla.ConfigurableValues[axis][config]
+ default:
+ panic(fmt.Errorf("Unrecognized ConfigurationAxis %s", axis))
+ }
+}
+
+// SortedConfigurationAxes returns all the used ConfigurationAxis in sorted order.
+func (sla *StringListAttribute) SortedConfigurationAxes() []ConfigurationAxis {
+ keys := make([]ConfigurationAxis, 0, len(sla.ConfigurableValues))
+ for k := range sla.ConfigurableValues {
+ keys = append(keys, k)
}
- for os := range PlatformOsMap {
- this := attrs.getValueForTarget(os)
- that := other.getValueForTarget(os)
- this.Append(that)
- attrs.setValueForTarget(os, this)
- }
-
- productValues := make(map[string][]string, 0)
- for _, pv := range attrs.ProductValues {
- productValues[pv.ProductVariable] = pv.Values
- }
- for _, pv := range other.ProductValues {
- productValues[pv.ProductVariable] = append(productValues[pv.ProductVariable], pv.Values...)
- }
- attrs.ProductValues = make([]ProductVariableValues, 0, len(productValues))
- for pv, vals := range productValues {
- attrs.ProductValues = append(attrs.ProductValues, ProductVariableValues{
- ProductVariable: pv,
- Values: vals,
- })
- }
-
- attrs.Value = append(attrs.Value, other.Value...)
+ sort.Slice(keys, func(i, j int) bool { return keys[i].less(keys[j]) })
+ return keys
}
// TryVariableSubstitution, replace string substitution formatting within each string in slice with
diff --git a/bazel/properties_test.go b/bazel/properties_test.go
index 229a4aa..9464245 100644
--- a/bazel/properties_test.go
+++ b/bazel/properties_test.go
@@ -122,7 +122,7 @@
}
}
}
-func TestUniqueBazelLabelList(t *testing.T) {
+func TestFirstUniqueBazelLabelList(t *testing.T) {
testCases := []struct {
originalLabelList LabelList
expectedUniqueLabelList LabelList
@@ -157,9 +157,139 @@
},
}
for _, tc := range testCases {
- actualUniqueLabelList := UniqueBazelLabelList(tc.originalLabelList)
+ actualUniqueLabelList := FirstUniqueBazelLabelList(tc.originalLabelList)
if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
}
}
}
+
+func TestUniqueSortedBazelLabelList(t *testing.T) {
+ testCases := []struct {
+ originalLabelList LabelList
+ expectedUniqueLabelList LabelList
+ }{
+ {
+ originalLabelList: LabelList{
+ Includes: []Label{
+ {Label: "c"},
+ {Label: "a"},
+ {Label: "a"},
+ {Label: "b"},
+ },
+ Excludes: []Label{
+ {Label: "y"},
+ {Label: "z"},
+ {Label: "x"},
+ {Label: "x"},
+ },
+ },
+ expectedUniqueLabelList: LabelList{
+ Includes: []Label{
+ {Label: "a"},
+ {Label: "b"},
+ {Label: "c"},
+ },
+ Excludes: []Label{
+ {Label: "x"},
+ {Label: "y"},
+ {Label: "z"},
+ },
+ },
+ },
+ }
+ for _, tc := range testCases {
+ actualUniqueLabelList := UniqueSortedBazelLabelList(tc.originalLabelList)
+ if !reflect.DeepEqual(tc.expectedUniqueLabelList, actualUniqueLabelList) {
+ t.Fatalf("Expected %v, got %v", tc.expectedUniqueLabelList, actualUniqueLabelList)
+ }
+ }
+}
+
+func makeLabels(labels ...string) []Label {
+ var ret []Label
+ for _, l := range labels {
+ ret = append(ret, Label{Label: l})
+ }
+ return ret
+}
+
+func makeLabelList(includes, excludes []string) LabelList {
+ return LabelList{
+ Includes: makeLabels(includes...),
+ Excludes: makeLabels(excludes...),
+ }
+}
+
+func TestResolveExcludes(t *testing.T) {
+ attr := LabelListAttribute{
+ Value: makeLabelList(
+ []string{
+ "all_include",
+ "arm_exclude",
+ "android_exclude",
+ },
+ []string{"all_exclude"},
+ ),
+ ConfigurableValues: configurableLabelLists{
+ ArchConfigurationAxis: labelListSelectValues{
+ "arm": makeLabelList([]string{}, []string{"arm_exclude"}),
+ "x86": makeLabelList([]string{"x86_include"}, []string{}),
+ },
+ OsConfigurationAxis: labelListSelectValues{
+ "android": makeLabelList([]string{}, []string{"android_exclude"}),
+ "linux": makeLabelList([]string{"linux_include"}, []string{}),
+ },
+ OsArchConfigurationAxis: labelListSelectValues{
+ "linux_x86": makeLabelList([]string{"linux_x86_include"}, []string{}),
+ },
+ ProductVariableConfigurationAxis("a"): labelListSelectValues{
+ "a": makeLabelList([]string{}, []string{"not_in_value"}),
+ },
+ },
+ }
+
+ attr.ResolveExcludes()
+
+ expectedBaseIncludes := []Label{Label{Label: "all_include"}}
+ if !reflect.DeepEqual(expectedBaseIncludes, attr.Value.Includes) {
+ t.Errorf("Expected Value includes %q, got %q", attr.Value.Includes, expectedBaseIncludes)
+ }
+ var nilLabels []Label
+ expectedConfiguredIncludes := map[ConfigurationAxis]map[string][]Label{
+ ArchConfigurationAxis: map[string][]Label{
+ "arm": nilLabels,
+ "x86": makeLabels("arm_exclude", "x86_include"),
+ "conditions_default": makeLabels("arm_exclude"),
+ },
+ OsConfigurationAxis: map[string][]Label{
+ "android": nilLabels,
+ "linux": makeLabels("android_exclude", "linux_include"),
+ "conditions_default": makeLabels("android_exclude"),
+ },
+ OsArchConfigurationAxis: map[string][]Label{
+ "linux_x86": makeLabels("linux_x86_include"),
+ "conditions_default": nilLabels,
+ },
+ }
+ for _, axis := range attr.SortedConfigurationAxes() {
+ if _, ok := expectedConfiguredIncludes[axis]; !ok {
+ t.Errorf("Found unexpected axis %s", axis)
+ continue
+ }
+ expectedForAxis := expectedConfiguredIncludes[axis]
+ gotForAxis := attr.ConfigurableValues[axis]
+ if len(expectedForAxis) != len(gotForAxis) {
+ t.Errorf("Expected %d configs for %s, got %d: %s", len(expectedForAxis), axis, len(gotForAxis), gotForAxis)
+ }
+ for config, value := range gotForAxis {
+ if expected, ok := expectedForAxis[config]; ok {
+ if !reflect.DeepEqual(expected, value.Includes) {
+ t.Errorf("For %s, expected: %#v, got %#v", axis, expected, value.Includes)
+ }
+ } else {
+ t.Errorf("Got unexpected config %q for %s", config, axis)
+ }
+ }
+ }
+}
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index b1c342c..6d0a9b2 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -1109,8 +1109,8 @@
"out",
],
srcs = [
- "in1",
"srcs-from-3",
+ "in1",
],
)`,
description: "genrule applies properties from genrule_defaults transitively",
@@ -1535,10 +1535,10 @@
expectedBazelTargets: []string{`filegroup(
name = "fg_foo",
srcs = [
- "//dir:e.txt",
- "//dir:f.txt",
"a.txt",
"b.txt",
+ "//dir:e.txt",
+ "//dir:f.txt",
],
)`,
},
@@ -1575,9 +1575,9 @@
expectedBazelTargets: []string{`filegroup(
name = "fg_foo",
srcs = [
+ "a.txt",
"//dir/subdir:e.txt",
"//dir/subdir:f.txt",
- "a.txt",
],
)`,
},
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index c8ae031..d84a7bb 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -985,3 +985,117 @@
)`},
})
}
+
+func TestCcLibraryExcludeLibs(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ filesystem: map[string]string{},
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_library {
+ name: "foo_static",
+ srcs: ["common.c"],
+ whole_static_libs: [
+ "arm_whole_static_lib_excludes",
+ "malloc_not_svelte_whole_static_lib_excludes"
+ ],
+ static_libs: [
+ "arm_static_lib_excludes",
+ "malloc_not_svelte_static_lib_excludes"
+ ],
+ shared_libs: [
+ "arm_shared_lib_excludes",
+ ],
+ arch: {
+ arm: {
+ exclude_shared_libs: [
+ "arm_shared_lib_excludes",
+ ],
+ exclude_static_libs: [
+ "arm_static_lib_excludes",
+ "arm_whole_static_lib_excludes",
+ ],
+ },
+ },
+ product_variables: {
+ malloc_not_svelte: {
+ shared_libs: ["malloc_not_svelte_shared_lib"],
+ whole_static_libs: ["malloc_not_svelte_whole_static_lib"],
+ exclude_static_libs: [
+ "malloc_not_svelte_static_lib_excludes",
+ "malloc_not_svelte_whole_static_lib_excludes",
+ ],
+ },
+ },
+}
+
+cc_library {
+ name: "arm_whole_static_lib_excludes",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "malloc_not_svelte_whole_static_lib",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "malloc_not_svelte_whole_static_lib_excludes",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "arm_static_lib_excludes",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "malloc_not_svelte_static_lib_excludes",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "arm_shared_lib_excludes",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "malloc_not_svelte_shared_lib",
+ bazel_module: { bp2build_available: false },
+}
+`,
+ expectedBazelTargets: []string{
+ `cc_library(
+ name = "foo_static",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ dynamic_deps = select({
+ "//build/bazel/platforms/arch:arm": [],
+ "//conditions:default": [":arm_shared_lib_excludes"],
+ }) + select({
+ "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
+ "//conditions:default": [],
+ }),
+ implementation_deps = select({
+ "//build/bazel/platforms/arch:arm": [],
+ "//conditions:default": [":arm_static_lib_excludes"],
+ }) + select({
+ "//build/bazel/product_variables:malloc_not_svelte": [],
+ "//conditions:default": [":malloc_not_svelte_static_lib_excludes"],
+ }),
+ srcs_c = ["common.c"],
+ whole_archive_deps = select({
+ "//build/bazel/platforms/arch:arm": [],
+ "//conditions:default": [":arm_whole_static_lib_excludes"],
+ }) + select({
+ "//build/bazel/product_variables:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib"],
+ "//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes"],
+ }),
+)`,
+ },
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index da38adb..40edec8 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -1286,8 +1286,6 @@
"//build/bazel/platforms/os_arch:android_arm64": ["android_arm64_src.c"],
"//build/bazel/platforms/os_arch:android_x86": ["android_x86_src.c"],
"//build/bazel/platforms/os_arch:android_x86_64": ["android_x86_64_src.c"],
- "//conditions:default": [],
- }) + select({
"//build/bazel/platforms/os_arch:linux_bionic_arm64": ["linux_bionic_arm64_src.c"],
"//build/bazel/platforms/os_arch:linux_bionic_x86_64": ["linux_bionic_x86_64_src.c"],
"//conditions:default": [],
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 7e1a298..60f6330 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -17,46 +17,20 @@
return value, []selects{}
}
- selectValues := make([]selects, 0)
- archSelects := map[string]reflect.Value{}
- for arch, selectKey := range bazel.PlatformArchMap {
- archSelects[selectKey] = reflect.ValueOf(list.GetValueForArch(arch))
- }
- if len(archSelects) > 0 {
- selectValues = append(selectValues, archSelects)
- }
-
- osSelects := map[string]reflect.Value{}
- osArchSelects := make([]selects, 0)
- for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
- selectKey := bazel.PlatformOsMap[os]
- osSelects[selectKey] = reflect.ValueOf(list.GetOsValueForTarget(os))
- archSelects := make(map[string]reflect.Value)
- // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (not in AllArches)
- for _, arch := range bazel.AllArches {
- target := os + "_" + arch
- selectKey := bazel.PlatformTargetMap[target]
- archSelects[selectKey] = reflect.ValueOf(list.GetOsArchValueForTarget(os, arch))
+ var ret []selects
+ for _, axis := range list.SortedConfigurationAxes() {
+ configToLists := list.ConfigurableValues[axis]
+ archSelects := map[string]reflect.Value{}
+ for config, labels := range configToLists {
+ selectKey := axis.SelectKey(config)
+ archSelects[selectKey] = reflect.ValueOf(labels)
}
- osArchSelects = append(osArchSelects, archSelects)
- }
- if len(osSelects) > 0 {
- selectValues = append(selectValues, osSelects)
- }
- if len(osArchSelects) > 0 {
- selectValues = append(selectValues, osArchSelects...)
- }
-
- for _, pv := range list.SortedProductVariables() {
- s := make(selects)
- if len(pv.Values) > 0 {
- s[pv.SelectKey()] = reflect.ValueOf(pv.Values)
- s[bazel.ConditionsDefaultSelectKey] = reflect.ValueOf([]string{})
- selectValues = append(selectValues, s)
+ if len(archSelects) > 0 {
+ ret = append(ret, archSelects)
}
}
- return value, selectValues
+ return value, ret
}
func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) {
@@ -65,105 +39,37 @@
return value, []selects{}
}
- // Keep track of which arches and oses have been used in case we need to raise a warning
- usedArches := make(map[string]bool)
- usedOses := make(map[string]bool)
-
- archSelects := map[string]reflect.Value{}
- for arch, selectKey := range bazel.PlatformArchMap {
- archSelects[selectKey] = reflect.ValueOf(label.GetValueForArch(arch))
- if archSelects[selectKey].IsValid() && !isZero(archSelects[selectKey]) {
- usedArches[arch] = true
+ ret := selects{}
+ for _, axis := range label.SortedConfigurationAxes() {
+ configToLabels := label.ConfigurableValues[axis]
+ for config, labels := range configToLabels {
+ selectKey := axis.SelectKey(config)
+ ret[selectKey] = reflect.ValueOf(labels)
}
}
- osSelects := map[string]reflect.Value{}
- for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
- selectKey := bazel.PlatformOsMap[os]
- osSelects[selectKey] = reflect.ValueOf(label.GetOsValueForTarget(os))
- if osSelects[selectKey].IsValid() && !isZero(osSelects[selectKey]) {
- usedOses[os] = true
- }
- }
-
- osArchSelects := make([]selects, 0)
- for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
- archSelects := make(map[string]reflect.Value)
- // TODO(b/187530594): Should we also check arch=CONDITIONS_DEFAULT? (not in AllArches)
- for _, arch := range bazel.AllArches {
- target := os + "_" + arch
- selectKey := bazel.PlatformTargetMap[target]
- archSelects[selectKey] = reflect.ValueOf(label.GetOsArchValueForTarget(os, arch))
- if archSelects[selectKey].IsValid() && !isZero(archSelects[selectKey]) {
- if _, ok := usedArches[arch]; ok {
- fmt.Printf("WARNING: Same arch used twice in LabelAttribute select: arch '%s'\n", arch)
- }
- if _, ok := usedOses[os]; ok {
- fmt.Printf("WARNING: Same os used twice in LabelAttribute select: os '%s'\n", os)
- }
- }
- }
- osArchSelects = append(osArchSelects, archSelects)
- }
-
- // Because we have to return a single Label, we can only use one select statement
- combinedSelects := map[string]reflect.Value{}
- for k, v := range archSelects {
- combinedSelects[k] = v
- }
- for k, v := range osSelects {
- combinedSelects[k] = v
- }
- for _, osArchSelect := range osArchSelects {
- for k, v := range osArchSelect {
- combinedSelects[k] = v
- }
- }
-
- return value, []selects{combinedSelects}
+ return value, []selects{ret}
}
func getLabelListValues(list bazel.LabelListAttribute) (reflect.Value, []selects) {
value := reflect.ValueOf(list.Value.Includes)
- if !list.HasConfigurableValues() {
- return value, []selects{}
- }
var ret []selects
-
- archSelects := map[string]reflect.Value{}
- for arch, selectKey := range bazel.PlatformArchMap {
- if use, value := labelListSelectValue(selectKey, list.GetValueForArch(arch)); use {
- archSelects[selectKey] = value
+ for _, axis := range list.SortedConfigurationAxes() {
+ configToLabels := list.ConfigurableValues[axis]
+ if !configToLabels.HasConfigurableValues() {
+ continue
}
- }
- if len(archSelects) > 0 {
- ret = append(ret, archSelects)
- }
-
- osSelects := map[string]reflect.Value{}
- osArchSelects := []selects{}
- for _, os := range android.SortedStringKeys(bazel.PlatformOsMap) {
- selectKey := bazel.PlatformOsMap[os]
- if use, value := labelListSelectValue(selectKey, list.GetOsValueForTarget(os)); use {
- osSelects[selectKey] = value
- }
- selects := make(map[string]reflect.Value)
- // TODO(b/187530594): Should we also check arch=CONDITIOSN_DEFAULT? (not in AllArches)
- for _, arch := range bazel.AllArches {
- target := os + "_" + arch
- selectKey := bazel.PlatformTargetMap[target]
- if use, value := labelListSelectValue(selectKey, list.GetOsArchValueForTarget(os, arch)); use {
- selects[selectKey] = value
+ archSelects := map[string]reflect.Value{}
+ for config, labels := range configToLabels {
+ selectKey := axis.SelectKey(config)
+ if use, value := labelListSelectValue(selectKey, labels); use {
+ archSelects[selectKey] = value
}
}
- if len(selects) > 0 {
- osArchSelects = append(osArchSelects, selects)
+ if len(archSelects) > 0 {
+ ret = append(ret, archSelects)
}
}
- if len(osSelects) > 0 {
- ret = append(ret, osSelects)
- }
- ret = append(ret, osArchSelects...)
return value, ret
}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index e575bc6..861f7d2 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -157,9 +157,11 @@
paths := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.props.Arch_paths))
- for arch, props := range m.GetArchProperties(ctx, &customProps{}) {
- if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
- paths.SetValueForArch(arch.Name, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths))
+ for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
+ for config, props := range configToProps {
+ if archProps, ok := props.(*customProps); ok && archProps.Arch_paths != nil {
+ paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, archProps.Arch_paths))
+ }
}
}
diff --git a/cc/Android.bp b/cc/Android.bp
index 1fc8d9f..46740dc 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -65,9 +65,10 @@
"test.go",
"toolchain_library.go",
- "ndk_prebuilt.go",
+ "ndk_abi.go",
"ndk_headers.go",
"ndk_library.go",
+ "ndk_prebuilt.go",
"ndk_sysroot.go",
"llndk_library.go",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index a156d54..752d43b 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -53,58 +53,29 @@
var allDeps []string
- for _, osProps := range module.GetTargetProperties(ctx, &BaseCompilerProperties{}) {
- // os base compiler props
- if baseCompilerProps, ok := osProps.Properties.(*BaseCompilerProperties); ok {
- allDeps = append(allDeps, baseCompilerProps.Generated_headers...)
- allDeps = append(allDeps, baseCompilerProps.Generated_sources...)
- }
- // os + arch base compiler props
- for _, archProps := range osProps.ArchProperties {
- if baseCompilerProps, ok := archProps.(*BaseCompilerProperties); ok {
+ for _, configToProps := range module.GetArchVariantProperties(ctx, &BaseCompilerProperties{}) {
+ for _, props := range configToProps {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
allDeps = append(allDeps, baseCompilerProps.Generated_headers...)
allDeps = append(allDeps, baseCompilerProps.Generated_sources...)
}
}
}
- for _, props := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
- // arch specific compiler props
- if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- allDeps = append(allDeps, baseCompilerProps.Generated_headers...)
- allDeps = append(allDeps, baseCompilerProps.Generated_sources...)
- }
- }
-
- for _, osProps := range module.GetTargetProperties(ctx, &BaseLinkerProperties{}) {
- // os specific linker props
- if baseLinkerProps, ok := osProps.Properties.(*BaseLinkerProperties); ok {
- allDeps = append(allDeps, baseLinkerProps.Header_libs...)
- allDeps = append(allDeps, baseLinkerProps.Export_header_lib_headers...)
- allDeps = append(allDeps, baseLinkerProps.Static_libs...)
- allDeps = append(allDeps, baseLinkerProps.Whole_static_libs...)
- }
- // os + arch base compiler props
- for _, archProps := range osProps.ArchProperties {
- if baseLinkerProps, ok := archProps.(*BaseLinkerProperties); ok {
+ for _, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
+ for _, props := range configToProps {
+ if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
allDeps = append(allDeps, baseLinkerProps.Header_libs...)
allDeps = append(allDeps, baseLinkerProps.Export_header_lib_headers...)
allDeps = append(allDeps, baseLinkerProps.Static_libs...)
+ allDeps = append(allDeps, baseLinkerProps.Exclude_static_libs...)
allDeps = append(allDeps, baseLinkerProps.Whole_static_libs...)
+ allDeps = append(allDeps, baseLinkerProps.Shared_libs...)
+ allDeps = append(allDeps, baseLinkerProps.Exclude_shared_libs...)
}
}
}
- for _, props := range module.GetArchProperties(ctx, &BaseLinkerProperties{}) {
- // arch specific linker props
- if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
- allDeps = append(allDeps, baseLinkerProps.Header_libs...)
- allDeps = append(allDeps, baseLinkerProps.Export_header_lib_headers...)
- allDeps = append(allDeps, baseLinkerProps.Static_libs...)
- allDeps = append(allDeps, baseLinkerProps.Whole_static_libs...)
- }
- }
-
// Deps in the static: { .. } and shared: { .. } props of a cc_library.
if lib, ok := module.compiler.(*libraryDecorator); ok {
appendDeps := func(deps []string, p StaticOrSharedProperties) []string {
@@ -124,37 +95,43 @@
// Deps in the target/arch nested static: { .. } and shared: { .. } props of a cc_library.
// target: { <target>: shared: { ... } }
- for _, targetProps := range module.GetTargetProperties(ctx, &SharedProperties{}) {
- if p, ok := targetProps.Properties.(*SharedProperties); ok {
- allDeps = appendDeps(allDeps, p.Shared)
- }
- for _, archProperties := range targetProps.ArchProperties {
- if p, ok := archProperties.(*SharedProperties); ok {
+ for _, configToProps := range module.GetArchVariantProperties(ctx, &SharedProperties{}) {
+ for _, props := range configToProps {
+ if p, ok := props.(*SharedProperties); ok {
allDeps = appendDeps(allDeps, p.Shared)
}
}
}
- // target: { <target>: static: { ... } }
- for _, targetProps := range module.GetTargetProperties(ctx, &StaticProperties{}) {
- if p, ok := targetProps.Properties.(*StaticProperties); ok {
- allDeps = appendDeps(allDeps, p.Static)
- }
- for _, archProperties := range targetProps.ArchProperties {
- if p, ok := archProperties.(*StaticProperties); ok {
+
+ for _, configToProps := range module.GetArchVariantProperties(ctx, &StaticProperties{}) {
+ for _, props := range configToProps {
+ if p, ok := props.(*StaticProperties); ok {
allDeps = appendDeps(allDeps, p.Static)
}
}
}
- // arch: { <arch>: shared: { ... } }
- for _, properties := range module.GetArchProperties(ctx, &SharedProperties{}) {
- if p, ok := properties.(*SharedProperties); ok {
- allDeps = appendDeps(allDeps, p.Shared)
- }
+ }
+
+ // product variables only support a limited set of fields, this is the full list of field names
+ // related to cc module dependency management that are supported.
+ productVariableDepFields := [4]string{
+ "Shared_libs",
+ "Static_libs",
+ "Exclude_static_libs",
+ "Whole_static_libs",
+ }
+
+ productVariableProps := android.ProductVariableProperties(ctx)
+ for _, name := range productVariableDepFields {
+ props, exists := productVariableProps[name]
+ if !exists {
+ continue
}
- // arch: { <arch>: static: { ... } }
- for _, properties := range module.GetArchProperties(ctx, &StaticProperties{}) {
- if p, ok := properties.(*StaticProperties); ok {
- allDeps = appendDeps(allDeps, p.Static)
+ for _, prop := range props {
+ if p, ok := prop.Property.([]string); !ok {
+ ctx.ModuleErrorf("Could not convert product variable %s property", name)
+ } else {
+ allDeps = append(allDeps, p...)
}
}
}
@@ -275,65 +252,33 @@
attrs := staticOrSharedAttributes{
copts: bazel.StringListAttribute{Value: props.Cflags},
- srcs: bazel.LabelListAttribute{Value: android.BazelLabelForModuleSrc(ctx, props.Srcs)},
- staticDeps: bazel.LabelListAttribute{Value: android.BazelLabelForModuleDeps(ctx, props.Static_libs)},
- dynamicDeps: bazel.LabelListAttribute{Value: android.BazelLabelForModuleDeps(ctx, props.Shared_libs)},
- wholeArchiveDeps: bazel.LabelListAttribute{Value: android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs)},
+ srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, props.Srcs)),
+ staticDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Static_libs)),
+ dynamicDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Shared_libs)),
+ wholeArchiveDeps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs)),
}
- setArchAttrs := func(arch string, props StaticOrSharedProperties) {
- attrs.copts.SetValueForArch(arch, props.Cflags)
- attrs.srcs.SetValueForArch(arch, android.BazelLabelForModuleSrc(ctx, props.Srcs))
- attrs.staticDeps.SetValueForArch(arch, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
- attrs.dynamicDeps.SetValueForArch(arch, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
- attrs.wholeArchiveDeps.SetValueForArch(arch, android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs))
- }
-
- setTargetAttrs := func(target string, props StaticOrSharedProperties) {
- attrs.copts.SetOsValueForTarget(target, props.Cflags)
- attrs.srcs.SetOsValueForTarget(target, android.BazelLabelForModuleSrc(ctx, props.Srcs))
- attrs.staticDeps.SetOsValueForTarget(target, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
- attrs.dynamicDeps.SetOsValueForTarget(target, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
- attrs.wholeArchiveDeps.SetOsValueForTarget(target, android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs))
- }
-
- setTargetArchAttrs := func(target, arch string, props StaticOrSharedProperties) {
- attrs.copts.SetOsArchValueForTarget(target, arch, props.Cflags)
- attrs.srcs.SetOsArchValueForTarget(target, arch, android.BazelLabelForModuleSrc(ctx, props.Srcs))
- attrs.staticDeps.SetOsArchValueForTarget(target, arch, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
- attrs.dynamicDeps.SetOsArchValueForTarget(target, arch, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
- attrs.wholeArchiveDeps.SetOsArchValueForTarget(target, arch, android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs))
+ setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
+ attrs.copts.SetSelectValue(axis, config, props.Cflags)
+ attrs.srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
+ attrs.staticDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
+ attrs.dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
+ attrs.wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Whole_static_libs))
}
if isStatic {
- for arch, properties := range module.GetArchProperties(ctx, &StaticProperties{}) {
- if staticOrSharedProps, ok := properties.(*StaticProperties); ok {
- setArchAttrs(arch.Name, staticOrSharedProps.Static)
- }
- }
- for target, p := range module.GetTargetProperties(ctx, &StaticProperties{}) {
- if staticOrSharedProps, ok := p.Properties.(*StaticProperties); ok {
- setTargetAttrs(target.Name, staticOrSharedProps.Static)
- }
- for arch, archProperties := range p.ArchProperties {
- if staticOrSharedProps, ok := archProperties.(*StaticProperties); ok {
- setTargetArchAttrs(target.Name, arch.Name, staticOrSharedProps.Static)
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &StaticProperties{}) {
+ for config, props := range configToProps {
+ if staticOrSharedProps, ok := props.(*StaticProperties); ok {
+ setAttrs(axis, config, staticOrSharedProps.Static)
}
}
}
} else {
- for arch, p := range module.GetArchProperties(ctx, &SharedProperties{}) {
- if staticOrSharedProps, ok := p.(*SharedProperties); ok {
- setArchAttrs(arch.Name, staticOrSharedProps.Shared)
- }
- }
- for target, p := range module.GetTargetProperties(ctx, &SharedProperties{}) {
- if staticOrSharedProps, ok := p.Properties.(*SharedProperties); ok {
- setTargetAttrs(target.Name, staticOrSharedProps.Shared)
- }
- for arch, archProperties := range p.ArchProperties {
- if staticOrSharedProps, ok := archProperties.(*SharedProperties); ok {
- setTargetArchAttrs(target.Name, arch.Name, staticOrSharedProps.Shared)
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &SharedProperties{}) {
+ for config, props := range configToProps {
+ if staticOrSharedProps, ok := props.(*SharedProperties); ok {
+ setAttrs(axis, config, staticOrSharedProps.Shared)
}
}
}
@@ -363,45 +308,23 @@
}
if len(prebuiltLinker.properties.Srcs) == 1 {
- srcLabelAttribute.Value = android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinker.properties.Srcs[0])
- for arch, props := range module.GetArchProperties(ctx, &prebuiltLinkerProperties{}) {
+ srcLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinker.properties.Srcs[0]))
+ }
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltLinkerProperties{}) {
+ for config, props := range configToProps {
if prebuiltLinkerProperties, ok := props.(*prebuiltLinkerProperties); ok {
if len(prebuiltLinkerProperties.Srcs) > 1 {
- ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most once source file for arch %s\n", arch.Name)
+ ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most once source file for %s %s\n", axis, config)
+ continue
+ } else if len(prebuiltLinkerProperties.Srcs) == 0 {
+ continue
}
- if len(prebuiltLinkerProperties.Srcs) == 1 {
- srcLabelAttribute.SetValueForArch(arch.Name, android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinkerProperties.Srcs[0]))
- }
+ src := android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinkerProperties.Srcs[0])
+ srcLabelAttribute.SetSelectValue(axis, config, src)
}
}
}
- for os, targetProperties := range module.GetTargetProperties(ctx, &prebuiltLinkerProperties{}) {
- if prebuiltLinkerProperties, ok := targetProperties.Properties.(*prebuiltLinkerProperties); ok {
- if len(prebuiltLinkerProperties.Srcs) > 1 {
- ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most once source file for os %s\n", os.Name)
-
- }
-
- if len(prebuiltLinkerProperties.Srcs) == 1 {
- srcLabelAttribute.SetOsValueForTarget(os.Name, android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinkerProperties.Srcs[0]))
- }
- }
- for arch, archProperties := range targetProperties.ArchProperties {
- if prebuiltLinkerProperties, ok := archProperties.(*prebuiltLinkerProperties); ok {
- if len(prebuiltLinkerProperties.Srcs) > 1 {
- ctx.ModuleErrorf("Bp2BuildParsePrebuiltLibraryProps: Expected at most once source file for os_arch %s_%s\n", os.Name, arch.Name)
-
- }
-
- if len(prebuiltLinkerProperties.Srcs) == 1 {
- srcLabelAttribute.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleSrcSingle(ctx, prebuiltLinkerProperties.Srcs[0]))
- }
- }
-
- }
- }
-
return prebuiltAttributes{
Src: srcLabelAttribute,
}
@@ -473,44 +396,26 @@
return copts
}
- // baseSrcs contain the list of src files that are used for every configuration.
- var baseSrcs []string
- // baseExcludeSrcs contain the list of src files that are excluded for every configuration.
- var baseExcludeSrcs []string
- // baseSrcsLabelList is a clone of the base srcs LabelList, used for computing the
- // arch or os specific srcs later.
- var baseSrcsLabelList bazel.LabelList
-
- // Parse srcs from an arch or OS's props value, taking the base srcs and
- // exclude srcs into account.
+ // Parse srcs from an arch or OS's props value.
parseSrcs := func(baseCompilerProps *BaseCompilerProperties) bazel.LabelList {
- // Combine the base srcs and arch-specific srcs
- allSrcs := append(baseSrcs, baseCompilerProps.Srcs...)
// Add srcs-like dependencies such as generated files.
// First create a LabelList containing these dependencies, then merge the values with srcs.
generatedHdrsAndSrcs := baseCompilerProps.Generated_headers
generatedHdrsAndSrcs = append(generatedHdrsAndSrcs, baseCompilerProps.Generated_sources...)
-
generatedHdrsAndSrcsLabelList := android.BazelLabelForModuleDeps(ctx, generatedHdrsAndSrcs)
- // Combine the base exclude_srcs and configuration-specific exclude_srcs
- allExcludeSrcs := append(baseExcludeSrcs, baseCompilerProps.Exclude_srcs...)
- allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, allSrcs, allExcludeSrcs)
+ allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, baseCompilerProps.Srcs, baseCompilerProps.Exclude_srcs)
return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedHdrsAndSrcsLabelList)
}
for _, props := range module.compiler.compilerProps() {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- srcs.Value = parseSrcs(baseCompilerProps)
+ srcs.SetValue(parseSrcs(baseCompilerProps))
copts.Value = parseCopts(baseCompilerProps)
asFlags.Value = parseCommandLineFlags(baseCompilerProps.Asflags)
conlyFlags.Value = parseCommandLineFlags(baseCompilerProps.Conlyflags)
cppFlags.Value = parseCommandLineFlags(baseCompilerProps.Cppflags)
- // Used for arch-specific srcs later.
- baseSrcs = baseCompilerProps.Srcs
- baseSrcsLabelList = parseSrcs(baseCompilerProps)
- baseExcludeSrcs = baseCompilerProps.Exclude_srcs
break
}
}
@@ -524,67 +429,28 @@
copts.Value = append(copts.Value, includeFlags(".")...)
}
- for arch, props := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
- if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- // If there's arch specific srcs or exclude_srcs, generate a select entry for it.
- // TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
- if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
- srcsList := parseSrcs(baseCompilerProps)
- srcs.SetValueForArch(arch.Name, srcsList)
- // The base srcs value should not contain any arch-specific excludes.
- srcs.Value = bazel.SubtractBazelLabelList(srcs.Value, bazel.LabelList{Includes: srcsList.Excludes})
- }
+ archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
- copts.SetValueForArch(arch.Name, parseCopts(baseCompilerProps))
- asFlags.SetValueForArch(arch.Name, parseCommandLineFlags(baseCompilerProps.Asflags))
- conlyFlags.SetValueForArch(arch.Name, parseCommandLineFlags(baseCompilerProps.Conlyflags))
- cppFlags.SetValueForArch(arch.Name, parseCommandLineFlags(baseCompilerProps.Cppflags))
- }
- }
-
- // After going through all archs, delete the duplicate files in the arch
- // values that are already in the base srcs.Value.
- for arch, props := range module.GetArchProperties(ctx, &BaseCompilerProperties{}) {
- if _, ok := props.(*BaseCompilerProperties); ok {
- srcs.SetValueForArch(arch.Name, bazel.SubtractBazelLabelList(srcs.GetValueForArch(arch.Name), srcs.Value))
- }
- }
-
- // Now that the srcs.Value list is finalized, compare it with the original
- // list, and put the difference into the default condition for the arch
- // select.
- defaultsSrcs := bazel.SubtractBazelLabelList(baseSrcsLabelList, srcs.Value)
- // TODO(b/186153868): handle the case with multiple variant types, e.g. when arch and os are both used.
- srcs.SetValueForArch(bazel.CONDITIONS_DEFAULT, defaultsSrcs)
-
- // Handle target specific properties.
- for os, osProps := range module.GetTargetProperties(ctx, &BaseCompilerProperties{}) {
- if baseCompilerProps, ok := osProps.Properties.(*BaseCompilerProperties); ok {
- srcsList := parseSrcs(baseCompilerProps)
- // TODO(b/186153868): add support for os-specific srcs and exclude_srcs
- if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
- srcs.SetOsValueForTarget(os.Name, bazel.SubtractBazelLabelList(srcsList, baseSrcsLabelList))
- }
- copts.SetOsValueForTarget(os.Name, parseCopts(baseCompilerProps))
- asFlags.SetOsValueForTarget(os.Name, parseCommandLineFlags(baseCompilerProps.Asflags))
- conlyFlags.SetOsValueForTarget(os.Name, parseCommandLineFlags(baseCompilerProps.Conlyflags))
- cppFlags.SetOsValueForTarget(os.Name, parseCommandLineFlags(baseCompilerProps.Cppflags))
- }
- for arch, archProps := range osProps.ArchProperties {
- if baseCompilerProps, ok := archProps.(*BaseCompilerProperties); ok {
- srcsList := parseSrcs(baseCompilerProps)
- // TODO(b/186153868): add support for os-specific srcs and exclude_srcs
+ for axis, configToProps := range archVariantCompilerProps {
+ for config, props := range configToProps {
+ if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
+ // If there's arch specific srcs or exclude_srcs, generate a select entry for it.
+ // TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
- srcs.SetOsArchValueForTarget(os.Name, arch.Name, bazel.SubtractBazelLabelList(srcsList, baseSrcsLabelList))
+ srcsList := parseSrcs(baseCompilerProps)
+ srcs.SetSelectValue(axis, config, srcsList)
}
- copts.SetOsArchValueForTarget(os.Name, arch.Name, parseCopts(baseCompilerProps))
- asFlags.SetOsArchValueForTarget(os.Name, arch.Name, parseCommandLineFlags(baseCompilerProps.Asflags))
- conlyFlags.SetOsArchValueForTarget(os.Name, arch.Name, parseCommandLineFlags(baseCompilerProps.Conlyflags))
- cppFlags.SetOsArchValueForTarget(os.Name, arch.Name, parseCommandLineFlags(baseCompilerProps.Cppflags))
+
+ copts.SetSelectValue(axis, config, parseCopts(baseCompilerProps))
+ asFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Asflags))
+ conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Conlyflags))
+ cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Cppflags))
}
}
}
+ srcs.ResolveExcludes()
+
productVarPropNameToAttribute := map[string]*bazel.StringListAttribute{
"Cflags": &copts,
"Asflags": &asFlags,
@@ -599,10 +465,7 @@
ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName))
}
newFlags, _ := bazel.TryVariableSubstitutions(flags, prop.ProductConfigVariable)
- attr.ProductValues = append(attr.ProductValues, bazel.ProductVariableValues{
- ProductVariable: prop.ProductConfigVariable,
- Values: newFlags,
- })
+ attr.SetSelectValue(bazel.ProductVariableConfigurationAxis(prop.FullConfig), prop.FullConfig, newFlags)
}
}
}
@@ -642,102 +505,121 @@
// bp2BuildParseLinkerProps parses the linker properties of a module, including
// configurable attribute values.
func bp2BuildParseLinkerProps(ctx android.TopDownMutatorContext, module *Module) linkerAttributes {
- var deps bazel.LabelListAttribute
+ var headerDeps bazel.LabelListAttribute
+ var staticDeps bazel.LabelListAttribute
var exportedDeps bazel.LabelListAttribute
var dynamicDeps bazel.LabelListAttribute
var wholeArchiveDeps bazel.LabelListAttribute
var linkopts bazel.StringListAttribute
var versionScript bazel.LabelAttribute
- getLibs := func(baseLinkerProps *BaseLinkerProperties) []string {
- libs := baseLinkerProps.Header_libs
- libs = append(libs, baseLinkerProps.Static_libs...)
- libs = android.SortedUniqueStrings(libs)
- return libs
- }
-
for _, linkerProps := range module.linker.linkerProps() {
if baseLinkerProps, ok := linkerProps.(*BaseLinkerProperties); ok {
- libs := getLibs(baseLinkerProps)
- exportedLibs := baseLinkerProps.Export_header_lib_headers
- wholeArchiveLibs := baseLinkerProps.Whole_static_libs
- deps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, libs))
+ // Excludes to parallel Soong:
+ // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
+ staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
+ staticDeps.Value = android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs)
+ wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
+ wholeArchiveDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
+ sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
+ dynamicDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
+
+ headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
+ headerDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, headerLibs))
+ // TODO(b/188796939): also handle export_static_lib_headers, export_shared_lib_headers,
+ // export_generated_headers
+ exportedLibs := android.FirstUniqueStrings(baseLinkerProps.Export_header_lib_headers)
exportedDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, exportedLibs))
+
linkopts.Value = getBp2BuildLinkerFlags(baseLinkerProps)
- wholeArchiveDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
-
if baseLinkerProps.Version_script != nil {
- versionScript.Value = android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script)
+ versionScript.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
}
- sharedLibs := baseLinkerProps.Shared_libs
- dynamicDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, sharedLibs))
-
break
}
}
- for arch, props := range module.GetArchProperties(ctx, &BaseLinkerProperties{}) {
- if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
- libs := getLibs(baseLinkerProps)
- exportedLibs := baseLinkerProps.Export_header_lib_headers
- wholeArchiveLibs := baseLinkerProps.Whole_static_libs
- deps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, libs))
- exportedDeps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, exportedLibs))
- linkopts.SetValueForArch(arch.Name, getBp2BuildLinkerFlags(baseLinkerProps))
- wholeArchiveDeps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
+ for config, props := range configToProps {
+ if baseLinkerProps, ok := props.(*BaseLinkerProperties); ok {
+ staticLibs := android.FirstUniqueStrings(baseLinkerProps.Static_libs)
+ staticDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs))
+ wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
+ wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
+ sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
+ dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
- if baseLinkerProps.Version_script != nil {
- versionScript.SetValueForArch(arch.Name,
- android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
- }
+ headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
+ headerDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, headerLibs))
+ exportedLibs := android.FirstUniqueStrings(baseLinkerProps.Export_header_lib_headers)
+ exportedDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, exportedLibs))
- sharedLibs := baseLinkerProps.Shared_libs
- dynamicDeps.SetValueForArch(arch.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
- }
- }
-
- for os, targetProperties := range module.GetTargetProperties(ctx, &BaseLinkerProperties{}) {
- if baseLinkerProps, ok := targetProperties.Properties.(*BaseLinkerProperties); ok {
- libs := getLibs(baseLinkerProps)
- exportedLibs := baseLinkerProps.Export_header_lib_headers
- wholeArchiveLibs := baseLinkerProps.Whole_static_libs
- wholeArchiveDeps.SetOsValueForTarget(os.Name, android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
- deps.SetOsValueForTarget(os.Name, android.BazelLabelForModuleDeps(ctx, libs))
- exportedDeps.SetOsValueForTarget(os.Name, android.BazelLabelForModuleDeps(ctx, exportedLibs))
-
- linkopts.SetOsValueForTarget(os.Name, getBp2BuildLinkerFlags(baseLinkerProps))
-
- if baseLinkerProps.Version_script != nil {
- versionScript.SetOsValueForTarget(os.Name, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
- }
-
- sharedLibs := baseLinkerProps.Shared_libs
- dynamicDeps.SetOsValueForTarget(os.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
- }
- for arch, archProperties := range targetProperties.ArchProperties {
- if baseLinkerProps, ok := archProperties.(*BaseLinkerProperties); ok {
- libs := getLibs(baseLinkerProps)
- exportedLibs := baseLinkerProps.Export_header_lib_headers
- wholeArchiveLibs := baseLinkerProps.Whole_static_libs
- wholeArchiveDeps.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
- deps.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleDeps(ctx, libs))
- exportedDeps.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleDeps(ctx, exportedLibs))
-
- linkopts.SetOsArchValueForTarget(os.Name, arch.Name, getBp2BuildLinkerFlags(baseLinkerProps))
-
+ linkopts.SetSelectValue(axis, config, getBp2BuildLinkerFlags(baseLinkerProps))
if baseLinkerProps.Version_script != nil {
- versionScript.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
+ versionScript.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
}
-
- sharedLibs := baseLinkerProps.Shared_libs
- dynamicDeps.SetOsArchValueForTarget(os.Name, arch.Name, android.BazelLabelForModuleDeps(ctx, sharedLibs))
}
}
}
+ type productVarDep struct {
+ // the name of the corresponding excludes field, if one exists
+ excludesField string
+ // reference to the bazel attribute that should be set for the given product variable config
+ attribute *bazel.LabelListAttribute
+ }
+
+ productVarToDepFields := map[string]productVarDep{
+ // product variables do not support exclude_shared_libs
+ "Shared_libs": productVarDep{attribute: &dynamicDeps},
+ "Static_libs": productVarDep{"Exclude_static_libs", &staticDeps},
+ "Whole_static_libs": productVarDep{"Exclude_static_libs", &wholeArchiveDeps},
+ }
+
+ productVariableProps := android.ProductVariableProperties(ctx)
+ for name, dep := range productVarToDepFields {
+ props, exists := productVariableProps[name]
+ excludeProps, excludesExists := productVariableProps[dep.excludesField]
+ // if neither an include or excludes property exists, then skip it
+ if !exists && !excludesExists {
+ continue
+ }
+ // collect all the configurations that an include or exclude property exists for.
+ // we want to iterate all configurations rather than either the include or exclude because for a
+ // particular configuration we may have only and include or only an exclude to handle
+ configs := make(map[string]bool, len(props)+len(excludeProps))
+ for config := range props {
+ configs[config] = true
+ }
+ for config := range excludeProps {
+ configs[config] = true
+ }
+
+ for config := range configs {
+ prop, includesExists := props[config]
+ excludesProp, excludesExists := excludeProps[config]
+ var includes, excludes []string
+ var ok bool
+ // if there was no includes/excludes property, casting fails and that's expected
+ if includes, ok = prop.Property.([]string); includesExists && !ok {
+ ctx.ModuleErrorf("Could not convert product variable %s property", name)
+ }
+ if excludes, ok = excludesProp.Property.([]string); excludesExists && !ok {
+ ctx.ModuleErrorf("Could not convert product variable %s property", dep.excludesField)
+ }
+ dep.attribute.SetSelectValue(bazel.ProductVariableConfigurationAxis(config), config, android.BazelLabelForModuleDepsExcludes(ctx, android.FirstUniqueStrings(includes), excludes))
+ }
+ }
+
+ staticDeps.ResolveExcludes()
+ dynamicDeps.ResolveExcludes()
+ wholeArchiveDeps.ResolveExcludes()
+
+ headerDeps.Append(staticDeps)
+
return linkerAttributes{
- deps: deps,
+ deps: headerDeps,
exportedDeps: exportedDeps,
dynamicDeps: dynamicDeps,
wholeArchiveDeps: wholeArchiveDeps,
@@ -800,27 +682,12 @@
return variantIncludeDirs
}
- for arch, props := range module.GetArchProperties(ctx, &FlagExporterProperties{}) {
- if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
- archIncludeDirs := getVariantIncludeDirs(includeDirs, flagExporterProperties)
- if len(archIncludeDirs) > 0 {
- includeDirsAttribute.SetValueForArch(arch.Name, archIncludeDirs)
- }
- }
- }
-
- for os, targetProperties := range module.GetTargetProperties(ctx, &FlagExporterProperties{}) {
- if flagExporterProperties, ok := targetProperties.Properties.(*FlagExporterProperties); ok {
- targetIncludeDirs := getVariantIncludeDirs(includeDirs, flagExporterProperties)
- if len(targetIncludeDirs) > 0 {
- includeDirsAttribute.SetOsValueForTarget(os.Name, targetIncludeDirs)
- }
- }
- for arch, archProperties := range targetProperties.ArchProperties {
- if flagExporterProperties, ok := archProperties.(*FlagExporterProperties); ok {
- targetIncludeDirs := getVariantIncludeDirs(includeDirs, flagExporterProperties)
- if len(targetIncludeDirs) > 0 {
- includeDirsAttribute.SetOsArchValueForTarget(os.Name, arch.Name, targetIncludeDirs)
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &FlagExporterProperties{}) {
+ for config, props := range configToProps {
+ if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
+ archVariantIncludeDirs := getVariantIncludeDirs(includeDirs, flagExporterProperties)
+ if len(archVariantIncludeDirs) > 0 {
+ includeDirsAttribute.SetSelectValue(axis, config, archVariantIncludeDirs)
}
}
}
diff --git a/cc/cc.go b/cc/cc.go
index 91c4417..7c4ba44 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1267,8 +1267,8 @@
}
func (c *Module) IsSnapshotPrebuilt() bool {
- if p, ok := c.linker.(snapshotInterface); ok {
- return p.isSnapshotPrebuilt()
+ if p, ok := c.linker.(SnapshotInterface); ok {
+ return p.IsSnapshotPrebuilt()
}
return false
}
@@ -1980,15 +1980,19 @@
}
}
-func (c *Module) addSharedLibDependenciesWithVersions(ctx android.BottomUpMutatorContext,
- variations []blueprint.Variation, depTag libraryDependencyTag, name, version string, far bool) {
+func AddSharedLibDependenciesWithVersions(ctx android.BottomUpMutatorContext, mod LinkableInterface,
+ variations []blueprint.Variation, depTag blueprint.DependencyTag, name, version string, far bool) {
variations = append([]blueprint.Variation(nil), variations...)
- if version != "" && CanBeOrLinkAgainstVersionVariants(c) {
+ if version != "" && CanBeOrLinkAgainstVersionVariants(mod) {
// Version is explicitly specified. i.e. libFoo#30
variations = append(variations, blueprint.Variation{Mutator: "version", Variation: version})
- depTag.explicitlyVersioned = true
+ if tag, ok := depTag.(libraryDependencyTag); ok {
+ tag.explicitlyVersioned = true
+ } else {
+ panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
+ }
}
if far {
@@ -1998,6 +2002,74 @@
}
}
+func GetSnapshot(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.BottomUpMutatorContext) SnapshotInfo {
+ // Only modules with BOARD_VNDK_VERSION uses snapshot. Others use the zero value of
+ // SnapshotInfo, which provides no mappings.
+ if *snapshotInfo == nil {
+ // Only retrieve the snapshot on demand in order to avoid circular dependencies
+ // between the modules in the snapshot and the snapshot itself.
+ var snapshotModule []blueprint.Module
+ if c.InVendor() && c.VndkVersion() == actx.DeviceConfig().VndkVersion() {
+ snapshotModule = actx.AddVariationDependencies(nil, nil, "vendor_snapshot")
+ } else if recoverySnapshotVersion := actx.DeviceConfig().RecoverySnapshotVersion(); recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" && c.InRecovery() {
+ snapshotModule = actx.AddVariationDependencies(nil, nil, "recovery_snapshot")
+ }
+ if len(snapshotModule) > 0 {
+ snapshot := actx.OtherModuleProvider(snapshotModule[0], SnapshotInfoProvider).(SnapshotInfo)
+ *snapshotInfo = &snapshot
+ // republish the snapshot for use in later mutators on this module
+ actx.SetProvider(SnapshotInfoProvider, snapshot)
+ } else {
+ *snapshotInfo = &SnapshotInfo{}
+ }
+ }
+
+ return **snapshotInfo
+}
+
+func RewriteSnapshotLib(lib string, snapshotMap map[string]string) string {
+ if snapshot, ok := snapshotMap[lib]; ok {
+ return snapshot
+ }
+
+ return lib
+}
+
+// RewriteLibs takes a list of names of shared libraries and scans it for three types
+// of names:
+//
+// 1. Name of an NDK library that refers to a prebuilt module.
+// For each of these, it adds the name of the prebuilt module (which will be in
+// prebuilts/ndk) to the list of nonvariant libs.
+// 2. Name of an NDK library that refers to an ndk_library module.
+// For each of these, it adds the name of the ndk_library module to the list of
+// variant libs.
+// 3. Anything else (so anything that isn't an NDK library).
+// It adds these to the nonvariantLibs list.
+//
+// The caller can then know to add the variantLibs dependencies differently from the
+// nonvariantLibs
+func RewriteLibs(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.BottomUpMutatorContext, config android.Config, list []string) (nonvariantLibs []string, variantLibs []string) {
+ variantLibs = []string{}
+
+ nonvariantLibs = []string{}
+ for _, entry := range list {
+ // strip #version suffix out
+ name, _ := StubsLibNameAndVersion(entry)
+ if c.InRecovery() {
+ nonvariantLibs = append(nonvariantLibs, RewriteSnapshotLib(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
+ } else if c.UseSdk() && inList(name, *getNDKKnownLibs(config)) {
+ variantLibs = append(variantLibs, name+ndkLibrarySuffix)
+ } else if c.UseVndk() {
+ nonvariantLibs = append(nonvariantLibs, RewriteSnapshotLib(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
+ } else {
+ // put name#version back
+ nonvariantLibs = append(nonvariantLibs, entry)
+ }
+ }
+ return nonvariantLibs, variantLibs
+}
+
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
if !c.Enabled() {
return
@@ -2016,83 +2088,16 @@
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
var snapshotInfo *SnapshotInfo
- getSnapshot := func() SnapshotInfo {
- // Only modules with BOARD_VNDK_VERSION uses snapshot. Others use the zero value of
- // SnapshotInfo, which provides no mappings.
- if snapshotInfo == nil {
- // Only retrieve the snapshot on demand in order to avoid circular dependencies
- // between the modules in the snapshot and the snapshot itself.
- var snapshotModule []blueprint.Module
- if c.InVendor() && c.VndkVersion() == actx.DeviceConfig().VndkVersion() {
- snapshotModule = ctx.AddVariationDependencies(nil, nil, "vendor_snapshot")
- } else if recoverySnapshotVersion := actx.DeviceConfig().RecoverySnapshotVersion(); recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" && c.InRecovery() {
- snapshotModule = ctx.AddVariationDependencies(nil, nil, "recovery_snapshot")
- }
- if len(snapshotModule) > 0 {
- snapshot := ctx.OtherModuleProvider(snapshotModule[0], SnapshotInfoProvider).(SnapshotInfo)
- snapshotInfo = &snapshot
- // republish the snapshot for use in later mutators on this module
- ctx.SetProvider(SnapshotInfoProvider, snapshot)
- } else {
- snapshotInfo = &SnapshotInfo{}
- }
- }
-
- return *snapshotInfo
- }
-
- rewriteSnapshotLib := func(lib string, snapshotMap map[string]string) string {
- if snapshot, ok := snapshotMap[lib]; ok {
- return snapshot
- }
-
- return lib
- }
variantNdkLibs := []string{}
variantLateNdkLibs := []string{}
if ctx.Os() == android.Android {
- // rewriteLibs takes a list of names of shared libraries and scans it for three types
- // of names:
- //
- // 1. Name of an NDK library that refers to a prebuilt module.
- // For each of these, it adds the name of the prebuilt module (which will be in
- // prebuilts/ndk) to the list of nonvariant libs.
- // 2. Name of an NDK library that refers to an ndk_library module.
- // For each of these, it adds the name of the ndk_library module to the list of
- // variant libs.
- // 3. Anything else (so anything that isn't an NDK library).
- // It adds these to the nonvariantLibs list.
- //
- // The caller can then know to add the variantLibs dependencies differently from the
- // nonvariantLibs
-
- rewriteLibs := func(list []string) (nonvariantLibs []string, variantLibs []string) {
- variantLibs = []string{}
- nonvariantLibs = []string{}
- for _, entry := range list {
- // strip #version suffix out
- name, _ := StubsLibNameAndVersion(entry)
- if c.InRecovery() {
- nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
- } else if ctx.useSdk() && inList(name, *getNDKKnownLibs(ctx.Config())) {
- variantLibs = append(variantLibs, name+ndkLibrarySuffix)
- } else if ctx.useVndk() {
- nonvariantLibs = append(nonvariantLibs, rewriteSnapshotLib(entry, getSnapshot().SharedLibs))
- } else {
- // put name#version back
- nonvariantLibs = append(nonvariantLibs, entry)
- }
- }
- return nonvariantLibs, variantLibs
- }
-
- deps.SharedLibs, variantNdkLibs = rewriteLibs(deps.SharedLibs)
- deps.LateSharedLibs, variantLateNdkLibs = rewriteLibs(deps.LateSharedLibs)
- deps.ReexportSharedLibHeaders, _ = rewriteLibs(deps.ReexportSharedLibHeaders)
+ deps.SharedLibs, variantNdkLibs = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.SharedLibs)
+ deps.LateSharedLibs, variantLateNdkLibs = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.LateSharedLibs)
+ deps.ReexportSharedLibHeaders, _ = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.ReexportSharedLibHeaders)
for idx, lib := range deps.RuntimeLibs {
- deps.RuntimeLibs[idx] = rewriteSnapshotLib(lib, getSnapshot().SharedLibs)
+ deps.RuntimeLibs[idx] = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).SharedLibs)
}
}
@@ -2102,7 +2107,7 @@
depTag.reexportFlags = true
}
- lib = rewriteSnapshotLib(lib, getSnapshot().HeaderLibs)
+ lib = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
if c.IsStubs() {
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
@@ -2112,6 +2117,15 @@
}
}
+ if c.isNDKStubLibrary() {
+ // NDK stubs depend on their implementation because the ABI dumps are
+ // generated from the implementation library.
+ actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
+ c.ImageVariation(),
+ blueprint.Variation{Mutator: "link", Variation: "shared"},
+ ), stubImplementation, c.BaseModuleName())
+ }
+
// sysprop_library has to support both C++ and Java. So sysprop_library internally creates one
// C++ implementation library and one Java implementation library. When a module links against
// sysprop_library, the C++ implementation library has to be linked. syspropImplLibraries is a
@@ -2125,7 +2139,7 @@
lib = impl
}
- lib = rewriteSnapshotLib(lib, getSnapshot().StaticLibs)
+ lib = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -2145,7 +2159,7 @@
lib = impl
}
- lib = rewriteSnapshotLib(lib, getSnapshot().StaticLibs)
+ lib = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
@@ -2159,14 +2173,14 @@
depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, depTag, rewriteSnapshotLib(staticUnwinder(actx), getSnapshot().StaticLibs))
+ }, depTag, RewriteSnapshotLib(staticUnwinder(actx), GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
}
for _, lib := range deps.LateStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
actx.AddVariationDependencies([]blueprint.Variation{
{Mutator: "link", Variation: "static"},
- }, depTag, rewriteSnapshotLib(lib, getSnapshot().StaticLibs))
+ }, depTag, RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
}
// shared lib names without the #version suffix
@@ -2191,7 +2205,7 @@
variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
}
- c.addSharedLibDependenciesWithVersions(ctx, variations, depTag, name, version, false)
+ AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false)
}
for _, lib := range deps.LateSharedLibs {
@@ -2205,7 +2219,7 @@
variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"},
}
- c.addSharedLibDependenciesWithVersions(ctx, variations, depTag, lib, "", false)
+ AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, lib, "", false)
}
actx.AddVariationDependencies([]blueprint.Variation{
@@ -2230,11 +2244,11 @@
actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
if deps.CrtBegin != "" {
actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
- rewriteSnapshotLib(deps.CrtBegin, getSnapshot().Objects))
+ RewriteSnapshotLib(deps.CrtBegin, GetSnapshot(c, &snapshotInfo, actx).Objects))
}
if deps.CrtEnd != "" {
actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
- rewriteSnapshotLib(deps.CrtEnd, getSnapshot().Objects))
+ RewriteSnapshotLib(deps.CrtEnd, GetSnapshot(c, &snapshotInfo, actx).Objects))
}
if deps.LinkerFlagsFile != "" {
actx.AddDependency(c, linkerFlagsDepTag, deps.LinkerFlagsFile)
@@ -2837,8 +2851,8 @@
// they merely serve as Make dependencies and do not affect this lib itself.
c.Properties.AndroidMkSharedLibs = append(
c.Properties.AndroidMkSharedLibs, makeLibName)
- // Record baseLibName for snapshots.
- c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, baseLibName(depName))
+ // Record BaseLibName for snapshots.
+ c.Properties.SnapshotSharedLibs = append(c.Properties.SnapshotSharedLibs, BaseLibName(depName))
case libDepTag.static():
if libDepTag.wholeStatic {
c.Properties.AndroidMkWholeStaticLibs = append(
@@ -2855,8 +2869,8 @@
case runtimeDepTag:
c.Properties.AndroidMkRuntimeLibs = append(
c.Properties.AndroidMkRuntimeLibs, MakeLibName(ctx, c, ccDep, depName)+libDepTag.makeSuffix)
- // Record baseLibName for snapshots.
- c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, baseLibName(depName))
+ // Record BaseLibName for snapshots.
+ c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, BaseLibName(depName))
case objDepTag:
depPaths.Objs.objFiles = append(depPaths.Objs.objFiles, linkFile.Path())
case CrtBeginDepTag:
@@ -2924,8 +2938,8 @@
return orderedStaticPaths, transitiveStaticLibs
}
-// baseLibName trims known prefixes and suffixes
-func baseLibName(depName string) string {
+// BaseLibName trims known prefixes and suffixes
+func BaseLibName(depName string) string {
libName := strings.TrimSuffix(depName, llndkLibrarySuffix)
libName = strings.TrimSuffix(libName, vendorPublicLibrarySuffix)
libName = android.RemoveOptionalPrebuiltPrefix(libName)
@@ -2933,7 +2947,7 @@
}
func MakeLibName(ctx android.ModuleContext, c LinkableInterface, ccDep LinkableInterface, depName string) string {
- libName := baseLibName(depName)
+ libName := BaseLibName(depName)
ccDepModule, _ := ccDep.(*Module)
isLLndk := ccDepModule != nil && ccDepModule.IsLlndk()
nonSystemVariantsExist := ccDep.HasNonSystemVariants() || isLLndk
@@ -2941,10 +2955,10 @@
if ccDepModule != nil {
// TODO(ivanlozano) Support snapshots for Rust-produced C library variants.
// Use base module name for snapshots when exporting to Makefile.
- if snapshotPrebuilt, ok := ccDepModule.linker.(snapshotInterface); ok {
+ if snapshotPrebuilt, ok := ccDepModule.linker.(SnapshotInterface); ok {
baseName := ccDepModule.BaseModuleName()
- return baseName + snapshotPrebuilt.snapshotAndroidMkSuffix()
+ return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix()
}
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7fc044d..e0fae5a 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -396,50 +396,6 @@
}
}
-func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
- t.Helper()
- mod := ctx.ModuleForTests(moduleName, variant)
- outputFiles := mod.OutputFiles(t, "")
- if len(outputFiles) != 1 {
- t.Errorf("%q must have single output\n", moduleName)
- return
- }
- snapshotPath := filepath.Join(subDir, snapshotFilename)
-
- if include {
- out := singleton.Output(snapshotPath)
- if fake {
- if out.Rule == nil {
- t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0])
- }
- } else {
- if out.Input.String() != outputFiles[0].String() {
- t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
- }
- }
- } else {
- out := singleton.MaybeOutput(snapshotPath)
- if out.Rule != nil {
- t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
- }
- }
-}
-
-func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
- t.Helper()
- checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
-}
-
-func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
- t.Helper()
- checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
-}
-
-func checkSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
- t.Helper()
- checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
-}
-
func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
t.Helper()
content := android.ContentFromFileRuleForTests(t, params)
@@ -631,21 +587,21 @@
snapshotSingleton := ctx.SingletonForTests("vndk-snapshot")
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLibPath, variant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLib2ndPath, variant2nd)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
- checkSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLibPath, variant)
- checkSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLib2ndPath, variant2nd)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLibPath, variant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", vndkCoreLib2ndPath, variant2nd)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLibPath, variant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_product", "libvndk_product.so", vndkCoreLib2ndPath, variant2nd)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLibPath, variant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk_sp", "libvndk_sp-x.so", vndkSpLib2ndPath, variant2nd)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLibPath, variant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", llndkLib2ndPath, variant2nd)
snapshotConfigsPath := filepath.Join(snapshotVariantPath, "configs")
- checkSnapshot(t, ctx, snapshotSingleton, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
- checkSnapshot(t, ctx, snapshotSingleton, "vndkproduct.libraries.txt", "vndkproduct.libraries.txt", snapshotConfigsPath, "")
+ CheckSnapshot(t, ctx, snapshotSingleton, "llndk.libraries.txt", "llndk.libraries.txt", snapshotConfigsPath, "")
+ CheckSnapshot(t, ctx, snapshotSingleton, "vndkcore.libraries.txt", "vndkcore.libraries.txt", snapshotConfigsPath, "")
+ CheckSnapshot(t, ctx, snapshotSingleton, "vndksp.libraries.txt", "vndksp.libraries.txt", snapshotConfigsPath, "")
+ CheckSnapshot(t, ctx, snapshotSingleton, "vndkprivate.libraries.txt", "vndkprivate.libraries.txt", snapshotConfigsPath, "")
+ CheckSnapshot(t, ctx, snapshotSingleton, "vndkproduct.libraries.txt", "vndkproduct.libraries.txt", snapshotConfigsPath, "")
checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
"LLNDK: libc.so",
@@ -2643,15 +2599,6 @@
return modulesInOrder, allDeps
}
-func getOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
- for _, moduleName := range moduleNames {
- module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
- output := module.outputFile.Path().RelativeToTop()
- paths = append(paths, output)
- }
- return paths
-}
-
func TestStaticLibDepReordering(t *testing.T) {
ctx := testCc(t, `
cc_library {
@@ -2679,7 +2626,7 @@
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).
TransitiveStaticLibrariesForOrdering.ToList().RelativeToTop()
- expected := getOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
+ expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings were not propagated correctly"+
@@ -2714,7 +2661,7 @@
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
actual := ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).
TransitiveStaticLibrariesForOrdering.ToList().RelativeToTop()
- expected := getOutputPaths(ctx, variant, []string{"a", "c", "b"})
+ expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings did not account for shared libs"+
@@ -3357,7 +3304,7 @@
mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a").Rule("ld")
actual := mybin.Implicits[:2]
- expected := getOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
+ expected := GetOutputPaths(ctx, "android_arm64_armv8-a_static", []string{"libfooB", "libfooC"})
if !reflect.DeepEqual(actual, expected) {
t.Errorf("staticDeps orderings were not propagated correctly"+
diff --git a/cc/config/global.go b/cc/config/global.go
index d458311..24e10a4 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -294,12 +294,3 @@
}
var HostPrebuiltTag = pctx.VariableConfigMethod("HostPrebuiltTag", android.Config.PrebuiltOS)
-
-func envOverrideFunc(envVar, defaultVal string) func(ctx android.PackageVarContext) string {
- return func(ctx android.PackageVarContext) string {
- if override := ctx.Config().Getenv(envVar); override != "" {
- return override
- }
- return defaultVal
- }
-}
diff --git a/cc/genrule.go b/cc/genrule.go
index 82d7205..b0efc6c 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -103,7 +103,7 @@
// If not, we assume modules under proprietary paths are compatible for
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
// PLATFORM_VNDK_VERSION.
- if vndkVersion == "current" || !isVendorProprietaryModule(ctx) {
+ if vndkVersion == "current" || !IsVendorProprietaryModule(ctx) {
variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
} else {
variants = append(variants, VendorVariationPrefix+vndkVersion)
diff --git a/cc/image.go b/cc/image.go
index c6b209f..c9c0e63 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -365,8 +365,8 @@
}
func (m *Module) SnapshotVersion(mctx android.BaseModuleContext) string {
- if snapshot, ok := m.linker.(snapshotInterface); ok {
- return snapshot.version()
+ if snapshot, ok := m.linker.(SnapshotInterface); ok {
+ return snapshot.Version()
} else {
mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
// Should we be panicking here instead?
@@ -496,7 +496,7 @@
// BOARD_VNDK_VERSION. The other modules are regarded as AOSP, or
// PLATFORM_VNDK_VERSION.
if m.HasVendorVariant() {
- if isVendorProprietaryModule(mctx) {
+ if IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
vendorVariants = append(vendorVariants, platformVndkVersion)
@@ -525,7 +525,7 @@
platformVndkVersion,
boardVndkVersion,
)
- } else if isVendorProprietaryModule(mctx) {
+ } else if IsVendorProprietaryModule(mctx) {
vendorVariants = append(vendorVariants, boardVndkVersion)
} else {
vendorVariants = append(vendorVariants, platformVndkVersion)
diff --git a/cc/library.go b/cc/library.go
index cdac01c..c88c29a 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -111,9 +111,6 @@
Check_all_apis *bool
}
- // Order symbols in .bss section by their sizes. Only useful for shared libraries.
- Sort_bss_symbols_by_size *bool
-
// Inject boringssl hash into the shared library. This is only intended for use by external/boringssl.
Inject_bssl_hash *bool `android:"arch_variant"`
@@ -305,8 +302,7 @@
linkerAttrs := bp2BuildParseLinkerProps(ctx, m)
exportedIncludes := bp2BuildParseExportedIncludes(ctx, m)
- var srcs bazel.LabelListAttribute
- srcs.Append(compilerAttrs.srcs)
+ srcs := compilerAttrs.srcs
attrs := &bazelCcLibraryAttributes{
Srcs: srcs,
@@ -363,6 +359,7 @@
staticLibrarySdkMemberType,
staticAndSharedLibrarySdkMemberType,
}
+ module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -371,7 +368,7 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
- module.bazelHandler = &staticLibraryBazelHandler{module: module}
+ module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -556,13 +553,17 @@
collectedSnapshotHeaders android.Paths
}
-type staticLibraryBazelHandler struct {
+type ccLibraryBazelHandler struct {
bazelHandler
module *Module
}
-func (handler *staticLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+func (handler *ccLibraryBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ if !handler.module.static() {
+ // TODO(cparsons): Support shared libraries.
+ return false
+ }
bazelCtx := ctx.Config().BazelContext
ccInfo, ok, err := bazelCtx.GetCcInfo(label, ctx.Arch().ArchType)
if err != nil {
@@ -572,18 +573,13 @@
if !ok {
return ok
}
- outputPaths := ccInfo.OutputFiles
+ rootStaticArchives := ccInfo.RootStaticArchives
objPaths := ccInfo.CcObjectFiles
- if len(outputPaths) > 1 {
- // TODO(cparsons): This is actually expected behavior for static libraries with no srcs.
- // We should support this.
- ctx.ModuleErrorf("expected at most one output file for '%s', but got %s", label, objPaths)
+ if len(rootStaticArchives) != 1 {
+ ctx.ModuleErrorf("expected exactly one root archive file for '%s', but got %s", label, rootStaticArchives)
return false
- } else if len(outputPaths) == 0 {
- handler.module.outputFile = android.OptionalPath{}
- return true
}
- outputFilePath := android.PathForBazelOut(ctx, outputPaths[0])
+ outputFilePath := android.PathForBazelOut(ctx, rootStaticArchives[0])
handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
objFiles := make(android.Paths, len(objPaths))
@@ -619,20 +615,14 @@
return ok
}
-// collectHeadersForSnapshot collects all exported headers from library.
-// It globs header files in the source tree for exported include directories,
-// and tracks generated header files separately.
-//
-// This is to be called from GenerateAndroidBuildActions, and then collected
-// header files can be retrieved by snapshotHeaders().
-func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) {
+func GlobHeadersForSnapshot(ctx android.ModuleContext, paths android.Paths) android.Paths {
ret := android.Paths{}
// Headers in the source tree should be globbed. On the contrast, generated headers
// can't be globbed, and they should be manually collected.
// So, we first filter out intermediate directories (which contains generated headers)
// from exported directories, and then glob headers under remaining directories.
- for _, path := range append(android.CopyOfPaths(l.flagExporter.dirs), l.flagExporter.systemDirs...) {
+ for _, path := range paths {
dir := path.String()
// Skip if dir is for generated headers
if strings.HasPrefix(dir, android.PathForOutput(ctx).String()) {
@@ -648,7 +638,7 @@
glob, err := ctx.GlobWithDeps("external/eigen/"+subdir+"/**/*", nil)
if err != nil {
ctx.ModuleErrorf("glob failed: %#v", err)
- return
+ return nil
}
for _, header := range glob {
if strings.HasSuffix(header, "/") {
@@ -666,7 +656,7 @@
glob, err := ctx.GlobWithDeps(dir+"/**/*", nil)
if err != nil {
ctx.ModuleErrorf("glob failed: %#v", err)
- return
+ return nil
}
isLibcxx := strings.HasPrefix(dir, "external/libcxx/include")
for _, header := range glob {
@@ -679,7 +669,7 @@
} else {
// Filter out only the files with extensions that are headers.
found := false
- for _, ext := range headerExts {
+ for _, ext := range HeaderExts {
if strings.HasSuffix(header, ext) {
found = true
break
@@ -692,15 +682,38 @@
ret = append(ret, android.PathForSource(ctx, header))
}
}
+ return ret
+}
- // Collect generated headers
- for _, header := range append(android.CopyOfPaths(l.flagExporter.headers), l.flagExporter.deps...) {
+func GlobGeneratedHeadersForSnapshot(ctx android.ModuleContext, paths android.Paths) android.Paths {
+ ret := android.Paths{}
+ for _, header := range paths {
// TODO(b/148123511): remove exportedDeps after cleaning up genrule
if strings.HasSuffix(header.Base(), "-phony") {
continue
}
ret = append(ret, header)
}
+ return ret
+}
+
+// collectHeadersForSnapshot collects all exported headers from library.
+// It globs header files in the source tree for exported include directories,
+// and tracks generated header files separately.
+//
+// This is to be called from GenerateAndroidBuildActions, and then collected
+// header files can be retrieved by snapshotHeaders().
+func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext) {
+ ret := android.Paths{}
+
+ // Headers in the source tree should be globbed. On the contrast, generated headers
+ // can't be globbed, and they should be manually collected.
+ // So, we first filter out intermediate directories (which contains generated headers)
+ // from exported directories, and then glob headers under remaining directories.
+ ret = append(ret, GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(l.flagExporter.dirs), l.flagExporter.systemDirs...))...)
+
+ // Collect generated headers
+ ret = append(ret, GlobGeneratedHeadersForSnapshot(ctx, append(android.CopyOfPaths(l.flagExporter.headers), l.flagExporter.deps...))...)
l.collectedSnapshotHeaders = ret
}
@@ -849,16 +862,23 @@
if library.stubsVersion() != "" {
vndkVer = library.stubsVersion()
}
- objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Llndk.Symbol_file), vndkVer, "--llndk")
+ nativeAbiResult := parseNativeAbiDefinition(ctx,
+ String(library.Properties.Llndk.Symbol_file),
+ android.ApiLevelOrPanic(ctx, vndkVer), "--llndk")
+ objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
if !Bool(library.Properties.Llndk.Unversioned) {
- library.versionScriptPath = android.OptionalPathForPath(versionScript)
+ library.versionScriptPath = android.OptionalPathForPath(
+ nativeAbiResult.versionScript)
}
return objs
}
if ctx.IsVendorPublicLibrary() {
- objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Vendor_public_library.Symbol_file), "current", "")
+ nativeAbiResult := parseNativeAbiDefinition(ctx,
+ String(library.Properties.Vendor_public_library.Symbol_file),
+ android.FutureApiLevel, "")
+ objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
if !Bool(library.Properties.Vendor_public_library.Unversioned) {
- library.versionScriptPath = android.OptionalPathForPath(versionScript)
+ library.versionScriptPath = android.OptionalPathForPath(nativeAbiResult.versionScript)
}
return objs
}
@@ -868,8 +888,12 @@
ctx.PropertyErrorf("symbol_file", "%q doesn't have .map.txt suffix", symbolFile)
return Objects{}
}
- objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex")
- library.versionScriptPath = android.OptionalPathForPath(versionScript)
+ nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
+ android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion),
+ "--apex")
+ objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
+ library.versionScriptPath = android.OptionalPathForPath(
+ nativeAbiResult.versionScript)
return objs
}
@@ -1315,19 +1339,6 @@
linkerDeps = append(linkerDeps, deps.SharedLibsDeps...)
linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...)
linkerDeps = append(linkerDeps, objs.tidyFiles...)
-
- if Bool(library.Properties.Sort_bss_symbols_by_size) && !library.buildStubs() {
- unsortedOutputFile := android.PathForModuleOut(ctx, "unsorted", fileName)
- transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
- deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
- linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, unsortedOutputFile, implicitOutputs)
-
- symbolOrderingFile := android.PathForModuleOut(ctx, "unsorted", fileName+".symbol_order")
- symbolOrderingFlag := library.baseLinker.sortBssSymbolsBySize(ctx, unsortedOutputFile, symbolOrderingFile, builderFlags)
- builderFlags.localLdFlags += " " + symbolOrderingFlag
- linkerDeps = append(linkerDeps, symbolOrderingFile)
- }
-
transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs,
deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs,
linkerDeps, deps.CrtBegin, deps.CrtEnd, false, builderFlags, outputFile, implicitOutputs)
diff --git a/cc/linker.go b/cc/linker.go
index 5bd21ed..1d8c649 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -594,28 +594,3 @@
},
})
}
-
-// Rule to generate .bss symbol ordering file.
-
-var (
- _ = pctx.SourcePathVariable("genSortedBssSymbolsPath", "build/soong/scripts/gen_sorted_bss_symbols.sh")
- genSortedBssSymbols = pctx.AndroidStaticRule("gen_sorted_bss_symbols",
- blueprint.RuleParams{
- Command: "CLANG_BIN=${clangBin} $genSortedBssSymbolsPath ${in} ${out}",
- CommandDeps: []string{"$genSortedBssSymbolsPath", "${clangBin}/llvm-nm"},
- },
- "clangBin")
-)
-
-func (linker *baseLinker) sortBssSymbolsBySize(ctx ModuleContext, in android.Path, symbolOrderingFile android.ModuleOutPath, flags builderFlags) string {
- ctx.Build(pctx, android.BuildParams{
- Rule: genSortedBssSymbols,
- Description: "generate bss symbol order " + symbolOrderingFile.Base(),
- Output: symbolOrderingFile,
- Input: in,
- Args: map[string]string{
- "clangBin": "${config.ClangBin}",
- },
- })
- return "-Wl,--symbol-ordering-file," + symbolOrderingFile.String()
-}
diff --git a/cc/ndk_abi.go b/cc/ndk_abi.go
new file mode 100644
index 0000000..927fa2e
--- /dev/null
+++ b/cc/ndk_abi.go
@@ -0,0 +1,102 @@
+// 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 cc
+
+import (
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterSingletonType("ndk_abi_dump", NdkAbiDumpSingleton)
+ android.RegisterSingletonType("ndk_abi_diff", NdkAbiDiffSingleton)
+}
+
+func getNdkAbiDumpInstallBase(ctx android.PathContext) android.OutputPath {
+ return android.PathForOutput(ctx).Join(ctx, "abi-dumps/ndk")
+}
+
+func getNdkAbiDumpTimestampFile(ctx android.PathContext) android.OutputPath {
+ return android.PathForOutput(ctx, "ndk_abi_dump.timestamp")
+}
+
+func NdkAbiDumpSingleton() android.Singleton {
+ return &ndkAbiDumpSingleton{}
+}
+
+type ndkAbiDumpSingleton struct{}
+
+func (n *ndkAbiDumpSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var depPaths android.Paths
+ ctx.VisitAllModules(func(module android.Module) {
+ if !module.Enabled() {
+ return
+ }
+
+ if m, ok := module.(*Module); ok {
+ if installer, ok := m.installer.(*stubDecorator); ok {
+ if canDumpAbi() {
+ depPaths = append(depPaths, installer.abiDumpPath)
+ }
+ }
+ }
+ })
+
+ // `m dump-ndk-abi` will dump the NDK ABI.
+ // `development/tools/ndk/update_ndk_abi.sh` will dump the NDK ABI and
+ // update the golden copies in prebuilts/abi-dumps/ndk.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: getNdkAbiDumpTimestampFile(ctx),
+ Implicits: depPaths,
+ })
+
+ ctx.Phony("dump-ndk-abi", getNdkAbiDumpTimestampFile(ctx))
+}
+
+func getNdkAbiDiffTimestampFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "ndk_abi_diff.timestamp")
+}
+
+func NdkAbiDiffSingleton() android.Singleton {
+ return &ndkAbiDiffSingleton{}
+}
+
+type ndkAbiDiffSingleton struct{}
+
+func (n *ndkAbiDiffSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var depPaths android.Paths
+ ctx.VisitAllModules(func(module android.Module) {
+ if m, ok := module.(android.Module); ok && !m.Enabled() {
+ return
+ }
+
+ if m, ok := module.(*Module); ok {
+ if installer, ok := m.installer.(*stubDecorator); ok {
+ depPaths = append(depPaths, installer.abiDiffPaths...)
+ }
+ }
+ })
+
+ depPaths = append(depPaths, getNdkAbiDumpTimestampFile(ctx))
+
+ // `m diff-ndk-abi` will diff the NDK ABI.
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: getNdkAbiDiffTimestampFile(ctx),
+ Implicits: depPaths,
+ })
+
+ ctx.Phony("diff-ndk-abi", getNdkAbiDiffTimestampFile(ctx))
+}
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 95d8477..a458380 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -16,6 +16,8 @@
import (
"fmt"
+ "path/filepath"
+ "runtime"
"strings"
"sync"
@@ -28,6 +30,9 @@
func init() {
pctx.HostBinToolVariable("ndkStubGenerator", "ndkstubgen")
pctx.HostBinToolVariable("ndk_api_coverage_parser", "ndk_api_coverage_parser")
+ pctx.HostBinToolVariable("abidiff", "abidiff")
+ pctx.HostBinToolVariable("abitidy", "abitidy")
+ pctx.HostBinToolVariable("abidw", "abidw")
}
var (
@@ -44,11 +49,31 @@
CommandDeps: []string{"$ndk_api_coverage_parser"},
}, "apiMap")
+ abidw = pctx.AndroidStaticRule("abidw",
+ blueprint.RuleParams{
+ Command: "$abidw --type-id-style hash --no-corpus-path " +
+ "--no-show-locs --no-comp-dir-path -w $symbolList $in | " +
+ "$abitidy --all -o $out",
+ CommandDeps: []string{"$abitidy", "$abidw"},
+ }, "symbolList")
+
+ abidiff = pctx.AndroidStaticRule("abidiff",
+ blueprint.RuleParams{
+ // Need to create *some* output for ninja. We don't want to use tee
+ // because we don't want to spam the build output with "nothing
+ // changed" messages, so redirect output message to $out, and if
+ // changes were detected print the output and fail.
+ Command: "$abidiff $args $in > $out || (cat $out && false)",
+ CommandDeps: []string{"$abidiff"},
+ }, "args")
+
ndkLibrarySuffix = ".ndk"
ndkKnownLibsKey = android.NewOnceKey("ndkKnownLibsKey")
// protects ndkKnownLibs writes during parallel BeginMutator.
ndkKnownLibsLock sync.Mutex
+
+ stubImplementation = dependencyTag{name: "stubImplementation"}
)
// The First_version and Unversioned_until properties of this struct should not
@@ -89,6 +114,8 @@
versionScriptPath android.ModuleGenPath
parsedCoverageXmlPath android.ModuleOutPath
installPath android.Path
+ abiDumpPath android.OutputPath
+ abiDiffPaths android.Paths
apiLevel android.ApiLevel
firstVersion android.ApiLevel
@@ -123,6 +150,16 @@
if !ctx.Module().Enabled() {
return nil
}
+ if ctx.Os() != android.Android {
+ // These modules are always android.DeviceEnabled only, but
+ // those include Fuchsia devices, which we don't support.
+ ctx.Module().Disable()
+ return nil
+ }
+ if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
+ ctx.Module().Disable()
+ return nil
+ }
firstVersion, err := nativeApiLevelFromUser(ctx,
String(this.properties.First_version))
if err != nil {
@@ -204,30 +241,45 @@
return addStubLibraryCompilerFlags(flags)
}
-func compileStubLibrary(ctx ModuleContext, flags Flags, symbolFile, apiLevel, genstubFlags string) (Objects, android.ModuleGenPath) {
- arch := ctx.Arch().ArchType.String()
+type ndkApiOutputs struct {
+ stubSrc android.ModuleGenPath
+ versionScript android.ModuleGenPath
+ symbolList android.ModuleGenPath
+}
+
+func parseNativeAbiDefinition(ctx ModuleContext, symbolFile string,
+ apiLevel android.ApiLevel, genstubFlags string) ndkApiOutputs {
stubSrcPath := android.PathForModuleGen(ctx, "stub.c")
versionScriptPath := android.PathForModuleGen(ctx, "stub.map")
symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
+ symbolListPath := android.PathForModuleGen(ctx, "abi_symbol_list.txt")
apiLevelsJson := android.GetApiLevelsJson(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: genStubSrc,
Description: "generate stubs " + symbolFilePath.Rel(),
- Outputs: []android.WritablePath{stubSrcPath, versionScriptPath},
- Input: symbolFilePath,
- Implicits: []android.Path{apiLevelsJson},
+ Outputs: []android.WritablePath{stubSrcPath, versionScriptPath,
+ symbolListPath},
+ Input: symbolFilePath,
+ Implicits: []android.Path{apiLevelsJson},
Args: map[string]string{
- "arch": arch,
- "apiLevel": apiLevel,
+ "arch": ctx.Arch().ArchType.String(),
+ "apiLevel": apiLevel.String(),
"apiMap": apiLevelsJson.String(),
"flags": genstubFlags,
},
})
- subdir := ""
- srcs := []android.Path{stubSrcPath}
- return compileObjs(ctx, flagsToBuilderFlags(flags), subdir, srcs, nil, nil), versionScriptPath
+ return ndkApiOutputs{
+ stubSrc: stubSrcPath,
+ versionScript: versionScriptPath,
+ symbolList: symbolListPath,
+ }
+}
+
+func compileStubLibrary(ctx ModuleContext, flags Flags, src android.Path) Objects {
+ return compileObjs(ctx, flagsToBuilderFlags(flags), "",
+ android.Paths{src}, nil, nil)
}
func parseSymbolFileForCoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
@@ -248,6 +300,140 @@
return parsedApiCoveragePath
}
+func (this *stubDecorator) findImplementationLibrary(ctx ModuleContext) android.Path {
+ dep := ctx.GetDirectDepWithTag(strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix),
+ stubImplementation)
+ if dep == nil {
+ ctx.ModuleErrorf("Could not find implementation for stub")
+ return nil
+ }
+ impl, ok := dep.(*Module)
+ if !ok {
+ ctx.ModuleErrorf("Implementation for stub is not correct module type")
+ }
+ output := impl.UnstrippedOutputFile()
+ if output == nil {
+ ctx.ModuleErrorf("implementation module (%s) has no output", impl)
+ return nil
+ }
+
+ return output
+}
+
+func (this *stubDecorator) libraryName(ctx ModuleContext) string {
+ return strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix)
+}
+
+func (this *stubDecorator) findPrebuiltAbiDump(ctx ModuleContext,
+ apiLevel android.ApiLevel) android.OptionalPath {
+
+ subpath := filepath.Join("prebuilts/abi-dumps/ndk", apiLevel.String(),
+ ctx.Arch().ArchType.String(), this.libraryName(ctx), "abi.xml")
+ return android.ExistentPathForSource(ctx, subpath)
+}
+
+// Feature flag.
+func canDumpAbi() bool {
+ return runtime.GOOS != "darwin"
+}
+
+// Feature flag to disable diffing against prebuilts.
+func canDiffAbi() bool {
+ return false
+}
+
+func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) {
+ implementationLibrary := this.findImplementationLibrary(ctx)
+ this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
+ this.apiLevel.String(), ctx.Arch().ArchType.String(),
+ this.libraryName(ctx), "abi.xml")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: abidw,
+ Description: fmt.Sprintf("abidw %s", implementationLibrary),
+ Output: this.abiDumpPath,
+ Input: implementationLibrary,
+ Implicit: symbolList,
+ Args: map[string]string{
+ "symbolList": symbolList.String(),
+ },
+ })
+}
+
+func findNextApiLevel(ctx ModuleContext, apiLevel android.ApiLevel) *android.ApiLevel {
+ apiLevels := append(ctx.Config().AllSupportedApiLevels(),
+ android.FutureApiLevel)
+ for _, api := range apiLevels {
+ if api.GreaterThan(apiLevel) {
+ return &api
+ }
+ }
+ return nil
+}
+
+func (this *stubDecorator) diffAbi(ctx ModuleContext) {
+ missingPrebuiltError := fmt.Sprintf(
+ "Did not find prebuilt ABI dump for %q. Generate with "+
+ "//development/tools/ndk/update_ndk_abi.sh.", this.libraryName(ctx))
+
+ // Catch any ABI changes compared to the checked-in definition of this API
+ // level.
+ abiDiffPath := android.PathForModuleOut(ctx, "abidiff.timestamp")
+ prebuiltAbiDump := this.findPrebuiltAbiDump(ctx, this.apiLevel)
+ if !prebuiltAbiDump.Valid() {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: abiDiffPath,
+ Args: map[string]string{
+ "error": missingPrebuiltError,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: abidiff,
+ Description: fmt.Sprintf("abidiff %s %s", prebuiltAbiDump,
+ this.abiDumpPath),
+ Output: abiDiffPath,
+ Inputs: android.Paths{prebuiltAbiDump.Path(), this.abiDumpPath},
+ })
+ }
+ this.abiDiffPaths = append(this.abiDiffPaths, abiDiffPath)
+
+ // Also ensure that the ABI of the next API level (if there is one) matches
+ // this API level. *New* ABI is allowed, but any changes to APIs that exist
+ // in this API level are disallowed.
+ if !this.apiLevel.IsCurrent() {
+ nextApiLevel := findNextApiLevel(ctx, this.apiLevel)
+ if nextApiLevel == nil {
+ panic(fmt.Errorf("could not determine which API level follows "+
+ "non-current API level %s", this.apiLevel))
+ }
+ nextAbiDiffPath := android.PathForModuleOut(ctx,
+ "abidiff_next.timestamp")
+ nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
+ if !nextAbiDump.Valid() {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.ErrorRule,
+ Output: nextAbiDiffPath,
+ Args: map[string]string{
+ "error": missingPrebuiltError,
+ },
+ })
+ } else {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: abidiff,
+ Description: fmt.Sprintf("abidiff %s %s", this.abiDumpPath,
+ nextAbiDump),
+ Output: nextAbiDiffPath,
+ Inputs: android.Paths{this.abiDumpPath, nextAbiDump.Path()},
+ Args: map[string]string{
+ "args": "--no-added-syms",
+ },
+ })
+ }
+ this.abiDiffPaths = append(this.abiDiffPaths, nextAbiDiffPath)
+ }
+}
+
func (c *stubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
if !strings.HasSuffix(String(c.properties.Symbol_file), ".map.txt") {
ctx.PropertyErrorf("symbol_file", "must end with .map.txt")
@@ -264,9 +450,15 @@
}
symbolFile := String(c.properties.Symbol_file)
- objs, versionScript := compileStubLibrary(ctx, flags, symbolFile,
- c.apiLevel.String(), "")
- c.versionScriptPath = versionScript
+ nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile, c.apiLevel, "")
+ objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
+ c.versionScriptPath = nativeAbiResult.versionScript
+ if canDumpAbi() {
+ c.dumpAbi(ctx, nativeAbiResult.symbolList)
+ if canDiffAbi() {
+ c.diffAbi(ctx)
+ }
+ }
if c.apiLevel.IsCurrent() && ctx.PrimaryArch() {
c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile)
}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index d8c500e..4a9601b 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -144,10 +144,9 @@
Inputs: licensePaths,
})
- baseDepPaths := append(installPaths, combinedLicense)
+ baseDepPaths := append(installPaths, combinedLicense,
+ getNdkAbiDiffTimestampFile(ctx))
- // There's a dummy "ndk" rule defined in ndk/Android.mk that depends on
- // this. `m ndk` will build the sysroots.
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
Output: getNdkBaseTimestampFile(ctx),
@@ -156,6 +155,11 @@
fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
+ // There's a phony "ndk" rule defined in core/main.mk that depends on this.
+ // `m ndk` will build the sysroots for the architectures in the current
+ // lunch target. `build/soong/scripts/build-ndk-prebuilts.sh` will build the
+ // sysroots for all the NDK architectures and package them so they can be
+ // imported into the NDK's build.
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
Output: getNdkFullTimestampFile(ctx),
diff --git a/cc/ndkstubgen/__init__.py b/cc/ndkstubgen/__init__.py
index 86bf6ff..2387e69 100755
--- a/cc/ndkstubgen/__init__.py
+++ b/cc/ndkstubgen/__init__.py
@@ -18,7 +18,7 @@
import argparse
import json
import logging
-import os
+from pathlib import Path
import sys
from typing import Iterable, TextIO
@@ -28,10 +28,12 @@
class Generator:
"""Output generator that writes stub source files and version scripts."""
- def __init__(self, src_file: TextIO, version_script: TextIO, arch: Arch,
- api: int, llndk: bool, apex: bool) -> None:
+ def __init__(self, src_file: TextIO, version_script: TextIO,
+ symbol_list: TextIO, arch: Arch, api: int, llndk: bool,
+ apex: bool) -> None:
self.src_file = src_file
self.version_script = version_script
+ self.symbol_list = symbol_list
self.arch = arch
self.api = api
self.llndk = llndk
@@ -39,6 +41,7 @@
def write(self, versions: Iterable[Version]) -> None:
"""Writes all symbol data to the output files."""
+ self.symbol_list.write('[abi_symbol_list]\n')
for version in versions:
self.write_version(version)
@@ -76,11 +79,11 @@
weak = '__attribute__((weak)) '
if 'var' in symbol.tags:
- self.src_file.write('{}int {} = 0;\n'.format(
- weak, symbol.name))
+ self.src_file.write(f'{weak}int {symbol.name} = 0;\n')
else:
- self.src_file.write('{}void {}() {{}}\n'.format(
- weak, symbol.name))
+ self.src_file.write(f'{weak}void {symbol.name}() {{}}\n')
+
+ self.symbol_list.write(f'{symbol.name}\n')
if not version_empty and section_versioned:
base = '' if version.base is None else ' ' + version.base
@@ -91,6 +94,10 @@
"""Parses and returns command line arguments."""
parser = argparse.ArgumentParser()
+ def resolved_path(raw: str) -> Path:
+ """Returns a resolved Path for the given string."""
+ return Path(raw).resolve()
+
parser.add_argument('-v', '--verbose', action='count', default=0)
parser.add_argument(
@@ -103,26 +110,23 @@
parser.add_argument(
'--apex', action='store_true', help='Use the APEX variant.')
- # https://github.com/python/mypy/issues/1317
- # mypy has issues with using os.path.realpath as an argument here.
- parser.add_argument(
- '--api-map',
- type=os.path.realpath, # type: ignore
- required=True,
- help='Path to the API level map JSON file.')
+ parser.add_argument('--api-map',
+ type=resolved_path,
+ required=True,
+ help='Path to the API level map JSON file.')
- parser.add_argument(
- 'symbol_file',
- type=os.path.realpath, # type: ignore
- help='Path to symbol file.')
- parser.add_argument(
- 'stub_src',
- type=os.path.realpath, # type: ignore
- help='Path to output stub source file.')
- parser.add_argument(
- 'version_script',
- type=os.path.realpath, # type: ignore
- help='Path to output version script.')
+ parser.add_argument('symbol_file',
+ type=resolved_path,
+ help='Path to symbol file.')
+ parser.add_argument('stub_src',
+ type=resolved_path,
+ help='Path to output stub source file.')
+ parser.add_argument('version_script',
+ type=resolved_path,
+ help='Path to output version script.')
+ parser.add_argument('symbol_list',
+ type=resolved_path,
+ help='Path to output abigail symbol list.')
return parser.parse_args()
@@ -131,7 +135,7 @@
"""Program entry point."""
args = parse_args()
- with open(args.api_map) as map_file:
+ with args.api_map.open() as map_file:
api_map = json.load(map_file)
api = symbolfile.decode_api_level(args.api, api_map)
@@ -141,19 +145,20 @@
verbosity = 2
logging.basicConfig(level=verbose_map[verbosity])
- with open(args.symbol_file) as symbol_file:
+ with args.symbol_file.open() as symbol_file:
try:
versions = symbolfile.SymbolFileParser(symbol_file, api_map,
args.arch, api, args.llndk,
args.apex).parse()
except symbolfile.MultiplyDefinedSymbolError as ex:
- sys.exit('{}: error: {}'.format(args.symbol_file, ex))
+ sys.exit(f'{args.symbol_file}: error: {ex}')
- with open(args.stub_src, 'w') as src_file:
- with open(args.version_script, 'w') as version_file:
- generator = Generator(src_file, version_file, args.arch, api,
- args.llndk, args.apex)
- generator.write(versions)
+ with args.stub_src.open('w') as src_file:
+ with args.version_script.open('w') as version_script:
+ with args.symbol_list.open('w') as symbol_list:
+ generator = Generator(src_file, version_script, symbol_list,
+ args.arch, api, args.llndk, args.apex)
+ generator.write(versions)
if __name__ == '__main__':
diff --git a/cc/ndkstubgen/test_ndkstubgen.py b/cc/ndkstubgen/test_ndkstubgen.py
index 6d2c9d6..3dbab61 100755
--- a/cc/ndkstubgen/test_ndkstubgen.py
+++ b/cc/ndkstubgen/test_ndkstubgen.py
@@ -33,8 +33,10 @@
# OmitVersionTest, PrivateVersionTest, and SymbolPresenceTest.
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
- 9, False, False)
+ symbol_list_file = io.StringIO()
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file,
+ Arch('arm'), 9, False, False)
version = symbolfile.Version('VERSION_PRIVATE', None, [], [
symbolfile.Symbol('foo', []),
@@ -62,8 +64,10 @@
# SymbolPresenceTest.
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
- 9, False, False)
+ symbol_list_file = io.StringIO()
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file,
+ Arch('arm'), 9, False, False)
version = symbolfile.Version('VERSION_1', None, [], [
symbolfile.Symbol('foo', [Tag('x86')]),
@@ -96,8 +100,10 @@
def test_write(self) -> None:
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
- 9, False, False)
+ symbol_list_file = io.StringIO()
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file,
+ Arch('arm'), 9, False, False)
versions = [
symbolfile.Version('VERSION_1', None, [], [
@@ -141,6 +147,17 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ expected_allowlist = textwrap.dedent("""\
+ [abi_symbol_list]
+ foo
+ bar
+ woodly
+ doodly
+ baz
+ qux
+ """)
+ self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
+
class IntegrationTest(unittest.TestCase):
def test_integration(self) -> None:
@@ -186,8 +203,10 @@
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
- 9, False, False)
+ symbol_list_file = io.StringIO()
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file,
+ Arch('arm'), 9, False, False)
generator.write(versions)
expected_src = textwrap.dedent("""\
@@ -215,6 +234,16 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ expected_allowlist = textwrap.dedent("""\
+ [abi_symbol_list]
+ foo
+ baz
+ qux
+ wibble
+ wobble
+ """)
+ self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
+
def test_integration_future_api(self) -> None:
api_map = {
'O': 9000,
@@ -238,8 +267,10 @@
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
- 9001, False, False)
+ symbol_list_file = io.StringIO()
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file,
+ Arch('arm'), 9001, False, False)
generator.write(versions)
expected_src = textwrap.dedent("""\
@@ -257,6 +288,13 @@
""")
self.assertEqual(expected_version, version_file.getvalue())
+ expected_allowlist = textwrap.dedent("""\
+ [abi_symbol_list]
+ foo
+ bar
+ """)
+ self.assertEqual(expected_allowlist, symbol_list_file.getvalue())
+
def test_multiple_definition(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
VERSION_1 {
@@ -336,8 +374,10 @@
src_file = io.StringIO()
version_file = io.StringIO()
- generator = ndkstubgen.Generator(src_file, version_file, Arch('arm'),
- 9, False, True)
+ symbol_list_file = io.StringIO()
+ generator = ndkstubgen.Generator(src_file,
+ version_file, symbol_list_file,
+ Arch('arm'), 9, False, True)
generator.write(versions)
expected_src = textwrap.dedent("""\
diff --git a/cc/sanitize.go b/cc/sanitize.go
index f486ee4..513730a 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -854,7 +854,7 @@
// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
// except for ones which explicitly disable cfi.
func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool {
- if isVendorProprietaryModule(mctx) {
+ if IsVendorProprietaryModule(mctx) {
return false
}
@@ -1192,7 +1192,7 @@
if c.Device() {
variations = append(variations, c.ImageVariation())
}
- c.addSharedLibDependenciesWithVersions(mctx, variations, depTag, runtimeLibrary, "", true)
+ AddSharedLibDependenciesWithVersions(mctx, c, variations, depTag, runtimeLibrary, "", true)
}
// static lib does not have dependency to the runtime library. The
// dependency will be added to the executables or shared libs using
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index bf11b11..81590a5 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -28,7 +28,7 @@
// Defines the specifics of different images to which the snapshot process is applicable, e.g.,
// vendor, recovery, ramdisk.
-type snapshotImage interface {
+type SnapshotImage interface {
// Returns true if a snapshot should be generated for this image.
shouldGenerateSnapshot(ctx android.SingletonContext) bool
@@ -108,7 +108,7 @@
}
)
-func (vendorSnapshotImage) init(ctx android.RegistrationContext) {
+func (vendorSnapshotImage) Init(ctx android.RegistrationContext) {
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
ctx.RegisterModuleType("vendor_snapshot", vendorSnapshotFactory)
ctx.RegisterModuleType("vendor_snapshot_shared", VendorSnapshotSharedFactory)
@@ -120,6 +120,10 @@
ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
}
+func (vendorSnapshotImage) RegisterAdditionalModule(ctx android.RegistrationContext, name string, factory android.ModuleFactory) {
+ ctx.RegisterModuleType(name, factory)
+}
+
func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
// BOARD_VNDK_VERSION must be set to 'current' in order to generate a snapshot.
return ctx.DeviceConfig().VndkVersion() == "current"
@@ -254,26 +258,28 @@
return recoverySuffix
}
-var vendorSnapshotImageSingleton vendorSnapshotImage
+var VendorSnapshotImageSingleton vendorSnapshotImage
var recoverySnapshotImageSingleton recoverySnapshotImage
func init() {
- vendorSnapshotImageSingleton.init(android.InitRegistrationContext)
+ VendorSnapshotImageSingleton.Init(android.InitRegistrationContext)
recoverySnapshotImageSingleton.init(android.InitRegistrationContext)
}
const (
snapshotHeaderSuffix = "_header."
- snapshotSharedSuffix = "_shared."
- snapshotStaticSuffix = "_static."
+ SnapshotSharedSuffix = "_shared."
+ SnapshotStaticSuffix = "_static."
snapshotBinarySuffix = "_binary."
snapshotObjectSuffix = "_object."
+ SnapshotRlibSuffix = "_rlib."
)
type SnapshotProperties struct {
Header_libs []string `android:"arch_variant"`
Static_libs []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
+ Rlibs []string `android:"arch_variant"`
Vndk_libs []string `android:"arch_variant"`
Binaries []string `android:"arch_variant"`
Objects []string `android:"arch_variant"`
@@ -284,14 +290,14 @@
properties SnapshotProperties
- baseSnapshot baseSnapshotDecorator
+ baseSnapshot BaseSnapshotDecorator
- image snapshotImage
+ image SnapshotImage
}
func (s *snapshot) ImageMutatorBegin(ctx android.BaseModuleContext) {
cfg := ctx.DeviceConfig()
- if !s.image.isUsingSnapshot(cfg) || s.image.targetSnapshotVersion(cfg) != s.baseSnapshot.version() {
+ if !s.image.isUsingSnapshot(cfg) || s.image.targetSnapshotVersion(cfg) != s.baseSnapshot.Version() {
s.Disable()
}
}
@@ -341,7 +347,7 @@
for _, name := range names {
snapshotMap[name] = name +
getSnapshotNameSuffix(snapshotSuffix+moduleSuffix,
- s.baseSnapshot.version(),
+ s.baseSnapshot.Version(),
ctx.DeviceConfig().Arches()[0].ArchType.String())
}
return snapshotMap
@@ -351,8 +357,9 @@
headers := collectSnapshotMap(s.properties.Header_libs, snapshotSuffix, snapshotHeaderSuffix)
binaries := collectSnapshotMap(s.properties.Binaries, snapshotSuffix, snapshotBinarySuffix)
objects := collectSnapshotMap(s.properties.Objects, snapshotSuffix, snapshotObjectSuffix)
- staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, snapshotStaticSuffix)
- sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, snapshotSharedSuffix)
+ staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, SnapshotStaticSuffix)
+ sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, SnapshotSharedSuffix)
+ rlibs := collectSnapshotMap(s.properties.Rlibs, snapshotSuffix, SnapshotRlibSuffix)
vndkLibs := collectSnapshotMap(s.properties.Vndk_libs, "", vndkSuffix)
for k, v := range vndkLibs {
sharedLibs[k] = v
@@ -364,11 +371,12 @@
Objects: objects,
StaticLibs: staticLibs,
SharedLibs: sharedLibs,
+ Rlibs: rlibs,
})
}
type SnapshotInfo struct {
- HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs map[string]string
+ HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs map[string]string
}
var SnapshotInfoProvider = blueprint.NewMutatorProvider(SnapshotInfo{}, "deps")
@@ -376,14 +384,14 @@
var _ android.ImageInterface = (*snapshot)(nil)
func vendorSnapshotFactory() android.Module {
- return snapshotFactory(vendorSnapshotImageSingleton)
+ return snapshotFactory(VendorSnapshotImageSingleton)
}
func recoverySnapshotFactory() android.Module {
return snapshotFactory(recoverySnapshotImageSingleton)
}
-func snapshotFactory(image snapshotImage) android.Module {
+func snapshotFactory(image SnapshotImage) android.Module {
snapshot := &snapshot{}
snapshot.image = image
snapshot.AddProperties(
@@ -393,7 +401,7 @@
return snapshot
}
-type baseSnapshotDecoratorProperties struct {
+type BaseSnapshotDecoratorProperties struct {
// snapshot version.
Version string
@@ -408,7 +416,7 @@
ModuleSuffix string `blueprint:"mutated"`
}
-// baseSnapshotDecorator provides common basic functions for all snapshot modules, such as snapshot
+// BaseSnapshotDecorator provides common basic functions for all snapshot modules, such as snapshot
// version, snapshot arch, etc. It also adds a special suffix to Soong module name, so it doesn't
// collide with source modules. e.g. the following example module,
//
@@ -420,40 +428,40 @@
// }
//
// will be seen as "libbase.vendor_static.30.arm64" by Soong.
-type baseSnapshotDecorator struct {
- baseProperties baseSnapshotDecoratorProperties
- image snapshotImage
+type BaseSnapshotDecorator struct {
+ baseProperties BaseSnapshotDecoratorProperties
+ image SnapshotImage
}
-func (p *baseSnapshotDecorator) Name(name string) string {
+func (p *BaseSnapshotDecorator) Name(name string) string {
return name + p.NameSuffix()
}
-func (p *baseSnapshotDecorator) NameSuffix() string {
- return getSnapshotNameSuffix(p.moduleSuffix(), p.version(), p.arch())
+func (p *BaseSnapshotDecorator) NameSuffix() string {
+ return getSnapshotNameSuffix(p.moduleSuffix(), p.Version(), p.Arch())
}
-func (p *baseSnapshotDecorator) version() string {
+func (p *BaseSnapshotDecorator) Version() string {
return p.baseProperties.Version
}
-func (p *baseSnapshotDecorator) arch() string {
+func (p *BaseSnapshotDecorator) Arch() string {
return p.baseProperties.Target_arch
}
-func (p *baseSnapshotDecorator) moduleSuffix() string {
+func (p *BaseSnapshotDecorator) moduleSuffix() string {
return p.baseProperties.ModuleSuffix
}
-func (p *baseSnapshotDecorator) isSnapshotPrebuilt() bool {
+func (p *BaseSnapshotDecorator) IsSnapshotPrebuilt() bool {
return true
}
-func (p *baseSnapshotDecorator) snapshotAndroidMkSuffix() string {
+func (p *BaseSnapshotDecorator) SnapshotAndroidMkSuffix() string {
return p.baseProperties.Androidmk_suffix
}
-func (p *baseSnapshotDecorator) setSnapshotAndroidMkSuffix(ctx android.ModuleContext, variant string) {
+func (p *BaseSnapshotDecorator) SetSnapshotAndroidMkSuffix(ctx android.ModuleContext, variant string) {
// If there are any 2 or more variations among {core, product, vendor, recovery}
// we have to add the androidmk suffix to avoid duplicate modules with the same
// name.
@@ -461,7 +469,7 @@
Mutator: "image",
Variation: android.CoreVariation})
- if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(*Module).BaseModuleName()) {
+ if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
return
}
@@ -470,12 +478,12 @@
Mutator: "image",
Variation: ProductVariationPrefix + ctx.DeviceConfig().PlatformVndkVersion()})
- if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(*Module).BaseModuleName()) {
+ if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
return
}
- images := []snapshotImage{vendorSnapshotImageSingleton, recoverySnapshotImageSingleton}
+ images := []SnapshotImage{VendorSnapshotImageSingleton, recoverySnapshotImageSingleton}
for _, image := range images {
if p.image == image {
@@ -486,10 +494,10 @@
Variation: image.imageVariantName(ctx.DeviceConfig())})
if ctx.OtherModuleFarDependencyVariantExists(variations,
- ctx.Module().(*Module).BaseModuleName()+
+ ctx.Module().(LinkableInterface).BaseModuleName()+
getSnapshotNameSuffix(
image.moduleNameSuffix()+variant,
- p.version(),
+ p.Version(),
ctx.DeviceConfig().Arches()[0].ArchType.String())) {
p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
return
@@ -501,7 +509,7 @@
// Call this with a module suffix after creating a snapshot module, such as
// vendorSnapshotSharedSuffix, recoverySnapshotBinarySuffix, etc.
-func (p *baseSnapshotDecorator) init(m *Module, image snapshotImage, moduleSuffix string) {
+func (p *BaseSnapshotDecorator) Init(m LinkableInterface, image SnapshotImage, moduleSuffix string) {
p.image = image
p.baseProperties.ModuleSuffix = image.moduleNameSuffix() + moduleSuffix
m.AddProperties(&p.baseProperties)
@@ -512,8 +520,8 @@
// vendorSnapshotLoadHook disables snapshots if it's not BOARD_VNDK_VERSION.
// As vendor snapshot is only for vendor, such modules won't be used at all.
-func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *baseSnapshotDecorator) {
- if p.version() != ctx.DeviceConfig().VndkVersion() {
+func vendorSnapshotLoadHook(ctx android.LoadHookContext, p *BaseSnapshotDecorator) {
+ if p.Version() != ctx.DeviceConfig().VndkVersion() {
ctx.Module().Disable()
return
}
@@ -528,7 +536,7 @@
// include directories, c flags, sanitize dependency information, etc.
//
// These modules are auto-generated by development/vendor_snapshot/update.py.
-type snapshotLibraryProperties struct {
+type SnapshotLibraryProperties struct {
// Prebuilt file for each arch.
Src *string `android:"arch_variant"`
@@ -554,14 +562,14 @@
}
type snapshotLibraryDecorator struct {
- baseSnapshotDecorator
+ BaseSnapshotDecorator
*libraryDecorator
- properties snapshotLibraryProperties
+ properties SnapshotLibraryProperties
sanitizerProperties struct {
CfiEnabled bool `blueprint:"mutated"`
// Library flags for cfi variant.
- Cfi snapshotLibraryProperties `android:"arch_variant"`
+ Cfi SnapshotLibraryProperties `android:"arch_variant"`
}
}
@@ -570,9 +578,9 @@
return p.libraryDecorator.linkerFlags(ctx, flags)
}
-func (p *snapshotLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+func (p *snapshotLibraryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
arches := config.Arches()
- if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
+ if len(arches) == 0 || arches[0].ArchType.String() != p.Arch() {
return false
}
if !p.header() && p.properties.Src == nil {
@@ -587,14 +595,14 @@
func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
var variant string
if p.shared() {
- variant = snapshotSharedSuffix
+ variant = SnapshotSharedSuffix
} else if p.static() {
- variant = snapshotStaticSuffix
+ variant = SnapshotStaticSuffix
} else {
variant = snapshotHeaderSuffix
}
- p.setSnapshotAndroidMkSuffix(ctx, variant)
+ p.SetSnapshotAndroidMkSuffix(ctx, variant)
if p.header() {
return p.libraryDecorator.link(ctx, flags, deps, objs)
@@ -604,7 +612,7 @@
p.properties = p.sanitizerProperties.Cfi
}
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
@@ -657,7 +665,7 @@
}
func (p *snapshotLibraryDecorator) install(ctx ModuleContext, file android.Path) {
- if p.matchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
+ if p.MatchesWithDevice(ctx.DeviceConfig()) && (p.shared() || p.static()) {
p.baseInstaller.install(ctx, file)
}
}
@@ -687,7 +695,7 @@
}
}
-func snapshotLibraryFactory(image snapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
+func snapshotLibraryFactory(image SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
module, library := NewLibrary(android.DeviceSupported)
module.stl = nil
@@ -710,7 +718,7 @@
module.linker = prebuilt
module.installer = prebuilt
- prebuilt.init(module, image, moduleSuffix)
+ prebuilt.Init(module, image, moduleSuffix)
module.AddProperties(
&prebuilt.properties,
&prebuilt.sanitizerProperties,
@@ -724,7 +732,7 @@
// overrides the vendor variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
// is set.
func VendorSnapshotSharedFactory() android.Module {
- module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton, snapshotSharedSuffix)
+ module, prebuilt := snapshotLibraryFactory(VendorSnapshotImageSingleton, SnapshotSharedSuffix)
prebuilt.libraryDecorator.BuildOnlyShared()
return module.Init()
}
@@ -734,7 +742,7 @@
// overrides the recovery variant of the cc shared library with the same name, if BOARD_VNDK_VERSION
// is set.
func RecoverySnapshotSharedFactory() android.Module {
- module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, snapshotSharedSuffix)
+ module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, SnapshotSharedSuffix)
prebuilt.libraryDecorator.BuildOnlyShared()
return module.Init()
}
@@ -744,7 +752,7 @@
// overrides the vendor variant of the cc static library with the same name, if BOARD_VNDK_VERSION
// is set.
func VendorSnapshotStaticFactory() android.Module {
- module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton, snapshotStaticSuffix)
+ module, prebuilt := snapshotLibraryFactory(VendorSnapshotImageSingleton, SnapshotStaticSuffix)
prebuilt.libraryDecorator.BuildOnlyStatic()
return module.Init()
}
@@ -754,7 +762,7 @@
// overrides the recovery variant of the cc static library with the same name, if BOARD_VNDK_VERSION
// is set.
func RecoverySnapshotStaticFactory() android.Module {
- module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, snapshotStaticSuffix)
+ module, prebuilt := snapshotLibraryFactory(recoverySnapshotImageSingleton, SnapshotStaticSuffix)
prebuilt.libraryDecorator.BuildOnlyStatic()
return module.Init()
}
@@ -764,7 +772,7 @@
// overrides the vendor variant of the cc header library with the same name, if BOARD_VNDK_VERSION
// is set.
func VendorSnapshotHeaderFactory() android.Module {
- module, prebuilt := snapshotLibraryFactory(vendorSnapshotImageSingleton, snapshotHeaderSuffix)
+ module, prebuilt := snapshotLibraryFactory(VendorSnapshotImageSingleton, snapshotHeaderSuffix)
prebuilt.libraryDecorator.HeaderOnly()
return module.Init()
}
@@ -794,13 +802,13 @@
}
type snapshotBinaryDecorator struct {
- baseSnapshotDecorator
+ BaseSnapshotDecorator
*binaryDecorator
properties snapshotBinaryProperties
}
-func (p *snapshotBinaryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
- if config.DeviceArch() != p.arch() {
+func (p *snapshotBinaryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.Arch() {
return false
}
if p.properties.Src == nil {
@@ -812,9 +820,9 @@
// cc modules' link functions are to link compiled objects into final binaries.
// As snapshots are prebuilts, this just returns the prebuilt binary
func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
- p.setSnapshotAndroidMkSuffix(ctx, snapshotBinarySuffix)
+ p.SetSnapshotAndroidMkSuffix(ctx, snapshotBinarySuffix)
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
@@ -842,7 +850,7 @@
// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_binary
// overrides the vendor variant of the cc binary with the same name, if BOARD_VNDK_VERSION is set.
func VendorSnapshotBinaryFactory() android.Module {
- return snapshotBinaryFactory(vendorSnapshotImageSingleton, snapshotBinarySuffix)
+ return snapshotBinaryFactory(VendorSnapshotImageSingleton, snapshotBinarySuffix)
}
// recovery_snapshot_binary is a special prebuilt executable binary which is auto-generated by
@@ -852,7 +860,7 @@
return snapshotBinaryFactory(recoverySnapshotImageSingleton, snapshotBinarySuffix)
}
-func snapshotBinaryFactory(image snapshotImage, moduleSuffix string) android.Module {
+func snapshotBinaryFactory(image SnapshotImage, moduleSuffix string) android.Module {
module, binary := NewBinary(android.DeviceSupported)
binary.baseLinker.Properties.No_libcrt = BoolPtr(true)
binary.baseLinker.Properties.Nocrt = BoolPtr(true)
@@ -871,7 +879,7 @@
module.stl = nil
module.linker = prebuilt
- prebuilt.init(module, image, moduleSuffix)
+ prebuilt.Init(module, image, moduleSuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
@@ -889,13 +897,13 @@
}
type snapshotObjectLinker struct {
- baseSnapshotDecorator
+ BaseSnapshotDecorator
objectLinker
properties vendorSnapshotObjectProperties
}
-func (p *snapshotObjectLinker) matchesWithDevice(config android.DeviceConfig) bool {
- if config.DeviceArch() != p.arch() {
+func (p *snapshotObjectLinker) MatchesWithDevice(config android.DeviceConfig) bool {
+ if config.DeviceArch() != p.Arch() {
return false
}
if p.properties.Src == nil {
@@ -907,9 +915,9 @@
// cc modules' link functions are to link compiled objects into final binaries.
// As snapshots are prebuilts, this just returns the prebuilt binary
func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
- p.setSnapshotAndroidMkSuffix(ctx, snapshotObjectSuffix)
+ p.SetSnapshotAndroidMkSuffix(ctx, snapshotObjectSuffix)
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
@@ -933,7 +941,7 @@
}
module.linker = prebuilt
- prebuilt.init(module, vendorSnapshotImageSingleton, snapshotObjectSuffix)
+ prebuilt.Init(module, VendorSnapshotImageSingleton, snapshotObjectSuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
@@ -951,19 +959,19 @@
}
module.linker = prebuilt
- prebuilt.init(module, recoverySnapshotImageSingleton, snapshotObjectSuffix)
+ prebuilt.Init(module, recoverySnapshotImageSingleton, snapshotObjectSuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
-type snapshotInterface interface {
- matchesWithDevice(config android.DeviceConfig) bool
- isSnapshotPrebuilt() bool
- version() string
- snapshotAndroidMkSuffix() string
+type SnapshotInterface interface {
+ MatchesWithDevice(config android.DeviceConfig) bool
+ IsSnapshotPrebuilt() bool
+ Version() string
+ SnapshotAndroidMkSuffix() string
}
-var _ snapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
-var _ snapshotInterface = (*snapshotLibraryDecorator)(nil)
-var _ snapshotInterface = (*snapshotBinaryDecorator)(nil)
-var _ snapshotInterface = (*snapshotObjectLinker)(nil)
+var _ SnapshotInterface = (*vndkPrebuiltLibraryDecorator)(nil)
+var _ SnapshotInterface = (*snapshotLibraryDecorator)(nil)
+var _ SnapshotInterface = (*snapshotBinaryDecorator)(nil)
+var _ SnapshotInterface = (*snapshotObjectLinker)(nil)
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 8eb6164..a6c8ed5 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -20,7 +20,7 @@
)
var (
- headerExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
+ HeaderExts = []string{".h", ".hh", ".hpp", ".hxx", ".h++", ".inl", ".inc", ".ipp", ".h.generic"}
)
func (m *Module) IsSnapshotLibrary() bool {
@@ -109,7 +109,7 @@
return ctx.Config().VndkSnapshotBuildArtifacts()
}
- for _, image := range []snapshotImage{vendorSnapshotImageSingleton, recoverySnapshotImageSingleton} {
+ for _, image := range []SnapshotImage{VendorSnapshotImageSingleton, recoverySnapshotImageSingleton} {
if isSnapshotAware(ctx.DeviceConfig(), m, image.isProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()), apexInfo, image) {
return true
}
diff --git a/cc/testing.go b/cc/testing.go
index 15f7ebb..f5c5ec5 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -15,6 +15,9 @@
package cc
import (
+ "path/filepath"
+ "testing"
+
"android/soong/android"
"android/soong/genrule"
)
@@ -625,7 +628,7 @@
var PrepareForTestWithCcIncludeVndk = android.GroupFixturePreparers(
PrepareForIntegrationTestWithCc,
android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- vendorSnapshotImageSingleton.init(ctx)
+ VendorSnapshotImageSingleton.Init(ctx)
recoverySnapshotImageSingleton.init(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
}),
@@ -674,7 +677,7 @@
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("vndk_prebuilt_shared", VndkPrebuiltSharedFactory)
- vendorSnapshotImageSingleton.init(ctx)
+ VendorSnapshotImageSingleton.Init(ctx)
recoverySnapshotImageSingleton.init(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
RegisterVndkLibraryTxtTypes(ctx)
@@ -685,3 +688,64 @@
return ctx
}
+
+func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) {
+ t.Helper()
+ mod := ctx.ModuleForTests(moduleName, variant)
+ outputFiles := mod.OutputFiles(t, "")
+ if len(outputFiles) != 1 {
+ t.Errorf("%q must have single output\n", moduleName)
+ return
+ }
+ snapshotPath := filepath.Join(subDir, snapshotFilename)
+
+ if include {
+ out := singleton.Output(snapshotPath)
+ if fake {
+ if out.Rule == nil {
+ t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0])
+ }
+ } else {
+ if out.Input.String() != outputFiles[0].String() {
+ t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0])
+ }
+ }
+ } else {
+ out := singleton.MaybeOutput(snapshotPath)
+ if out.Rule != nil {
+ t.Errorf("There must be no rule for module %q output file %q", moduleName, outputFiles[0])
+ }
+ }
+}
+
+func CheckSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ t.Helper()
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false)
+}
+
+func CheckSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ t.Helper()
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false)
+}
+
+func CheckSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) {
+ t.Helper()
+ checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true)
+}
+
+func AssertExcludeFromVendorSnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool, variant string) {
+ t.Helper()
+ m := ctx.ModuleForTests(name, variant).Module().(LinkableInterface)
+ if m.ExcludeFromVendorSnapshot() != expected {
+ t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", m.String(), expected)
+ }
+}
+
+func GetOutputPaths(ctx *android.TestContext, variant string, moduleNames []string) (paths android.Paths) {
+ for _, moduleName := range moduleNames {
+ module := ctx.ModuleForTests(moduleName, variant).Module().(*Module)
+ output := module.outputFile.Path().RelativeToTop()
+ paths = append(paths, output)
+ }
+ return paths
+}
diff --git a/cc/vendor_public_library_test.go b/cc/vendor_public_library_test.go
index 01959b4..769be09 100644
--- a/cc/vendor_public_library_test.go
+++ b/cc/vendor_public_library_test.go
@@ -79,7 +79,7 @@
// test if libsystem is linked to the stub
ld := ctx.ModuleForTests("libsystem", coreVariant).Rule("ld")
libflags := ld.Args["libFlags"]
- stubPaths := getOutputPaths(ctx, coreVariant, []string{"libvendorpublic"})
+ stubPaths := GetOutputPaths(ctx, coreVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libsystem must contain %#v, but was %#v", stubPaths[0], libflags)
}
@@ -87,7 +87,7 @@
// test if libsystem is linked to the stub
ld = ctx.ModuleForTests("libproduct", productVariant).Rule("ld")
libflags = ld.Args["libFlags"]
- stubPaths = getOutputPaths(ctx, productVariant, []string{"libvendorpublic"})
+ stubPaths = GetOutputPaths(ctx, productVariant, []string{"libvendorpublic"})
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libproduct must contain %#v, but was %#v", stubPaths[0], libflags)
}
@@ -95,7 +95,8 @@
// test if libvendor is linked to the real shared lib
ld = ctx.ModuleForTests("libvendor", vendorVariant).Rule("ld")
libflags = ld.Args["libFlags"]
- stubPaths = getOutputPaths(ctx, vendorVariant, []string{"libvendorpublic"})
+ stubPaths = GetOutputPaths(ctx, vendorVariant, []string{"libvendorpublic"})
+
if !strings.Contains(libflags, stubPaths[0].String()) {
t.Errorf("libflags for libvendor must contain %#v, but was %#v", stubPaths[0], libflags)
}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 4e59a95..5a303c8 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -31,7 +31,7 @@
"SOONG_VENDOR_SNAPSHOT_ZIP",
android.OptionalPath{},
true,
- vendorSnapshotImageSingleton,
+ VendorSnapshotImageSingleton,
false, /* fake */
}
@@ -40,7 +40,7 @@
"SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
android.OptionalPath{},
true,
- vendorSnapshotImageSingleton,
+ VendorSnapshotImageSingleton,
true, /* fake */
}
@@ -82,7 +82,7 @@
// Implementation of the image interface specific to the image
// associated with this snapshot (e.g., specific to the vendor image,
// recovery image, etc.).
- image snapshotImage
+ image SnapshotImage
// Whether this singleton is for fake snapshot or not.
// Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
@@ -104,7 +104,7 @@
return RecoverySnapshotSingleton().(*snapshotSingleton).image.isProprietaryPath(dir, deviceConfig)
}
-func isVendorProprietaryModule(ctx android.BaseModuleContext) bool {
+func IsVendorProprietaryModule(ctx android.BaseModuleContext) bool {
// Any module in a vendor proprietary path is a vendor proprietary
// module.
if isVendorProprietaryPath(ctx.ModuleDir(), ctx.DeviceConfig()) {
@@ -147,7 +147,7 @@
}
// Determines if the module is a candidate for snapshot.
-func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshotImage) bool {
+func isSnapshotAware(cfg android.DeviceConfig, m LinkableInterface, inProprietaryPath bool, apexInfo android.ApexInfo, image SnapshotImage) bool {
if !m.Enabled() || m.HiddenFromMake() {
return false
}
@@ -205,7 +205,7 @@
if sanitizable.Static() {
return sanitizable.OutputFile().Valid() && !image.private(m)
}
- if sanitizable.Shared() {
+ if sanitizable.Shared() || sanitizable.Rlib() {
if !sanitizable.OutputFile().Valid() {
return false
}
@@ -393,6 +393,8 @@
libType = "static"
} else if m.Shared() {
libType = "shared"
+ } else if m.Rlib() {
+ libType = "rlib"
} else {
libType = "header"
}
@@ -404,7 +406,7 @@
libPath := m.OutputFile().Path()
stem = libPath.Base()
if sanitizable, ok := m.(PlatformSanitizeable); ok {
- if sanitizable.Static() && sanitizable.SanitizePropDefined() && sanitizable.IsSanitizerEnabled(cfi) {
+ if (sanitizable.Static() || sanitizable.Rlib()) && sanitizable.SanitizePropDefined() && sanitizable.IsSanitizerEnabled(cfi) {
// both cfi and non-cfi variant for static libraries can exist.
// attach .cfi to distinguish between cfi and non-cfi.
// e.g. libbase.a -> libbase.cfi.a
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index c3b5e8c..ceffb29 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -108,27 +108,27 @@
// For shared libraries, only non-VNDK vendor_available modules are captured
sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
jsonFiles = append(jsonFiles,
filepath.Join(sharedDir, "libvendor.so.json"),
filepath.Join(sharedDir, "libvendor_available.so.json"))
// LLNDK modules are not captured
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant)
// For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
// Also cfi variants are captured, except for prebuilts like toolchain_library
staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
staticCfiVariant := fmt.Sprintf("android_vendor.29_%s_%s_static_cfi", archType, archVariant)
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.cfi.a", staticDir, staticCfiVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.cfi.a", staticDir, staticCfiVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.cfi.a", staticDir, staticCfiVariant)
jsonFiles = append(jsonFiles,
filepath.Join(staticDir, "libb.a.json"),
filepath.Join(staticDir, "libvndk.a.json"),
@@ -142,8 +142,8 @@
if archType == "arm64" {
binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- checkSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
jsonFiles = append(jsonFiles,
filepath.Join(binaryDir, "vendor_bin.json"),
filepath.Join(binaryDir, "vendor_available_bin.json"))
@@ -156,7 +156,7 @@
// For object modules, all vendor:true and vendor_available modules are captured.
objectVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
- checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
}
@@ -239,15 +239,15 @@
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
// Included modules
- checkSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
// Check that snapshot captures "prefer: true" prebuilt
- checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
// Excluded modules. Modules not included in the directed vendor snapshot
// are still include as fake modules.
- checkSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
+ CheckSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json"))
}
@@ -839,10 +839,11 @@
[]string{staticVariant, "libvendor.vendor_static.31.arm64"},
[]string{staticVariant, "libvendor_without_snapshot"},
} {
- outputPaths := getOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
+ outputPaths := GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
}
+
}
libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
@@ -868,7 +869,7 @@
}
libclientCfiLdFlags := ctx.ModuleForTests("libclient_cfi", sharedCfiVariant).Rule("ld").Args["libFlags"]
- libvendorCfiOutputPaths := getOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
+ libvendorCfiOutputPaths := GetOutputPaths(ctx, staticCfiVariant, []string{"libvendor.vendor_static.31.arm64"})
if !strings.Contains(libclientCfiLdFlags, libvendorCfiOutputPaths[0].String()) {
t.Errorf("libflags for libclientCfi must contain %#v, but was %#v", libvendorCfiOutputPaths[0], libclientCfiLdFlags)
}
@@ -881,7 +882,7 @@
}
binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("ld").Args["libFlags"]
- libVndkStaticOutputPaths := getOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
+ libVndkStaticOutputPaths := GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.31.arm64"})
if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
@@ -1006,14 +1007,6 @@
assertString(t, staticCfiModule.outputFile.Path().Base(), "libsnapshot.cfi.a")
}
-func assertExcludeFromVendorSnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
- t.Helper()
- m := ctx.ModuleForTests(name, vendorVariant).Module().(*Module)
- if m.ExcludeFromVendorSnapshot() != expected {
- t.Errorf("expected %q ExcludeFromVendorSnapshot to be %t", m.String(), expected)
- }
-}
-
func assertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, name string, expected bool) {
t.Helper()
m := ctx.ModuleForTests(name, recoveryVariant).Module().(*Module)
@@ -1081,13 +1074,13 @@
android.FailIfErrored(t, errs)
// Test an include and exclude framework module.
- assertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false)
- assertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true)
- assertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true)
+ AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, vendorVariant)
+ AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, vendorVariant)
+ AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, vendorVariant)
// A vendor module is excluded, but by its path, not the
// exclude_from_vendor_snapshot property.
- assertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false)
+ AssertExcludeFromVendorSnapshotIs(t, ctx, "libvendor", false, vendorVariant)
// Verify the content of the vendor snapshot.
@@ -1110,15 +1103,15 @@
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
// Included modules
- checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
// Excluded modules
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "libvendor", "libvendor.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor.so.json"))
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
}
@@ -1258,9 +1251,9 @@
// For shared libraries, only recovery_available modules are captured.
sharedVariant := fmt.Sprintf("android_recovery_%s_%s_shared", archType, archVariant)
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
- checkSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libvndk", "libvndk.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
jsonFiles = append(jsonFiles,
filepath.Join(sharedDir, "libvndk.so.json"),
filepath.Join(sharedDir, "librecovery.so.json"),
@@ -1269,9 +1262,9 @@
// For static libraries, all recovery:true and recovery_available modules are captured.
staticVariant := fmt.Sprintf("android_recovery_%s_%s_static", archType, archVariant)
staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
- checkSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libb", "libb.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.a", staticDir, staticVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.a", staticDir, staticVariant)
jsonFiles = append(jsonFiles,
filepath.Join(staticDir, "libb.a.json"),
filepath.Join(staticDir, "librecovery.a.json"),
@@ -1281,8 +1274,8 @@
if archType == "arm64" {
binaryVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
- checkSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
- checkSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "recovery_bin", "recovery_bin", binaryDir, binaryVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "recovery_available_bin", "recovery_available_bin", binaryDir, binaryVariant)
jsonFiles = append(jsonFiles,
filepath.Join(binaryDir, "recovery_bin.json"),
filepath.Join(binaryDir, "recovery_available_bin.json"))
@@ -1295,7 +1288,7 @@
// For object modules, all vendor:true and vendor_available modules are captured.
objectVariant := fmt.Sprintf("android_recovery_%s_%s", archType, archVariant)
objectDir := filepath.Join(snapshotVariantPath, archDir, "object")
- checkSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant)
jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json"))
}
@@ -1393,15 +1386,15 @@
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
// Included modules
- checkSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
// Excluded modules
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
- checkSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
- checkSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
+ CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
}
@@ -1482,15 +1475,15 @@
sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
// Included modules
- checkSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "librecovery", "librecovery.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery.so.json"))
// Check that snapshot captures "prefer: true" prebuilt
- checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
+ CheckSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json"))
// Excluded modules. Modules not included in the directed recovery snapshot
// are still include as fake modules.
- checkSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
+ CheckSnapshotRule(t, ctx, snapshotSingleton, "librecovery_available", "librecovery_available.so", sharedDir, sharedVariant)
includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "librecovery_available.so.json"))
}
diff --git a/cc/vndk.go b/cc/vndk.go
index 6a56c34..dd1c3e1 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -360,7 +360,7 @@
// prebuilt vndk modules should match with device
// TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared
// When b/142675459 is landed, remove following check
- if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.matchesWithDevice(mctx.DeviceConfig()) {
+ if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.MatchesWithDevice(mctx.DeviceConfig()) {
return false
}
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index fc4412a..141f438 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -82,7 +82,7 @@
}
func (p *vndkPrebuiltLibraryDecorator) NameSuffix() string {
- suffix := p.version()
+ suffix := p.Version()
if p.arch() != "" {
suffix += "." + p.arch()
}
@@ -92,7 +92,7 @@
return vndkSuffix + suffix
}
-func (p *vndkPrebuiltLibraryDecorator) version() string {
+func (p *vndkPrebuiltLibraryDecorator) Version() string {
return String(p.properties.Version)
}
@@ -107,7 +107,7 @@
return "64"
}
-func (p *vndkPrebuiltLibraryDecorator) snapshotAndroidMkSuffix() string {
+func (p *vndkPrebuiltLibraryDecorator) SnapshotAndroidMkSuffix() string {
return ".vendor"
}
@@ -133,7 +133,7 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
ctx.Module().HideFromMake()
return nil
}
@@ -163,7 +163,7 @@
p.androidMkSuffix = p.NameSuffix()
vndkVersion := ctx.DeviceConfig().VndkVersion()
- if vndkVersion == p.version() {
+ if vndkVersion == p.Version() {
p.androidMkSuffix = ""
}
@@ -184,7 +184,7 @@
return nil
}
-func (p *vndkPrebuiltLibraryDecorator) matchesWithDevice(config android.DeviceConfig) bool {
+func (p *vndkPrebuiltLibraryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
arches := config.Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
return false
@@ -202,7 +202,7 @@
return false
}
-func (p *vndkPrebuiltLibraryDecorator) isSnapshotPrebuilt() bool {
+func (p *vndkPrebuiltLibraryDecorator) IsSnapshotPrebuilt() bool {
return true
}
diff --git a/jar/jar.go b/jar/jar.go
index a8f06a4..f164ee1 100644
--- a/jar/jar.go
+++ b/jar/jar.go
@@ -77,7 +77,7 @@
Name: MetaDir,
Extra: []byte{MetaDirExtra[1], MetaDirExtra[0], 0, 0},
}
- dirHeader.SetMode(0700 | os.ModeDir)
+ dirHeader.SetMode(0755 | os.ModeDir)
dirHeader.SetModTime(DefaultTime)
return dirHeader
@@ -95,7 +95,7 @@
Method: zip.Store,
UncompressedSize64: uint64(len(b)),
}
- fh.SetMode(0700)
+ fh.SetMode(0644)
fh.SetModTime(DefaultTime)
return fh, b, nil
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 17c7a7b..3607082 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -397,7 +397,17 @@
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
- cmd := rule.Command()
+ var cmd *android.RuleBuilderCommand
+ if len(sourcepaths) > 0 {
+ // We are passing the sourcepaths as an argument to metalava below, but the directories may
+ // not exist already (if they do not contain any listed inputs for metalava). Note that this
+ // is in a rule.SboxInputs()rule, so we are not modifying the actual source tree by creating
+ // these directories.
+ cmd = rule.Command()
+ cmd.Text("mkdir -p").Flags(cmd.PathsForInputs(sourcepaths))
+ }
+
+ cmd = rule.Command()
cmd.FlagWithArg("ANDROID_PREFS_ROOT=", homeDir.String())
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
@@ -431,6 +441,7 @@
}
if len(sourcepaths) > 0 {
+ // TODO(b/153703940): Pass .html files to metalava and remove this argument.
cmd.FlagWithList("-sourcepath ", sourcepaths.Strings(), ":")
} else {
cmd.FlagWithArg("-sourcepath ", `""`)
diff --git a/rust/Android.bp b/rust/Android.bp
index b611672..11069d1 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -32,6 +32,7 @@
"rust.go",
"sanitize.go",
"source_provider.go",
+ "snapshot_prebuilt.go",
"snapshot_utils.go",
"strip.go",
"test.go",
@@ -53,6 +54,7 @@
"rust_test.go",
"source_provider_test.go",
"test_test.go",
+ "vendor_snapshot_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/rust/binary.go b/rust/binary.go
index ffc0413..8d0a0a7 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -137,6 +137,9 @@
// Binaries default to dylib dependencies for device, rlib for host.
if binary.preferRlib() {
return rlibAutoDep
+ } else if mod, ok := ctx.Module().(*Module); ok && mod.InVendor() {
+ // Vendor Rust binaries should prefer rlibs.
+ return rlibAutoDep
} else if ctx.Device() {
return dylibAutoDep
} else {
@@ -147,6 +150,8 @@
func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
if binary.preferRlib() {
return RlibLinkage
+ } else if ctx.RustModule().InVendor() {
+ return RlibLinkage
}
return binary.baseCompiler.stdLinkage(ctx)
}
diff --git a/rust/image.go b/rust/image.go
index 900842e..3b54f12 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -82,7 +82,12 @@
}
func (mod *Module) SnapshotVersion(mctx android.BaseModuleContext) string {
- panic("Rust modules do not support snapshotting: " + mod.BaseModuleName())
+ if snapshot, ok := mod.compiler.(cc.SnapshotInterface); ok {
+ return snapshot.Version()
+ } else {
+ mctx.ModuleErrorf("version is unknown for snapshot prebuilt")
+ return ""
+ }
}
func (mod *Module) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -110,7 +115,9 @@
}
func (mod *Module) IsSnapshotPrebuilt() bool {
- // Rust does not support prebuilts in its snapshots
+ if p, ok := mod.compiler.(cc.SnapshotInterface); ok {
+ return p.IsSnapshotPrebuilt()
+ }
return false
}
@@ -202,6 +209,8 @@
func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) {
// Rust does not support installing to the product image yet.
+ vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
+
if Bool(mod.VendorProperties.Product_available) {
mctx.PropertyErrorf("product_available",
"Rust modules do not yet support being available to the product image")
@@ -217,6 +226,11 @@
mctx.PropertyErrorf("vendor_ramdisk_available", "cannot be set for rust_ffi or rust_ffi_shared modules.")
}
}
+ if vendorSpecific {
+ if lib, ok := mod.compiler.(libraryInterface); ok && lib.buildDylib() {
+ mctx.PropertyErrorf("vendor", "Vendor-only dylibs are not yet supported, use rust_library_rlib.")
+ }
+ }
cc.MutateImage(mctx, mod)
diff --git a/rust/library.go b/rust/library.go
index 1bdf83a..1a56ef6 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -99,6 +99,8 @@
MutatedProperties LibraryMutatedProperties
includeDirs android.Paths
sourceProvider SourceProvider
+
+ collectedSnapshotHeaders android.Paths
}
type libraryInterface interface {
@@ -122,7 +124,8 @@
setStatic()
setSource()
- // Set libstd linkage
+ // libstd linkage functions
+ rlibStd() bool
setRlibStd()
setDylibStd()
@@ -193,6 +196,10 @@
library.MutatedProperties.VariantIsShared = false
}
+func (library *libraryDecorator) rlibStd() bool {
+ return library.MutatedProperties.VariantIsStaticStd
+}
+
func (library *libraryDecorator) setRlibStd() {
library.MutatedProperties.VariantIsStaticStd = true
}
@@ -220,7 +227,10 @@
}
func (library *libraryDecorator) autoDep(ctx android.BottomUpMutatorContext) autoDep {
- if library.preferRlib() {
+ if ctx.Module().(*Module).InVendor() {
+ // Vendor modules should statically link libstd.
+ return rlibAutoDep
+ } else if library.preferRlib() {
return rlibAutoDep
} else if library.rlib() || library.static() {
return rlibAutoDep
@@ -236,7 +246,10 @@
}
func (library *libraryDecorator) stdLinkage(ctx *depsContext) RustLinkage {
- if library.static() || library.MutatedProperties.VariantIsStaticStd {
+ if ctx.RustModule().InVendor() {
+ // Vendor modules should statically link libstd.
+ return RlibLinkage
+ } else if library.static() || library.MutatedProperties.VariantIsStaticStd {
return RlibLinkage
} else if library.baseCompiler.preferRlib() {
return RlibLinkage
@@ -623,6 +636,19 @@
// Disable dylib Vendor Ramdisk variations until we support these.
v.(*Module).Disable()
}
+
+ variation := v.(*Module).ModuleBase.ImageVariation().Variation
+ if strings.HasPrefix(variation, cc.VendorVariationPrefix) &&
+ m.HasVendorVariant() &&
+ !cc.IsVendorProprietaryModule(mctx) &&
+ strings.TrimPrefix(variation, cc.VendorVariationPrefix) == mctx.DeviceConfig().VndkVersion() {
+
+ // cc.MutateImage runs before LibraryMutator, so vendor variations which are meant for rlibs only are
+ // produced for Dylibs; however, dylibs should not be enabled for boardVndkVersion for
+ // non-vendor proprietary modules.
+ v.(*Module).Disable()
+ }
+
case "source":
v.(*Module).compiler.(libraryInterface).setSource()
// The source variant does not produce any library.
@@ -659,9 +685,10 @@
dylib := modules[1].(*Module)
rlib.compiler.(libraryInterface).setRlibStd()
dylib.compiler.(libraryInterface).setDylibStd()
- if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation {
+ if dylib.ModuleBase.ImageVariation().Variation == android.VendorRamdiskVariation ||
+ strings.HasPrefix(dylib.ModuleBase.ImageVariation().Variation, cc.VendorVariationPrefix) {
// TODO(b/165791368)
- // Disable rlibs that link against dylib-std on vendor ramdisk variations until those dylib
+ // Disable rlibs that link against dylib-std on vendor and vendor ramdisk variations until those dylib
// variants are properly supported.
dylib.Disable()
}
@@ -671,3 +698,54 @@
}
}
}
+
+func (l *libraryDecorator) snapshotHeaders() android.Paths {
+ if l.collectedSnapshotHeaders == nil {
+ panic("snapshotHeaders() must be called after collectHeadersForSnapshot()")
+ }
+ return l.collectedSnapshotHeaders
+}
+
+// collectHeadersForSnapshot collects all exported headers from library.
+// It globs header files in the source tree for exported include directories,
+// and tracks generated header files separately.
+//
+// This is to be called from GenerateAndroidBuildActions, and then collected
+// header files can be retrieved by snapshotHeaders().
+func (l *libraryDecorator) collectHeadersForSnapshot(ctx android.ModuleContext, deps PathDeps) {
+ ret := android.Paths{}
+
+ // Glob together the headers from the modules include_dirs property
+ for _, path := range android.CopyOfPaths(l.includeDirs) {
+ dir := path.String()
+ glob, err := ctx.GlobWithDeps(dir+"/**/*", nil)
+ if err != nil {
+ ctx.ModuleErrorf("glob failed: %#v", err)
+ return
+ }
+
+ for _, header := range glob {
+ // Filter out only the files with extensions that are headers.
+ found := false
+ for _, ext := range cc.HeaderExts {
+ if strings.HasSuffix(header, ext) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ continue
+ }
+ ret = append(ret, android.PathForSource(ctx, header))
+ }
+ }
+
+ // Glob together the headers from C dependencies as well, starting with non-generated headers.
+ ret = append(ret, cc.GlobHeadersForSnapshot(ctx, append(android.CopyOfPaths(deps.depIncludePaths), deps.depSystemIncludePaths...))...)
+
+ // Collect generated headers from C dependencies.
+ ret = append(ret, cc.GlobGeneratedHeadersForSnapshot(ctx, deps.depGeneratedHeaders)...)
+
+ // TODO(185577950): If support for generated headers is added, they need to be collected here as well.
+ l.collectedSnapshotHeaders = ret
+}
diff --git a/rust/rust.go b/rust/rust.go
index 46c8f25..b8c8be5 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -85,6 +85,9 @@
VendorRamdiskVariantNeeded bool `blueprint:"mutated"`
ExtraVariants []string `blueprint:"mutated"`
+ // Used by vendor snapshot to record dependencies from snapshot modules.
+ SnapshotSharedLibs []string `blueprint:"mutated"`
+
// Make this module available when building for vendor ramdisk.
// On device without a dedicated recovery partition, the module is only
// available after switching root into
@@ -92,6 +95,20 @@
// the recovery variant instead (TODO(b/165791368) recovery not yet supported)
Vendor_ramdisk_available *bool
+ // Normally Soong uses the directory structure to decide which modules
+ // should be included (framework) or excluded (non-framework) from the
+ // different snapshots (vendor, recovery, etc.), but this property
+ // allows a partner to exclude a module normally thought of as a
+ // framework module from the vendor snapshot.
+ Exclude_from_vendor_snapshot *bool
+
+ // Normally Soong uses the directory structure to decide which modules
+ // should be included (framework) or excluded (non-framework) from the
+ // different snapshots (vendor, recovery, etc.), but this property
+ // allows a partner to exclude a module normally thought of as a
+ // framework module from the recovery snapshot.
+ Exclude_from_recovery_snapshot *bool
+
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
Min_sdk_version *string
@@ -826,6 +843,14 @@
mod.docTimestampFile = mod.compiler.rustdoc(ctx, flags, deps)
+ // glob exported headers for snapshot, if BOARD_VNDK_VERSION is current or
+ // RECOVERY_SNAPSHOT_VERSION is current.
+ if lib, ok := mod.compiler.(snapshotLibraryInterface); ok {
+ if cc.ShouldCollectHeadersForSnapshot(ctx, mod, apexInfo) {
+ lib.collectHeadersForSnapshot(ctx, deps)
+ }
+ }
+
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if mod.installable(apexInfo) {
mod.compiler.install(ctx)
@@ -1056,6 +1081,10 @@
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
directSharedLibDeps = append(directSharedLibDeps, ccDep)
+
+ // Record baseLibName for snapshots.
+ mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))
+
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, makeLibName)
exportDep = true
case cc.IsHeaderDepTag(depTag):
@@ -1161,6 +1190,11 @@
deps := mod.deps(ctx)
var commonDepVariations []blueprint.Variation
+ var snapshotInfo *cc.SnapshotInfo
+
+ if ctx.Os() == android.Android {
+ deps.SharedLibs, _ = cc.RewriteLibs(mod, &snapshotInfo, actx, ctx.Config(), deps.SharedLibs)
+ }
stdLinkage := "dylib-std"
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
@@ -1168,61 +1202,101 @@
}
rlibDepVariations := commonDepVariations
+
if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() {
rlibDepVariations = append(rlibDepVariations,
blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage})
}
- actx.AddVariationDependencies(
- append(rlibDepVariations, []blueprint.Variation{
- {Mutator: "rust_libraries", Variation: rlibVariation}}...),
- rlibDepTag, deps.Rlibs...)
+ // rlibs
+ for _, lib := range deps.Rlibs {
+ depTag := rlibDepTag
+ lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
+
+ actx.AddVariationDependencies(append(rlibDepVariations, []blueprint.Variation{
+ {Mutator: "rust_libraries", Variation: rlibVariation},
+ }...), depTag, lib)
+ }
+
+ // dylibs
actx.AddVariationDependencies(
append(commonDepVariations, []blueprint.Variation{
{Mutator: "rust_libraries", Variation: dylibVariation}}...),
dylibDepTag, deps.Dylibs...)
+ // rustlibs
if deps.Rustlibs != nil && !mod.compiler.Disabled() {
autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
if autoDep.depTag == rlibDepTag {
- actx.AddVariationDependencies(
- append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}),
- autoDep.depTag, deps.Rustlibs...)
+ for _, lib := range deps.Rustlibs {
+ depTag := autoDep.depTag
+ lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
+ actx.AddVariationDependencies(append(rlibDepVariations, []blueprint.Variation{
+ {Mutator: "rust_libraries", Variation: autoDep.variation},
+ }...), depTag, lib)
+ }
} else {
actx.AddVariationDependencies(
append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}),
autoDep.depTag, deps.Rustlibs...)
}
}
+
+ // stdlibs
if deps.Stdlibs != nil {
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
- actx.AddVariationDependencies(
- append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "rlib"}),
- rlibDepTag, deps.Stdlibs...)
+ for _, lib := range deps.Stdlibs {
+ depTag := rlibDepTag
+ lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
+
+ actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
+ depTag, lib)
+ }
} else {
actx.AddVariationDependencies(
append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}),
dylibDepTag, deps.Stdlibs...)
}
}
- actx.AddVariationDependencies(append(commonDepVariations,
- blueprint.Variation{Mutator: "link", Variation: "shared"}),
- cc.SharedDepTag(), deps.SharedLibs...)
- actx.AddVariationDependencies(append(commonDepVariations,
- blueprint.Variation{Mutator: "link", Variation: "static"}),
- cc.StaticDepTag(false), deps.StaticLibs...)
- actx.AddVariationDependencies(append(commonDepVariations,
- blueprint.Variation{Mutator: "link", Variation: "static"}),
- cc.StaticDepTag(true), deps.WholeStaticLibs...)
+
+ for _, lib := range deps.SharedLibs {
+ depTag := cc.SharedDepTag()
+ name, version := cc.StubsLibNameAndVersion(lib)
+
+ variations := []blueprint.Variation{
+ {Mutator: "link", Variation: "shared"},
+ }
+ cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
+ }
+
+ for _, lib := range deps.WholeStaticLibs {
+ depTag := cc.StaticDepTag(true)
+ lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
+
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "link", Variation: "static"},
+ }, depTag, lib)
+ }
+
+ for _, lib := range deps.StaticLibs {
+ depTag := cc.StaticDepTag(false)
+ lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
+
+ actx.AddVariationDependencies([]blueprint.Variation{
+ {Mutator: "link", Variation: "static"},
+ }, depTag, lib)
+ }
actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
crtVariations := cc.GetCrtVariations(ctx, mod)
if deps.CrtBegin != "" {
- actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, deps.CrtBegin)
+ actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag,
+ cc.RewriteSnapshotLib(deps.CrtBegin, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
}
if deps.CrtEnd != "" {
- actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, deps.CrtEnd)
+ actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag,
+ cc.RewriteSnapshotLib(deps.CrtEnd, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
}
if mod.sourceProvider != nil {
@@ -1232,6 +1306,7 @@
bindgen.Properties.Custom_bindgen)
}
}
+
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
}
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 6ae05d9..80f693e 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -37,21 +37,29 @@
genrule.PrepareForTestWithGenRuleBuildComponents,
- PrepareForIntegrationTestWithRust,
+ PrepareForTestWithRustIncludeVndk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = StringPtr("current")
+ variables.ProductVndkVersion = StringPtr("current")
+ variables.Platform_vndk_version = StringPtr("29")
+ }),
)
var rustMockedFiles = android.MockFS{
- "foo.rs": nil,
- "foo.c": nil,
- "src/bar.rs": nil,
- "src/any.h": nil,
- "proto.proto": nil,
- "proto/buf.proto": nil,
- "buf.proto": nil,
- "foo.proto": nil,
- "liby.so": nil,
- "libz.so": nil,
- "data.txt": nil,
+ "foo.rs": nil,
+ "foo.c": nil,
+ "src/bar.rs": nil,
+ "src/any.h": nil,
+ "c_includes/c_header.h": nil,
+ "rust_includes/rust_headers.h": nil,
+ "proto.proto": nil,
+ "proto/buf.proto": nil,
+ "buf.proto": nil,
+ "foo.proto": nil,
+ "liby.so": nil,
+ "libz.so": nil,
+ "data.txt": nil,
+ "liblog.map.txt": nil,
}
// testRust returns a TestContext in which a basic environment has been setup.
@@ -67,19 +75,33 @@
}
func testRustVndk(t *testing.T, bp string) *android.TestContext {
+ return testRustVndkFs(t, bp, rustMockedFiles)
+}
+
+const (
+ sharedVendorVariant = "android_vendor.29_arm64_armv8-a_shared"
+ rlibVendorVariant = "android_vendor.29_arm64_armv8-a_rlib_rlib-std"
+)
+
+func testRustVndkFs(t *testing.T, bp string, fs android.MockFS) *android.TestContext {
+ return testRustVndkFsVersions(t, bp, fs, "current", "current", "29")
+}
+
+func testRustVndkFsVersions(t *testing.T, bp string, fs android.MockFS, device_version, product_version, vndk_version string) *android.TestContext {
skipTestIfOsNotSupported(t)
result := android.GroupFixturePreparers(
prepareForRustTest,
- rustMockedFiles.AddToFixture(),
+ fs.AddToFixture(),
android.FixtureModifyProductVariables(
func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = StringPtr("current")
- variables.ProductVndkVersion = StringPtr("current")
- variables.Platform_vndk_version = StringPtr("29")
+ variables.DeviceVndkVersion = StringPtr(device_version)
+ variables.ProductVndkVersion = StringPtr(product_version)
+ variables.Platform_vndk_version = StringPtr(vndk_version)
},
),
).RunTestWithBp(t, bp)
return result.TestContext
+
}
// testRustCov returns a TestContext in which a basic environment has been
@@ -115,10 +137,14 @@
// testRustVndkError is similar to testRustError, but can be used to test VNDK-related errors.
func testRustVndkError(t *testing.T, pattern string, bp string) {
+ testRustVndkFsError(t, pattern, bp, rustMockedFiles)
+}
+
+func testRustVndkFsError(t *testing.T, pattern string, bp string, fs android.MockFS) {
skipTestIfOsNotSupported(t)
android.GroupFixturePreparers(
prepareForRustTest,
- rustMockedFiles.AddToFixture(),
+ fs.AddToFixture(),
android.FixtureModifyProductVariables(
func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = StringPtr("current")
diff --git a/rust/snapshot_prebuilt.go b/rust/snapshot_prebuilt.go
new file mode 100644
index 0000000..2f54973
--- /dev/null
+++ b/rust/snapshot_prebuilt.go
@@ -0,0 +1,121 @@
+// Copyright 2021 The Android Open Source Project
+//
+// 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 rust
+
+import (
+ "android/soong/android"
+ "android/soong/cc"
+ "github.com/google/blueprint/proptools"
+)
+
+const (
+ snapshotRlibSuffix = "_rlib."
+)
+
+type snapshotLibraryDecorator struct {
+ cc.BaseSnapshotDecorator
+ *libraryDecorator
+ properties cc.SnapshotLibraryProperties
+ sanitizerProperties struct {
+ CfiEnabled bool `blueprint:"mutated"`
+
+ // Library flags for cfi variant.
+ Cfi cc.SnapshotLibraryProperties `android:"arch_variant"`
+ }
+}
+
+func init() {
+ registerRustSnapshotModules(android.InitRegistrationContext)
+}
+
+func registerRustSnapshotModules(ctx android.RegistrationContext) {
+ cc.VendorSnapshotImageSingleton.RegisterAdditionalModule(ctx,
+ "vendor_snapshot_rlib", VendorSnapshotRlibFactory)
+}
+
+func snapshotLibraryFactory(image cc.SnapshotImage, moduleSuffix string) (*Module, *snapshotLibraryDecorator) {
+ module, library := NewRustLibrary(android.DeviceSupported)
+
+ module.sanitize = nil
+ library.stripper.StripProperties.Strip.None = proptools.BoolPtr(true)
+
+ prebuilt := &snapshotLibraryDecorator{
+ libraryDecorator: library,
+ }
+
+ module.compiler = prebuilt
+
+ prebuilt.Init(module, image, moduleSuffix)
+ module.AddProperties(
+ &prebuilt.properties,
+ &prebuilt.sanitizerProperties,
+ )
+
+ return module, prebuilt
+}
+
+func (library *snapshotLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path {
+ var variant string
+ if library.static() {
+ variant = cc.SnapshotStaticSuffix
+ } else if library.shared() {
+ variant = cc.SnapshotSharedSuffix
+ } else if library.rlib() {
+ variant = cc.SnapshotRlibSuffix
+ }
+
+ if !library.dylib() {
+ // TODO(184042776): Remove this check when dylibs are supported in snapshots.
+ library.SetSnapshotAndroidMkSuffix(ctx, variant)
+ }
+
+ if !library.MatchesWithDevice(ctx.DeviceConfig()) {
+ return nil
+ }
+
+ return android.PathForModuleSrc(ctx, *library.properties.Src)
+}
+
+func (library *snapshotLibraryDecorator) rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath {
+ return android.OptionalPath{}
+}
+
+// vendor_snapshot_rlib is a special prebuilt rlib library which is auto-generated by
+// development/vendor_snapshot/update.py. As a part of vendor snapshot, vendor_snapshot_rlib
+// overrides the vendor variant of the rust rlib library with the same name, if BOARD_VNDK_VERSION
+// is set.
+func VendorSnapshotRlibFactory() android.Module {
+ module, prebuilt := snapshotLibraryFactory(cc.VendorSnapshotImageSingleton, cc.SnapshotRlibSuffix)
+ prebuilt.libraryDecorator.BuildOnlyRlib()
+ prebuilt.libraryDecorator.setNoStdlibs()
+ return module.Init()
+}
+
+func (library *snapshotLibraryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
+ arches := config.Arches()
+ if len(arches) == 0 || arches[0].ArchType.String() != library.Arch() {
+ return false
+ }
+ if library.properties.Src == nil {
+ return false
+ }
+ return true
+}
+
+func (library *snapshotLibraryDecorator) IsSnapshotPrebuilt() bool {
+ return true
+}
+
+var _ cc.SnapshotInterface = (*snapshotLibraryDecorator)(nil)
diff --git a/rust/snapshot_utils.go b/rust/snapshot_utils.go
index 943c790..bd7ca7f 100644
--- a/rust/snapshot_utils.go
+++ b/rust/snapshot_utils.go
@@ -18,18 +18,33 @@
"android/soong/android"
)
+// snapshotLibraryInterface is an interface for libraries captured to VNDK / vendor snapshots.
+type snapshotLibraryInterface interface {
+ libraryInterface
+
+ // collectHeadersForSnapshot is called in GenerateAndroidBuildActions for snapshot aware
+ // modules (See isSnapshotAware below).
+ // This function should gather all headers needed for snapshot.
+ collectHeadersForSnapshot(ctx android.ModuleContext, deps PathDeps)
+
+ // snapshotHeaders should return collected headers by collectHeadersForSnapshot.
+ // Calling snapshotHeaders before collectHeadersForSnapshot is an error.
+ snapshotHeaders() android.Paths
+}
+
func (mod *Module) ExcludeFromVendorSnapshot() bool {
- // TODO Rust does not yet support snapshotting
- return false
+ return Bool(mod.Properties.Exclude_from_vendor_snapshot)
}
func (mod *Module) ExcludeFromRecoverySnapshot() bool {
- // TODO Rust does not yet support snapshotting
- return false
+ return Bool(mod.Properties.Exclude_from_recovery_snapshot)
}
func (mod *Module) IsSnapshotLibrary() bool {
- // TODO Rust does not yet support snapshotting
+ if lib, ok := mod.compiler.(libraryInterface); ok {
+ // Rust-native dylibs are not snapshot supported yet. Only snapshot the rlib-std variants of rlibs.
+ return lib.shared() || lib.static() || (lib.rlib() && lib.rlibStd())
+ }
return false
}
@@ -39,8 +54,7 @@
}
func (mod *Module) SnapshotSharedLibs() []string {
- // TODO Rust does not yet support snapshotting
- return []string{}
+ return mod.Properties.SnapshotSharedLibs
}
func (mod *Module) Symlinks() []string {
@@ -49,6 +63,8 @@
}
func (m *Module) SnapshotHeaders() android.Paths {
- // TODO Rust does not yet support snapshotting
+ if l, ok := m.compiler.(snapshotLibraryInterface); ok {
+ return l.snapshotHeaders()
+ }
return android.Paths{}
}
diff --git a/rust/testing.go b/rust/testing.go
index a0f86b2..72f87e1 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -45,6 +45,11 @@
PrepareForTestWithRustDefaultModules,
)
+var PrepareForTestWithRustIncludeVndk = android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithRust,
+ cc.PrepareForTestWithCcIncludeVndk,
+)
+
func GatherRequiredDepsForTest() string {
bp := `
rust_prebuilt_library {
@@ -130,6 +135,9 @@
apex_available: ["//apex_available:platform", "//apex_available:anyapex"],
min_sdk_version: "29",
vendor_available: true,
+ llndk: {
+ symbol_file: "liblog.map.txt",
+ },
}
cc_library {
name: "libprotobuf-cpp-full",
@@ -240,4 +248,5 @@
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
})
ctx.RegisterSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
+ registerRustSnapshotModules(ctx)
}
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
new file mode 100644
index 0000000..815f80e
--- /dev/null
+++ b/rust/vendor_snapshot_test.go
@@ -0,0 +1,1015 @@
+// Copyright 2021 The Android Open Source Project
+//
+// 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 rust
+
+import (
+ "fmt"
+ "path/filepath"
+ "reflect"
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+)
+
+func TestVendorSnapshotCapture(t *testing.T) {
+ bp := `
+ rust_ffi {
+ name: "libffivendor_available",
+ crate_name: "ffivendor_available",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ include_dirs: ["rust_headers/"],
+ }
+
+ rust_ffi {
+ name: "libffivendor",
+ crate_name: "ffivendor",
+ srcs: ["lib.rs"],
+ vendor: true,
+ include_dirs: ["rust_headers/"],
+ }
+
+ rust_library {
+ name: "librustvendor_available",
+ crate_name: "rustvendor_available",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ include_dirs: ["rust_headers/"],
+ }
+
+ rust_library_rlib {
+ name: "librustvendor",
+ crate_name: "rustvendor",
+ srcs: ["lib.rs"],
+ vendor: true,
+ include_dirs: ["rust_headers/"],
+ }
+
+ rust_binary {
+ name: "vendor_available_bin",
+ vendor_available: true,
+ srcs: ["srcs/lib.rs"],
+ }
+
+ rust_binary {
+ name: "vendor_bin",
+ vendor: true,
+ srcs: ["srcs/lib.rs"],
+ }
+ `
+ skipTestIfOsNotSupported(t)
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ rustMockedFiles.AddToFixture(),
+ android.FixtureModifyProductVariables(
+ func(variables android.FixtureProductVariables) {
+ variables.DeviceVndkVersion = StringPtr("current")
+ variables.Platform_vndk_version = StringPtr("29")
+ },
+ ),
+ ).RunTestWithBp(t, bp)
+ ctx := result.TestContext
+
+ // Check Vendor snapshot output.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+ var jsonFiles []string
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ // For shared libraries, only non-VNDK vendor_available modules are captured
+ sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(sharedDir, "libffivendor_available.so.json"))
+
+ // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+ staticVariant := fmt.Sprintf("android_vendor.29_%s_%s_static", archType, archVariant)
+ staticDir := filepath.Join(snapshotVariantPath, archDir, "static")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.a", staticDir, staticVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor", "libffivendor.a", staticDir, staticVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libffivendor_available.a.json"))
+ jsonFiles = append(jsonFiles,
+ filepath.Join(staticDir, "libffivendor.a.json"))
+
+ // For rlib libraries, all vendor:true and vendor_available modules (including VNDK) are captured.
+ rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor", "librustvendor.rlib", rlibDir, rlibVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
+ jsonFiles = append(jsonFiles,
+ filepath.Join(rlibDir, "librustvendor.rlib.json"))
+
+ // For binary executables, all vendor:true and vendor_available modules are captured.
+ if archType == "arm64" {
+ binaryVariant := fmt.Sprintf("android_vendor.29_%s_%s", archType, archVariant)
+ binaryDir := filepath.Join(snapshotVariantPath, archDir, "binary")
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_available_bin", "vendor_available_bin", binaryDir, binaryVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "vendor_bin", "vendor_bin", binaryDir, binaryVariant)
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "vendor_available_bin.json"))
+ jsonFiles = append(jsonFiles,
+ filepath.Join(binaryDir, "vendor_bin.json"))
+ }
+ }
+
+ for _, jsonFile := range jsonFiles {
+ // verify all json files exist
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("%q expected but not found; #%v", jsonFile, jsonFiles)
+ }
+ }
+
+ // fake snapshot should have all outputs in the normal snapshot.
+ fakeSnapshotSingleton := ctx.SingletonForTests("vendor-fake-snapshot")
+
+ for _, output := range snapshotSingleton.AllOutputs() {
+ fakeOutput := strings.Replace(output, "/vendor-snapshot/", "/fake/vendor-snapshot/", 1)
+ if fakeSnapshotSingleton.MaybeOutput(fakeOutput).Rule == nil {
+ t.Errorf("%q expected but not found", fakeOutput)
+ }
+ }
+}
+
+func TestVendorSnapshotDirected(t *testing.T) {
+ bp := `
+ rust_ffi_shared {
+ name: "libffivendor_available",
+ crate_name: "ffivendor_available",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ }
+
+ rust_library {
+ name: "librustvendor_available",
+ crate_name: "rustvendor_available",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ }
+
+ rust_ffi_shared {
+ name: "libffivendor_exclude",
+ crate_name: "ffivendor_exclude",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ }
+
+ rust_library {
+ name: "librustvendor_exclude",
+ crate_name: "rustvendor_exclude",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ }
+`
+ ctx := testRustVndk(t, bp)
+ ctx.Config().TestProductVariables.VendorSnapshotModules = make(map[string]bool)
+ ctx.Config().TestProductVariables.VendorSnapshotModules["librustvendor_available"] = true
+ ctx.Config().TestProductVariables.VendorSnapshotModules["libffivendor_available"] = true
+ ctx.Config().TestProductVariables.DirectedVendorSnapshot = true
+
+ // Check Vendor snapshot output.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var includeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
+ rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+
+ // Included modules
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librustvendor_available", "librustvendor_available.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libffivendor_available", "libffivendor_available.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_available.rlib.json"))
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_available.so.json"))
+
+ // Excluded modules. Modules not included in the directed vendor snapshot
+ // are still include as fake modules.
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "librustvendor_exclude", "librustvendor_exclude.rlib", rlibDir, rlibVariant)
+ cc.CheckSnapshotRule(t, ctx, snapshotSingleton, "libffivendor_exclude", "libffivendor_exclude.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librustvendor_exclude.rlib.json"))
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libffivendor_exclude.so.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+}
+
+func TestVendorSnapshotExclude(t *testing.T) {
+
+ // This test verifies that the exclude_from_vendor_snapshot property
+ // makes its way from the Android.bp source file into the module data
+ // structure. It also verifies that modules are correctly included or
+ // excluded in the vendor snapshot based on their path (framework or
+ // vendor) and the exclude_from_vendor_snapshot property.
+
+ frameworkBp := `
+ rust_ffi_shared {
+ name: "libinclude",
+ crate_name: "include",
+ srcs: ["include.rs"],
+ vendor_available: true,
+ }
+
+ rust_ffi_shared {
+ name: "libexclude",
+ crate_name: "exclude",
+ srcs: ["exclude.rs"],
+ vendor: true,
+ exclude_from_vendor_snapshot: true,
+ }
+
+ rust_ffi_shared {
+ name: "libavailable_exclude",
+ crate_name: "available_exclude",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ exclude_from_vendor_snapshot: true,
+ }
+
+ rust_library {
+ name: "librust_include",
+ crate_name: "rust_include",
+ srcs: ["include.rs"],
+ vendor_available: true,
+ }
+
+ rust_library_rlib {
+ name: "librust_exclude",
+ crate_name: "rust_exclude",
+ srcs: ["exclude.rs"],
+ vendor: true,
+ exclude_from_vendor_snapshot: true,
+ }
+
+ rust_library {
+ name: "librust_available_exclude",
+ crate_name: "rust_available_exclude",
+ srcs: ["lib.rs"],
+ vendor_available: true,
+ exclude_from_vendor_snapshot: true,
+ }
+ `
+
+ mockFS := map[string][]byte{
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/include.rs": nil,
+ "framework/exclude.rs": nil,
+ }
+
+ ctx := testRustVndkFs(t, "", mockFS)
+
+ // Test an include and exclude framework module.
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libinclude", false, sharedVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libexclude", true, sharedVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "libavailable_exclude", true, sharedVendorVariant)
+
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_include", false, rlibVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_exclude", true, rlibVendorVariant)
+ cc.AssertExcludeFromVendorSnapshotIs(t, ctx, "librust_available_exclude", true, rlibVendorVariant)
+
+ // Verify the content of the vendor snapshot.
+
+ snapshotDir := "vendor-snapshot"
+ snapshotVariantPath := filepath.Join("out/soong", snapshotDir, "arm64")
+ snapshotSingleton := ctx.SingletonForTests("vendor-snapshot")
+
+ var includeJsonFiles []string
+ var excludeJsonFiles []string
+
+ for _, arch := range [][]string{
+ []string{"arm64", "armv8-a"},
+ []string{"arm", "armv7-a-neon"},
+ } {
+ archType := arch[0]
+ archVariant := arch[1]
+ archDir := fmt.Sprintf("arch-%s-%s", archType, archVariant)
+
+ sharedVariant := fmt.Sprintf("android_vendor.29_%s_%s_shared", archType, archVariant)
+ sharedDir := filepath.Join(snapshotVariantPath, archDir, "shared")
+ rlibVariant := fmt.Sprintf("android_vendor.29_%s_%s_rlib_rlib-std", archType, archVariant)
+ rlibDir := filepath.Join(snapshotVariantPath, archDir, "rlib")
+
+ // Included modules
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "libinclude", "libinclude.so", sharedDir, sharedVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libinclude.so.json"))
+ cc.CheckSnapshot(t, ctx, snapshotSingleton, "librust_include", "librust_include.rlib", rlibDir, rlibVariant)
+ includeJsonFiles = append(includeJsonFiles, filepath.Join(rlibDir, "librust_include.rlib.json"))
+
+ // Excluded modules
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libexclude", "libexclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libexclude.so.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "libavailable_exclude", "libavailable_exclude.so", sharedDir, sharedVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libavailable_exclude.so.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_exclude", "librust_exclude.rlib", rlibDir, rlibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_exclude.rlib.json"))
+ cc.CheckSnapshotExclude(t, ctx, snapshotSingleton, "librust_available_exclude", "librust_available_exclude.rlib", rlibDir, rlibVariant)
+ excludeJsonFiles = append(excludeJsonFiles, filepath.Join(rlibDir, "librust_available_exclude.rlib.json"))
+ }
+
+ // Verify that each json file for an included module has a rule.
+ for _, jsonFile := range includeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule == nil {
+ t.Errorf("include json file %q not found", jsonFile)
+ }
+ }
+
+ // Verify that each json file for an excluded module has no rule.
+ for _, jsonFile := range excludeJsonFiles {
+ if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil {
+ t.Errorf("exclude json file %q found", jsonFile)
+ }
+ }
+}
+
+func TestVendorSnapshotUse(t *testing.T) {
+ frameworkBp := `
+ cc_library {
+ name: "libvndk",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ nocrt: true,
+ }
+
+ cc_library {
+ name: "libvendor",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "libvendor_available",
+ vendor_available: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ cc_library {
+ name: "lib32",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ compile_multilib: "32",
+ }
+
+ cc_library {
+ name: "lib64",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ compile_multilib: "64",
+ }
+
+ rust_binary {
+ name: "bin",
+ vendor: true,
+ srcs: ["bin.rs"],
+ }
+
+ rust_binary {
+ name: "bin32",
+ vendor: true,
+ compile_multilib: "32",
+ srcs: ["bin.rs"],
+ }
+`
+
+ vndkBp := `
+ vndk_prebuilt_shared {
+ name: "libvndk",
+ version: "30",
+ target_arch: "arm64",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm64: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ arm: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ },
+ }
+
+ // old snapshot module which has to be ignored
+ vndk_prebuilt_shared {
+ name: "libvndk",
+ version: "26",
+ target_arch: "arm64",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm64: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ arm: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ },
+ }
+
+ // different arch snapshot which has to be ignored
+ vndk_prebuilt_shared {
+ name: "libvndk",
+ version: "30",
+ target_arch: "arm",
+ vendor_available: true,
+ product_available: true,
+ vndk: {
+ enabled: true,
+ },
+ arch: {
+ arm: {
+ srcs: ["libvndk.so"],
+ export_include_dirs: ["include/libvndk"],
+ },
+ },
+ }
+`
+
+ vendorProprietaryBp := `
+ cc_library {
+ name: "libvendor_without_snapshot",
+ vendor: true,
+ nocrt: true,
+ no_libcrt: true,
+ stl: "none",
+ system_shared_libs: [],
+ }
+
+ rust_library {
+ name: "librust_vendor_available",
+ crate_name: "rust_vendor",
+ vendor_available: true,
+ srcs: ["client.rs"],
+ }
+
+ rust_ffi_shared {
+ name: "libclient",
+ crate_name: "client",
+ vendor: true,
+ shared_libs: ["libvndk", "libvendor_available"],
+ static_libs: ["libvendor", "libvendor_without_snapshot"],
+ rustlibs: ["librust_vendor_available"],
+ arch: {
+ arm64: {
+ shared_libs: ["lib64"],
+ },
+ arm: {
+ shared_libs: ["lib32"],
+ },
+ },
+ srcs: ["client.rs"],
+ }
+
+ rust_library_rlib {
+ name: "libclient_rust",
+ crate_name: "client_rust",
+ vendor: true,
+ shared_libs: ["libvndk", "libvendor_available"],
+ static_libs: ["libvendor", "libvendor_without_snapshot"],
+ rustlibs: ["librust_vendor_available"],
+ arch: {
+ arm64: {
+ shared_libs: ["lib64"],
+ },
+ arm: {
+ shared_libs: ["lib32"],
+ },
+ },
+ srcs: ["client.rs"],
+ }
+
+ rust_binary {
+ name: "bin_without_snapshot",
+ vendor: true,
+ static_libs: ["libvndk"],
+ srcs: ["bin.rs"],
+ rustlibs: ["librust_vendor_available"],
+ }
+
+ vendor_snapshot {
+ name: "vendor_snapshot",
+ version: "30",
+ arch: {
+ arm64: {
+ vndk_libs: [
+ "libvndk",
+ ],
+ static_libs: [
+ "libvendor",
+ "libvndk",
+ "libclang_rt.builtins-aarch64-android",
+ ],
+ shared_libs: [
+ "libvendor_available",
+ "lib64",
+ ],
+ rlibs: [
+ "libstd",
+ "libtest",
+ "librust_vendor_available",
+ ],
+ binaries: [
+ "bin",
+ ],
+ objects: [
+ "crtend_so",
+ "crtbegin_so",
+ "crtbegin_dynamic",
+ "crtend_android"
+ ],
+ },
+ arm: {
+ vndk_libs: [
+ "libvndk",
+ ],
+ static_libs: [
+ "libvendor",
+ "libvndk",
+ "libclang_rt.builtins-arm-android",
+ ],
+ shared_libs: [
+ "libvendor_available",
+ "lib32",
+ ],
+ rlibs: [
+ "libstd",
+ "libtest",
+ "librust_vendor_available",
+ ],
+ binaries: [
+ "bin32",
+ ],
+ objects: [
+ "crtend_so",
+ "crtbegin_so",
+ "crtbegin_dynamic",
+ "crtend_android"
+ ],
+
+ },
+ }
+ }
+
+ vendor_snapshot_object {
+ name: "crtend_so",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ stl: "none",
+ crt: true,
+ arch: {
+ arm64: {
+ src: "crtend_so.o",
+ },
+ arm: {
+ src: "crtend_so.o",
+ },
+ },
+ }
+
+ vendor_snapshot_object {
+ name: "crtbegin_so",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ stl: "none",
+ crt: true,
+ arch: {
+ arm64: {
+ src: "crtbegin_so.o",
+ },
+ arm: {
+ src: "crtbegin_so.o",
+ },
+ },
+ }
+
+ vendor_snapshot_rlib {
+ name: "libstd",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ sysroot: true,
+ arch: {
+ arm64: {
+ src: "libstd.rlib",
+ },
+ arm: {
+ src: "libstd.rlib",
+ },
+ },
+ }
+
+ vendor_snapshot_rlib {
+ name: "libtest",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ sysroot: true,
+ arch: {
+ arm64: {
+ src: "libtest.rlib",
+ },
+ arm: {
+ src: "libtest.rlib",
+ },
+ },
+ }
+
+ vendor_snapshot_rlib {
+ name: "librust_vendor_available",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "librust_vendor_available.rlib",
+ },
+ arm: {
+ src: "librust_vendor_available.rlib",
+ },
+ },
+ }
+
+ vendor_snapshot_object {
+ name: "crtend_android",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ stl: "none",
+ crt: true,
+ arch: {
+ arm64: {
+ src: "crtend_so.o",
+ },
+ arm: {
+ src: "crtend_so.o",
+ },
+ },
+ }
+
+ vendor_snapshot_object {
+ name: "crtbegin_dynamic",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ stl: "none",
+ crt: true,
+ arch: {
+ arm64: {
+ src: "crtbegin_so.o",
+ },
+ arm: {
+ src: "crtbegin_so.o",
+ },
+ },
+ }
+
+ vendor_snapshot_static {
+ name: "libvndk",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "both",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvndk.a",
+ },
+ arm: {
+ src: "libvndk.a",
+ },
+ },
+ shared_libs: ["libvndk"],
+ export_shared_lib_headers: ["libvndk"],
+ }
+
+ vendor_snapshot_static {
+ name: "libclang_rt.builtins-aarch64-android",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libclang_rt.builtins-aarch64-android.a",
+ },
+ },
+ }
+
+ vendor_snapshot_static {
+ name: "libclang_rt.builtins-arm-android",
+ version: "30",
+ target_arch: "arm64",
+ vendor: true,
+ arch: {
+ arm: {
+ src: "libclang_rt.builtins-arm-android.a",
+ },
+ },
+ }
+
+ vendor_snapshot_shared {
+ name: "lib32",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "32",
+ vendor: true,
+ arch: {
+ arm: {
+ src: "lib32.so",
+ },
+ },
+ }
+
+ vendor_snapshot_shared {
+ name: "lib64",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "lib64.so",
+ },
+ },
+ }
+ vendor_snapshot_shared {
+ name: "liblog",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "liblog.so",
+ },
+ },
+ }
+
+ vendor_snapshot_static {
+ name: "libvendor",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "both",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvendor.a",
+ export_include_dirs: ["include/libvendor"],
+ },
+ arm: {
+ src: "libvendor.a",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
+ vendor_snapshot_shared {
+ name: "libvendor_available",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "both",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "libvendor_available.so",
+ export_include_dirs: ["include/libvendor"],
+ },
+ arm: {
+ src: "libvendor_available.so",
+ export_include_dirs: ["include/libvendor"],
+ },
+ },
+ }
+
+ vendor_snapshot_binary {
+ name: "bin",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "64",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "bin",
+ },
+ },
+ }
+
+ vendor_snapshot_binary {
+ name: "bin32",
+ version: "30",
+ target_arch: "arm64",
+ compile_multilib: "32",
+ vendor: true,
+ arch: {
+ arm: {
+ src: "bin32",
+ },
+ },
+ }
+
+ // old snapshot module which has to be ignored
+ vendor_snapshot_binary {
+ name: "bin",
+ version: "26",
+ target_arch: "arm64",
+ compile_multilib: "first",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "bin",
+ },
+ },
+ }
+
+ // different arch snapshot which has to be ignored
+ vendor_snapshot_binary {
+ name: "bin",
+ version: "30",
+ target_arch: "arm",
+ compile_multilib: "first",
+ vendor: true,
+ arch: {
+ arm64: {
+ src: "bin",
+ },
+ },
+ }
+`
+
+ mockFS := android.MockFS{
+ "framework/Android.bp": []byte(frameworkBp),
+ "framework/bin.rs": nil,
+ "vendor/Android.bp": []byte(vendorProprietaryBp),
+ "vendor/bin": nil,
+ "vendor/bin32": nil,
+ "vendor/bin.rs": nil,
+ "vendor/client.rs": nil,
+ "vendor/include/libvndk/a.h": nil,
+ "vendor/include/libvendor/b.h": nil,
+ "vendor/libvndk.a": nil,
+ "vendor/libvendor.a": nil,
+ "vendor/libvendor.so": nil,
+ "vendor/lib32.so": nil,
+ "vendor/lib64.so": nil,
+ "vendor/liblog.so": nil,
+ "vendor/libstd.rlib": nil,
+ "vendor/libtest.rlib": nil,
+ "vendor/librust_vendor_available.rlib": nil,
+ "vendor/crtbegin_so.o": nil,
+ "vendor/crtend_so.o": nil,
+ "vendor/libclang_rt.builtins-aarch64-android.a": nil,
+ "vendor/libclang_rt.builtins-arm-android.a": nil,
+ "vndk/Android.bp": []byte(vndkBp),
+ "vndk/include/libvndk/a.h": nil,
+ "vndk/libvndk.so": nil,
+ }
+
+ sharedVariant := "android_vendor.30_arm64_armv8-a_shared"
+ rlibVariant := "android_vendor.30_arm64_armv8-a_rlib_rlib-std"
+ staticVariant := "android_vendor.30_arm64_armv8-a_static"
+ binaryVariant := "android_vendor.30_arm64_armv8-a"
+
+ shared32Variant := "android_vendor.30_arm_armv7-a-neon_shared"
+ binary32Variant := "android_vendor.30_arm_armv7-a-neon"
+
+ ctx := testRustVndkFsVersions(t, "", mockFS, "30", "current", "31")
+
+ // libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot
+ libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").Args["linkFlags"]
+ for _, input := range [][]string{
+ []string{sharedVariant, "libvndk.vndk.30.arm64"},
+ []string{staticVariant, "libvendor.vendor_static.30.arm64"},
+ []string{staticVariant, "libvendor_without_snapshot"},
+ } {
+ outputPaths := cc.GetOutputPaths(ctx, input[0] /* variant */, []string{input[1]} /* module name */)
+ if !strings.Contains(libclientLdFlags, outputPaths[0].String()) {
+ t.Errorf("libflags for libclient must contain %#v, but was %#v", outputPaths[0], libclientLdFlags)
+ }
+ }
+
+ libclientAndroidMkSharedLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkSharedLibs
+ if g, w := libclientAndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib64", "liblog.vendor", "libc.vendor", "libm.vendor", "libdl.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient AndroidMkSharedLibs %q, got %q", w, g)
+ }
+
+ libclientAndroidMkStaticLibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkStaticLibs
+ if g, w := libclientAndroidMkStaticLibs, []string{"libvendor", "libvendor_without_snapshot", "libclang_rt.builtins-aarch64-android.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient AndroidMkStaticLibs %q, got %q", w, g)
+ }
+
+ libclientAndroidMkRlibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkRlibs
+ if g, w := libclientAndroidMkRlibs, []string{"librust_vendor_available.vendor_rlib.30.arm64.rlib-std", "libstd.vendor_rlib.30.arm64", "libtest.vendor_rlib.30.arm64"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
+ }
+
+ libclientAndroidMkDylibs := ctx.ModuleForTests("libclient", sharedVariant).Module().(*Module).Properties.AndroidMkDylibs
+ if len(libclientAndroidMkDylibs) > 0 {
+ t.Errorf("wanted libclient libclientAndroidMkDylibs [], got %q", libclientAndroidMkDylibs)
+ }
+
+ libclient32AndroidMkSharedLibs := ctx.ModuleForTests("libclient", shared32Variant).Module().(*Module).Properties.AndroidMkSharedLibs
+ if g, w := libclient32AndroidMkSharedLibs, []string{"libvndk.vendor", "libvendor_available.vendor", "lib32", "liblog.vendor", "libc.vendor", "libm.vendor", "libdl.vendor"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient32 AndroidMkSharedLibs %q, got %q", w, g)
+ }
+
+ libclientRustAndroidMkRlibs := ctx.ModuleForTests("libclient_rust", rlibVariant).Module().(*Module).Properties.AndroidMkRlibs
+ if g, w := libclientRustAndroidMkRlibs, []string{"librust_vendor_available.vendor_rlib.30.arm64.rlib-std", "libstd.vendor_rlib.30.arm64", "libtest.vendor_rlib.30.arm64"}; !reflect.DeepEqual(g, w) {
+ t.Errorf("wanted libclient libclientAndroidMkRlibs %q, got %q", w, g)
+ }
+
+ binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").Args["linkFlags"]
+ libVndkStaticOutputPaths := cc.GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"})
+ if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
+ t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
+ libVndkStaticOutputPaths[0], binWithoutSnapshotLdFlags)
+ }
+
+ // bin is installed by bin.vendor_binary.30.arm64
+ ctx.ModuleForTests("bin.vendor_binary.30.arm64", binaryVariant).Output("bin")
+
+ // bin32 is installed by bin32.vendor_binary.30.arm64
+ ctx.ModuleForTests("bin32.vendor_binary.30.arm64", binary32Variant).Output("bin32")
+
+ // bin_without_snapshot is installed by bin_without_snapshot
+ ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Output("bin_without_snapshot")
+
+ // libvendor, libvendor_available and bin don't have vendor.30 variant
+ libvendorVariants := ctx.ModuleVariantsForTests("libvendor")
+ if android.InList(sharedVariant, libvendorVariants) {
+ t.Errorf("libvendor must not have variant %#v, but it does", sharedVariant)
+ }
+
+ libvendorAvailableVariants := ctx.ModuleVariantsForTests("libvendor_available")
+ if android.InList(sharedVariant, libvendorAvailableVariants) {
+ t.Errorf("libvendor_available must not have variant %#v, but it does", sharedVariant)
+ }
+
+ binVariants := ctx.ModuleVariantsForTests("bin")
+ if android.InList(binaryVariant, binVariants) {
+ t.Errorf("bin must not have variant %#v, but it does", sharedVariant)
+ }
+}
diff --git a/scripts/gen_sorted_bss_symbols.sh b/scripts/gen_sorted_bss_symbols.sh
deleted file mode 100755
index a9b61a1..0000000
--- a/scripts/gen_sorted_bss_symbols.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash -e
-
-# Copyright 2019 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.
-
-# Script to generate a symbol ordering file that sorts bss section symbols by
-# their sizes.
-# Inputs:
-# Environment:
-# CLANG_BIN: path to the clang bin directory
-# Arguments:
-# $1: Input ELF file
-# $2: Output symbol ordering file
-
-set -o pipefail
-
-${CLANG_BIN}/llvm-nm --size-sort $1 | awk '{if ($2 == "b" || $2 == "B") print $3}' > $2
diff --git a/zip/zip.go b/zip/zip.go
index 6e412c9..ae379f5 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -656,9 +656,9 @@
UncompressedSize64: uint64(fileSize),
}
- mode := os.FileMode(0600)
+ mode := os.FileMode(0644)
if executable {
- mode = 0700
+ mode = 0755
}
header.SetMode(mode)
@@ -955,7 +955,7 @@
dirHeader = &zip.FileHeader{
Name: cleanDir + "/",
}
- dirHeader.SetMode(0700 | os.ModeDir)
+ dirHeader.SetMode(0755 | os.ModeDir)
}
dirHeader.SetModTime(z.time)
diff --git a/zip/zip_test.go b/zip/zip_test.go
index 441dea3..79cc0b4 100644
--- a/zip/zip_test.go
+++ b/zip/zip_test.go
@@ -62,7 +62,7 @@
Method: method,
CRC32: crc32.ChecksumIEEE(contents),
UncompressedSize64: uint64(len(contents)),
- ExternalAttrs: (syscall.S_IFREG | 0600) << 16,
+ ExternalAttrs: (syscall.S_IFREG | 0644) << 16,
}
}
@@ -72,7 +72,7 @@
Method: zip.Store,
CRC32: crc32.ChecksumIEEE(contents),
UncompressedSize64: uint64(len(contents)),
- ExternalAttrs: (syscall.S_IFREG | 0700) << 16,
+ ExternalAttrs: (syscall.S_IFREG | 0644) << 16,
}
}
@@ -92,7 +92,7 @@
Method: zip.Store,
CRC32: crc32.ChecksumIEEE(nil),
UncompressedSize64: 0,
- ExternalAttrs: (syscall.S_IFDIR|0700)<<16 | 0x10,
+ ExternalAttrs: (syscall.S_IFDIR|0755)<<16 | 0x10,
}
}