Merge "Use libabigail to track NDK ABIs."
diff --git a/android/arch.go b/android/arch.go
index f057342..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)
@@ -1885,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()
@@ -1923,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() ).
@@ -1951,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
@@ -1992,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 4967b12..8c68055 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -220,8 +220,7 @@
// Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build.
mixedBuildsDisabledList = []string{
- "libc_common_shared", // cparsons@ cc_library_static, breaks module `libc`.
- "libc_nomalloc", // cparsons@ cc_library_static, breaks module `linker`
+ // Currently empty, though should remain present to facilitate granular bp2build migration.
}
// Used for quicker lookups
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index a1206dc..f906c8a 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -351,6 +351,9 @@
"HOME="+paths.homeDir,
pwdPrefix(),
"BUILD_DIR="+absolutePath(paths.buildDir),
+ // Make OUT_DIR absolute here so tools/bazel.sh uses the correct
+ // OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
+ "OUT_DIR="+absolutePath(paths.outDir()),
// Disables local host detection of gcc; toolchain information is defined
// explicitly in BUILD files.
"BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1")
@@ -576,6 +579,11 @@
return filepath.Join(p.buildDir, "workspace")
}
+// Returns the path to the top level out dir ($OUT_DIR).
+func (p *bazelPaths) outDir() string {
+ return filepath.Dir(p.buildDir)
+}
+
// Issues commands to Bazel to receive results for all cquery requests
// queued in the BazelContext.
func (context *bazelContext) InvokeBazel() error {
diff --git a/android/filegroup.go b/android/filegroup.go
index fc6850e..e207412 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -63,7 +63,10 @@
Srcs: srcs,
}
- props := bazel.BazelTargetModuleProperties{Rule_class: "filegroup"}
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "filegroup",
+ Bzl_load_location: "//build/bazel/rules:filegroup.bzl",
+ }
ctx.CreateBazelTargetModule(BazelFileGroupFactory, fg.Name(), props, attrs)
}
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..6d235d6 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -479,18 +479,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)
}
}
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..df9c9bf
--- /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 b2d68da..c55de95 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,10 @@
Excludes []Label
}
+func (ll *LabelList) IsNil() bool {
+ return ll.Includes == nil && ll.Excludes == nil
+}
+
// uniqueParentDirectories returns a list of the unique parent directories for
// all files in ll.Includes.
func (ll *LabelList) uniqueParentDirectories() []string {
@@ -106,7 +109,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)
@@ -137,6 +160,32 @@
return strings
}
+// Map a function over all labels in a LabelList.
+func MapLabelList(mapOver LabelList, mapFn func(string) string) LabelList {
+ var includes []Label
+ for _, inc := range mapOver.Includes {
+ mappedLabel := Label{Label: mapFn(inc.Label), OriginalModuleName: inc.OriginalModuleName}
+ includes = append(includes, mappedLabel)
+ }
+ // mapFn is not applied over excludes, but they are propagated as-is.
+ return LabelList{Includes: includes, Excludes: mapOver.Excludes}
+}
+
+// Map a function over all Labels in a LabelListAttribute
+func MapLabelListAttribute(mapOver LabelListAttribute, mapFn func(string) string) LabelListAttribute {
+ var result LabelListAttribute
+
+ result.Value = MapLabelList(mapOver.Value, mapFn)
+
+ for axis, configToLabels := range mapOver.ConfigurableValues {
+ for config, value := range configToLabels {
+ result.SetSelectValue(axis, config, MapLabelList(value, mapFn))
+ }
+ }
+
+ return result
+}
+
// Return all needles in a given haystack, where needleFn is true for needles.
func FilterLabelList(haystack LabelList, needleFn func(string) bool) LabelList {
var includes []Label
@@ -145,26 +194,20 @@
includes = append(includes, inc)
}
}
+ // needleFn is not applied over excludes, but they are propagated as-is.
return LabelList{Includes: includes, Excludes: haystack.Excludes}
}
// 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
@@ -172,24 +215,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
}
@@ -234,489 +271,202 @@
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
- }
- }
-
- for os := range PlatformOsMap {
- if len(attrs.GetOsValueForTarget(os).Includes) > 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).Includes) > 0 {
- return true
- }
- }
- }
- return false
-}
-
-func (attrs *LabelListAttribute) archValuePtrs() map[string]*LabelList {
- return map[string]*LabelList{
- ARCH_X86: &attrs.ArchValues.X86,
- ARCH_X86_64: &attrs.ArchValues.X86_64,
- ARCH_ARM: &attrs.ArchValues.Arm,
- ARCH_ARM64: &attrs.ArchValues.Arm64,
- 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))
- }
+// HasConfigurableValues returns true if the attribute contains axis-specific label list values.
+func (lla LabelListAttribute) HasConfigurableValues() bool {
+ return len(lla.ConfigurableValues) > 0
}
// StringListAttribute corresponds to the string_list Bazel attribute type with
@@ -725,256 +475,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..bc556bf 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,7 +157,49 @@
},
}
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)
}
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 b87d713..c8ae031 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -47,6 +47,7 @@
func registerCcLibraryModuleTypes(ctx android.RegistrationContext) {
cc.RegisterCCBuildComponents(ctx)
+ ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
@@ -535,6 +536,139 @@
})
}
+func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library shared/static props with c/cpp/s mixed sources",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ depsMutators: []android.RegisterMutatorFunc{cc.RegisterDepsBp2Build},
+ dir: "foo/bar",
+ filesystem: map[string]string{
+ "foo/bar/both_source.cpp": "",
+ "foo/bar/both_source.cc": "",
+ "foo/bar/both_source.c": "",
+ "foo/bar/both_source.s": "",
+ "foo/bar/both_source.S": "",
+ "foo/bar/shared_source.cpp": "",
+ "foo/bar/shared_source.cc": "",
+ "foo/bar/shared_source.c": "",
+ "foo/bar/shared_source.s": "",
+ "foo/bar/shared_source.S": "",
+ "foo/bar/static_source.cpp": "",
+ "foo/bar/static_source.cc": "",
+ "foo/bar/static_source.c": "",
+ "foo/bar/static_source.s": "",
+ "foo/bar/static_source.S": "",
+ "foo/bar/Android.bp": `
+cc_library {
+ name: "a",
+ srcs: [
+ "both_source.cpp",
+ "both_source.cc",
+ "both_source.c",
+ "both_source.s",
+ "both_source.S",
+ ":both_filegroup",
+ ],
+ static: {
+ srcs: [
+ "static_source.cpp",
+ "static_source.cc",
+ "static_source.c",
+ "static_source.s",
+ "static_source.S",
+ ":static_filegroup",
+ ],
+ },
+ shared: {
+ srcs: [
+ "shared_source.cpp",
+ "shared_source.cc",
+ "shared_source.c",
+ "shared_source.s",
+ "shared_source.S",
+ ":shared_filegroup",
+ ],
+ },
+ bazel_module: { bp2build_available: true },
+}
+
+filegroup {
+ name: "both_filegroup",
+ srcs: [
+ // Not relevant, handled by filegroup macro
+ ],
+}
+
+filegroup {
+ name: "shared_filegroup",
+ srcs: [
+ // Not relevant, handled by filegroup macro
+ ],
+}
+
+filegroup {
+ name: "static_filegroup",
+ srcs: [
+ // Not relevant, handled by filegroup macro
+ ],
+}
+`,
+ },
+ blueprint: soongCcLibraryPreamble,
+ expectedBazelTargets: []string{`cc_library(
+ name = "a",
+ copts = [
+ "-Ifoo/bar",
+ "-I$(BINDIR)/foo/bar",
+ ],
+ shared_srcs = [
+ ":shared_filegroup_cpp_srcs",
+ "shared_source.cc",
+ "shared_source.cpp",
+ ],
+ shared_srcs_as = [
+ "shared_source.s",
+ "shared_source.S",
+ ":shared_filegroup_as_srcs",
+ ],
+ shared_srcs_c = [
+ "shared_source.c",
+ ":shared_filegroup_c_srcs",
+ ],
+ srcs = [
+ ":both_filegroup_cpp_srcs",
+ "both_source.cc",
+ "both_source.cpp",
+ ],
+ srcs_as = [
+ "both_source.s",
+ "both_source.S",
+ ":both_filegroup_as_srcs",
+ ],
+ srcs_c = [
+ "both_source.c",
+ ":both_filegroup_c_srcs",
+ ],
+ static_srcs = [
+ ":static_filegroup_cpp_srcs",
+ "static_source.cc",
+ "static_source.cpp",
+ ],
+ static_srcs_as = [
+ "static_source.s",
+ "static_source.S",
+ ":static_filegroup_as_srcs",
+ ],
+ static_srcs_c = [
+ "static_source.c",
+ ":static_filegroup_c_srcs",
+ ],
+)`},
+ })
+}
+
func TestCcLibraryNonConfiguredVersionScript(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
description: "cc_library non-configured version script",
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/build_test.bash b/build_test.bash
index 296a79c..b039285 100755
--- a/build_test.bash
+++ b/build_test.bash
@@ -54,7 +54,7 @@
echo
echo "Running Bazel smoke test..."
-"${TOP}/tools/bazel" --batch --max_idle_secs=1 info
+STANDALONE_BAZEL=true "${TOP}/tools/bazel" --batch --max_idle_secs=1 info
echo
echo "Running Soong test..."
diff --git a/cc/bp2build.go b/cc/bp2build.go
index fed9936..31e69d8 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -14,6 +14,7 @@
package cc
import (
+ "fmt"
"path/filepath"
"strings"
@@ -52,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 {
@@ -123,39 +95,21 @@
// 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)
- }
- }
- // arch: { <arch>: static: { ... } }
- for _, properties := range module.GetArchProperties(ctx, &StaticProperties{}) {
- if p, ok := properties.(*StaticProperties); ok {
- allDeps = appendDeps(allDeps, p.Static)
- }
- }
}
ctx.AddDependency(module, nil, android.SortedUniqueStrings(allDeps)...)
@@ -164,13 +118,86 @@
// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
// properties which apply to either the shared or static version of a cc_library module.
type staticOrSharedAttributes struct {
- copts bazel.StringListAttribute
- srcs bazel.LabelListAttribute
+ srcs bazel.LabelListAttribute
+ srcs_c bazel.LabelListAttribute
+ srcs_as bazel.LabelListAttribute
+
+ copts bazel.StringListAttribute
+
staticDeps bazel.LabelListAttribute
dynamicDeps bazel.LabelListAttribute
wholeArchiveDeps bazel.LabelListAttribute
}
+func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) {
+ // Branch srcs into three language-specific groups.
+ // C++ is the "catch-all" group, and comprises generated sources because we don't
+ // know the language of these sources until the genrule is executed.
+ // TODO(b/190006308): Handle language detection of sources in a Bazel rule.
+ isCSrcOrFilegroup := func(s string) bool {
+ return strings.HasSuffix(s, ".c") || strings.HasSuffix(s, "_c_srcs")
+ }
+
+ isAsmSrcOrFilegroup := func(s string) bool {
+ return strings.HasSuffix(s, ".S") || strings.HasSuffix(s, ".s") || strings.HasSuffix(s, "_as_srcs")
+ }
+
+ // Check that a module is a filegroup type named <label>.
+ isFilegroupNamed := func(m android.Module, fullLabel string) bool {
+ if ctx.OtherModuleType(m) != "filegroup" {
+ return false
+ }
+ labelParts := strings.Split(fullLabel, ":")
+ if len(labelParts) > 2 {
+ // There should not be more than one colon in a label.
+ panic(fmt.Errorf("%s is not a valid Bazel label for a filegroup", fullLabel))
+ } else {
+ return m.Name() == labelParts[len(labelParts)-1]
+ }
+ }
+
+ // Convert the filegroup dependencies into the extension-specific filegroups
+ // filtered in the filegroup.bzl macro.
+ cppFilegroup := func(label string) string {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if isFilegroupNamed(m, label) {
+ label = label + "_cpp_srcs"
+ return
+ }
+ })
+ return label
+ }
+ cFilegroup := func(label string) string {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if isFilegroupNamed(m, label) {
+ label = label + "_c_srcs"
+ return
+ }
+ })
+ return label
+ }
+ asFilegroup := func(label string) string {
+ ctx.VisitDirectDeps(func(m android.Module) {
+ if isFilegroupNamed(m, label) {
+ label = label + "_as_srcs"
+ return
+ }
+ })
+ return label
+ }
+
+ cSrcs = bazel.MapLabelListAttribute(srcs, cFilegroup)
+ cSrcs = bazel.FilterLabelListAttribute(cSrcs, isCSrcOrFilegroup)
+
+ asSrcs = bazel.MapLabelListAttribute(srcs, asFilegroup)
+ asSrcs = bazel.FilterLabelListAttribute(asSrcs, isAsmSrcOrFilegroup)
+
+ cppSrcs = bazel.MapLabelListAttribute(srcs, cppFilegroup)
+ cppSrcs = bazel.SubtractBazelLabelListAttribute(cppSrcs, cSrcs)
+ cppSrcs = bazel.SubtractBazelLabelListAttribute(cppSrcs, asSrcs)
+ return
+}
+
// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
func bp2BuildParseSharedProps(ctx android.TopDownMutatorContext, module *Module) staticOrSharedAttributes {
lib, ok := module.compiler.(*libraryDecorator)
@@ -201,70 +228,43 @@
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)
}
}
}
}
+ cppSrcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, attrs.srcs)
+ attrs.srcs = cppSrcs
+ attrs.srcs_c = cSrcs
+ attrs.srcs_as = asSrcs
+
return attrs
}
@@ -284,45 +284,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,
}
@@ -422,7 +400,7 @@
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)
@@ -445,65 +423,45 @@
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))
+ 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 {
+ srcsList := parseSrcs(baseCompilerProps)
+ srcs.SetSelectValue(axis, config, srcsList)
+ // The base srcs value should not contain any arch-specific excludes.
+ srcs.SetValue(bazel.SubtractBazelLabelList(srcs.Value, bazel.LabelList{Includes: srcsList.Excludes}))
+ }
+
+ 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))
+ }
}
}
// 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))
+ for axis, configToProps := range archVariantCompilerProps {
+ for config, props := range configToProps {
+ if _, ok := props.(*BaseCompilerProperties); ok {
+ // TODO: handle non-arch
+ srcs.SetSelectValue(axis, config, bazel.SubtractBazelLabelList(srcs.SelectValue(axis, config), 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
- if len(baseCompilerProps.Srcs) > 0 || len(baseCompilerProps.Exclude_srcs) > 0 {
- srcs.SetOsArchValueForTarget(os.Name, arch.Name, bazel.SubtractBazelLabelList(srcsList, baseSrcsLabelList))
- }
- 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))
- }
- }
+ for axis := range archVariantCompilerProps {
+ defaultsSrcs := bazel.SubtractBazelLabelList(baseSrcsLabelList, srcs.Value)
+ srcs.SetSelectValue(axis, bazel.ConditionsDefault, defaultsSrcs)
}
productVarPropNameToAttribute := map[string]*bazel.StringListAttribute{
@@ -520,28 +478,13 @@
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.ProductConfigVariable), prop.ProductConfigVariable, newFlags)
}
}
}
- // Branch srcs into three language-specific groups.
- // C++ is the "catch-all" group, and comprises generated sources because we don't
- // know the language of these sources until the genrule is executed.
- // TODO(b/): Handle language detection of sources in a Bazel rule.
- isCSrc := func(s string) bool {
- return strings.HasSuffix(s, ".c")
- }
- isAsmSrc := func(s string) bool {
- return strings.HasSuffix(s, ".S") || strings.HasSuffix(s, ".s")
- }
- cSrcs := bazel.FilterLabelListAttribute(srcs, isCSrc)
- asSrcs := bazel.FilterLabelListAttribute(srcs, isAsmSrc)
- srcs = bazel.SubtractBazelLabelListAttribute(srcs, cSrcs)
- srcs = bazel.SubtractBazelLabelListAttribute(srcs, asSrcs)
+ srcs, cSrcs, asSrcs := groupSrcsByExtension(ctx, srcs)
+
return compilerAttributes{
copts: copts,
srcs: srcs,
@@ -600,7 +543,7 @@
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
@@ -610,61 +553,23 @@
}
}
- 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))
-
- if baseLinkerProps.Version_script != nil {
- versionScript.SetValueForArch(arch.Name,
- android.BazelLabelForModuleSrcSingle(ctx, *baseLinkerProps.Version_script))
- }
-
- 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 {
+ for axis, configToProps := range module.GetArchVariantProperties(ctx, &BaseLinkerProperties{}) {
+ for config, props := range configToProps {
+ if baseLinkerProps, ok := props.(*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))
+ deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, libs))
+ exportedDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, exportedLibs))
+ linkopts.SetSelectValue(axis, config, getBp2BuildLinkerFlags(baseLinkerProps))
+ wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, wholeArchiveLibs))
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))
+ dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, sharedLibs))
}
}
}
@@ -733,27 +638,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 e4a52f1..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()),
@@ -2134,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"},
@@ -2154,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"},
@@ -2168,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
@@ -2200,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 {
@@ -2214,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{
@@ -2239,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)
@@ -2846,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(
@@ -2864,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:
@@ -2933,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)
@@ -2942,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
@@ -2950,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 aec2e4d..0ff78a5 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -221,25 +221,29 @@
// For bp2build conversion.
type bazelCcLibraryAttributes struct {
// Attributes pertaining to both static and shared variants.
- Srcs bazel.LabelListAttribute
+ Srcs bazel.LabelListAttribute
+ Srcs_c bazel.LabelListAttribute
+ Srcs_as bazel.LabelListAttribute
+
+ Copts bazel.StringListAttribute
+ Cppflags bazel.StringListAttribute
+ Conlyflags bazel.StringListAttribute
+ Asflags bazel.StringListAttribute
+
Hdrs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
- Copts bazel.StringListAttribute
Includes bazel.StringListAttribute
Linkopts bazel.StringListAttribute
- Cppflags bazel.StringListAttribute
- Srcs_c bazel.LabelListAttribute
- Conlyflags bazel.StringListAttribute
- Srcs_as bazel.LabelListAttribute
- Asflags bazel.StringListAttribute
-
// Attributes pertaining to shared variant.
- Shared_copts bazel.StringListAttribute
- Shared_srcs bazel.LabelListAttribute
+ Shared_srcs bazel.LabelListAttribute
+ Shared_srcs_c bazel.LabelListAttribute
+ Shared_srcs_as bazel.LabelListAttribute
+ Shared_copts bazel.StringListAttribute
+
Exported_deps_for_shared bazel.LabelListAttribute
Static_deps_for_shared bazel.LabelListAttribute
Dynamic_deps_for_shared bazel.LabelListAttribute
@@ -248,8 +252,11 @@
Version_script bazel.LabelAttribute
// Attributes pertaining to static variant.
- Static_copts bazel.StringListAttribute
- Static_srcs bazel.LabelListAttribute
+ Static_srcs bazel.LabelListAttribute
+ Static_srcs_c bazel.LabelListAttribute
+ Static_srcs_as bazel.LabelListAttribute
+ Static_copts bazel.StringListAttribute
+
Exported_deps_for_static bazel.LabelListAttribute
Static_deps_for_static bazel.LabelListAttribute
Dynamic_deps_for_static bazel.LabelListAttribute
@@ -298,33 +305,38 @@
linkerAttrs := bp2BuildParseLinkerProps(ctx, m)
exportedIncludes := bp2BuildParseExportedIncludes(ctx, m)
- var srcs bazel.LabelListAttribute
- srcs.Append(compilerAttrs.srcs)
+ srcs := compilerAttrs.srcs
attrs := &bazelCcLibraryAttributes{
- Srcs: srcs,
+ Srcs: srcs,
+ Srcs_c: compilerAttrs.cSrcs,
+ Srcs_as: compilerAttrs.asSrcs,
+
+ Copts: compilerAttrs.copts,
+ Cppflags: compilerAttrs.cppFlags,
+ Conlyflags: compilerAttrs.conlyFlags,
+ Asflags: compilerAttrs.asFlags,
+
Implementation_deps: linkerAttrs.deps,
Deps: linkerAttrs.exportedDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
- Copts: compilerAttrs.copts,
Includes: exportedIncludes,
Linkopts: linkerAttrs.linkopts,
- Cppflags: compilerAttrs.cppFlags,
- Srcs_c: compilerAttrs.cSrcs,
- Conlyflags: compilerAttrs.conlyFlags,
- Srcs_as: compilerAttrs.asSrcs,
- Asflags: compilerAttrs.asFlags,
- Shared_copts: sharedAttrs.copts,
Shared_srcs: sharedAttrs.srcs,
+ Shared_srcs_c: sharedAttrs.srcs_c,
+ Shared_srcs_as: sharedAttrs.srcs_as,
+ Shared_copts: sharedAttrs.copts,
Static_deps_for_shared: sharedAttrs.staticDeps,
Whole_archive_deps_for_shared: sharedAttrs.wholeArchiveDeps,
Dynamic_deps_for_shared: sharedAttrs.dynamicDeps,
Version_script: linkerAttrs.versionScript,
- Static_copts: staticAttrs.copts,
Static_srcs: staticAttrs.srcs,
+ Static_srcs_c: staticAttrs.srcs_c,
+ Static_srcs_as: staticAttrs.srcs_as,
+ Static_copts: staticAttrs.copts,
Static_deps_for_static: staticAttrs.staticDeps,
Whole_archive_deps_for_static: staticAttrs.wholeArchiveDeps,
Dynamic_deps_for_static: staticAttrs.dynamicDeps,
@@ -350,6 +362,7 @@
staticLibrarySdkMemberType,
staticAndSharedLibrarySdkMemberType,
}
+ module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -358,7 +371,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()
}
@@ -543,13 +556,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 {
@@ -559,18 +576,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))
@@ -606,20 +618,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()) {
@@ -635,7 +641,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, "/") {
@@ -653,7 +659,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 {
@@ -666,7 +672,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
@@ -679,15 +685,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
}
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 a7351a9..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,69 +428,88 @@
// }
//
// 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) {
- coreVariations := append(ctx.Target().Variations(), blueprint.Variation{
+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.
+ variations := append(ctx.Target().Variations(), blueprint.Variation{
Mutator: "image",
Variation: android.CoreVariation})
- if ctx.OtherModuleFarDependencyVariantExists(coreVariations, ctx.Module().(*Module).BaseModuleName()) {
+ if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
return
}
- // If there is no matching core variation, there could still be a
- // product variation, for example if a module is product specific and
- // vendor available. In that case, we also want to add the androidmk
- // suffix.
-
- productVariations := append(ctx.Target().Variations(), blueprint.Variation{
+ variations = append(ctx.Target().Variations(), blueprint.Variation{
Mutator: "image",
Variation: ProductVariationPrefix + ctx.DeviceConfig().PlatformVndkVersion()})
- if ctx.OtherModuleFarDependencyVariantExists(productVariations, ctx.Module().(*Module).BaseModuleName()) {
+ if ctx.OtherModuleFarDependencyVariantExists(variations, ctx.Module().(LinkableInterface).BaseModuleName()) {
p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
return
}
+ images := []SnapshotImage{VendorSnapshotImageSingleton, recoverySnapshotImageSingleton}
+
+ for _, image := range images {
+ if p.image == image {
+ continue
+ }
+ variations = append(ctx.Target().Variations(), blueprint.Variation{
+ Mutator: "image",
+ Variation: image.imageVariantName(ctx.DeviceConfig())})
+
+ if ctx.OtherModuleFarDependencyVariantExists(variations,
+ ctx.Module().(LinkableInterface).BaseModuleName()+
+ getSnapshotNameSuffix(
+ image.moduleNameSuffix()+variant,
+ p.Version(),
+ ctx.DeviceConfig().Arches()[0].ArchType.String())) {
+ p.baseProperties.Androidmk_suffix = p.image.moduleNameSuffix()
+ return
+ }
+ }
+
p.baseProperties.Androidmk_suffix = ""
}
// 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)
@@ -493,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
}
@@ -509,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"`
@@ -535,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"`
}
}
@@ -551,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 {
@@ -566,7 +593,16 @@
// As snapshots are prebuilts, this just returns the prebuilt binary after doing things which are
// done by normal library decorator, e.g. exporting flags.
func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
- p.setSnapshotAndroidMkSuffix(ctx)
+ var variant string
+ if p.shared() {
+ variant = SnapshotSharedSuffix
+ } else if p.static() {
+ variant = SnapshotStaticSuffix
+ } else {
+ variant = snapshotHeaderSuffix
+ }
+
+ p.SetSnapshotAndroidMkSuffix(ctx, variant)
if p.header() {
return p.libraryDecorator.link(ctx, flags, deps, objs)
@@ -576,7 +612,7 @@
p.properties = p.sanitizerProperties.Cfi
}
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
@@ -629,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)
}
}
@@ -659,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
@@ -682,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,
@@ -696,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()
}
@@ -706,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()
}
@@ -716,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()
}
@@ -726,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()
}
@@ -736,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()
}
@@ -766,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 {
@@ -784,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)
+ p.SetSnapshotAndroidMkSuffix(ctx, snapshotBinarySuffix)
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
@@ -814,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
@@ -824,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)
@@ -843,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()
}
@@ -861,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 {
@@ -879,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)
+ p.SetSnapshotAndroidMkSuffix(ctx, snapshotObjectSuffix)
- if !p.matchesWithDevice(ctx.DeviceConfig()) {
+ if !p.MatchesWithDevice(ctx.DeviceConfig()) {
return nil
}
@@ -905,7 +941,7 @@
}
module.linker = prebuilt
- prebuilt.init(module, vendorSnapshotImageSingleton, snapshotObjectSuffix)
+ prebuilt.Init(module, VendorSnapshotImageSingleton, snapshotObjectSuffix)
module.AddProperties(&prebuilt.properties)
return module.Init()
}
@@ -923,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/java_test.go b/java/java_test.go
index 1b8aec2..bd373c1 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -19,7 +19,6 @@
"os"
"path/filepath"
"reflect"
- "regexp"
"runtime"
"strconv"
"strings"
@@ -655,306 +654,6 @@
})
}
-func TestJavaSdkLibraryImport(t *testing.T) {
- result := prepareForJavaTest.RunTestWithBp(t, `
- java_library {
- name: "foo",
- srcs: ["a.java"],
- libs: ["sdklib"],
- sdk_version: "current",
- }
-
- java_library {
- name: "foo.system",
- srcs: ["a.java"],
- libs: ["sdklib"],
- sdk_version: "system_current",
- }
-
- java_library {
- name: "foo.test",
- srcs: ["a.java"],
- libs: ["sdklib"],
- sdk_version: "test_current",
- }
-
- java_sdk_library_import {
- name: "sdklib",
- public: {
- jars: ["a.jar"],
- },
- system: {
- jars: ["b.jar"],
- },
- test: {
- jars: ["c.jar"],
- stub_srcs: ["c.java"],
- },
- }
- `)
-
- for _, scope := range []string{"", ".system", ".test"} {
- fooModule := result.ModuleForTests("foo"+scope, "android_common")
- javac := fooModule.Rule("javac")
-
- sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Rule("combineJar").Output
- android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], sdklibStubsJar.String())
- }
-
- CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
- `prebuilt_sdklib.stubs`,
- `prebuilt_sdklib.stubs.source.test`,
- `prebuilt_sdklib.stubs.system`,
- `prebuilt_sdklib.stubs.test`,
- })
-}
-
-func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("sdklib"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "sdklib",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "none",
- public: {
- enabled: true,
- },
- }
-
- java_sdk_library_import {
- name: "sdklib",
- public: {
- jars: ["a.jar"],
- },
- }
- `)
-
- CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
- `dex2oatd`,
- `prebuilt_sdklib`,
- `sdklib.impl`,
- `sdklib.stubs`,
- `sdklib.stubs.source`,
- `sdklib.xml`,
- })
-
- CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
- `prebuilt_sdklib.stubs`,
- `sdklib.impl`,
- // This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
- // dependency is added after prebuilts may have been renamed and so has to use
- // the renamed name.
- `sdklib.xml`,
- })
-}
-
-func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("sdklib"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "sdklib",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "none",
- public: {
- enabled: true,
- },
- }
-
- java_sdk_library_import {
- name: "sdklib",
- prefer: true,
- public: {
- jars: ["a.jar"],
- },
- }
- `)
-
- CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
- `dex2oatd`,
- `prebuilt_sdklib`,
- `sdklib.impl`,
- `sdklib.stubs`,
- `sdklib.stubs.source`,
- `sdklib.xml`,
- })
-
- CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
- `prebuilt_sdklib.stubs`,
- `sdklib.impl`,
- `sdklib.xml`,
- })
-}
-
-func TestJavaSdkLibraryEnforce(t *testing.T) {
- partitionToBpOption := func(partition string) string {
- switch partition {
- case "system":
- return ""
- case "vendor":
- return "soc_specific: true,"
- case "product":
- return "product_specific: true,"
- default:
- panic("Invalid partition group name: " + partition)
- }
- }
-
- type testConfigInfo struct {
- libraryType string
- fromPartition string
- toPartition string
- enforceVendorInterface bool
- enforceProductInterface bool
- enforceJavaSdkLibraryCheck bool
- allowList []string
- }
-
- createPreparer := func(info testConfigInfo) android.FixturePreparer {
- bpFileTemplate := `
- java_library {
- name: "foo",
- srcs: ["foo.java"],
- libs: ["bar"],
- sdk_version: "current",
- %s
- }
-
- %s {
- name: "bar",
- srcs: ["bar.java"],
- sdk_version: "current",
- %s
- }
- `
-
- bpFile := fmt.Sprintf(bpFileTemplate,
- partitionToBpOption(info.fromPartition),
- info.libraryType,
- partitionToBpOption(info.toPartition))
-
- return android.GroupFixturePreparers(
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("bar"),
- android.FixtureWithRootAndroidBp(bpFile),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
- if info.enforceVendorInterface {
- variables.DeviceVndkVersion = proptools.StringPtr("current")
- }
- variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
- variables.InterPartitionJavaLibraryAllowList = info.allowList
- }),
- )
- }
-
- runTest := func(t *testing.T, info testConfigInfo, expectedErrorPattern string) {
- t.Run(fmt.Sprintf("%v", info), func(t *testing.T) {
- errorHandler := android.FixtureExpectsNoErrors
- if expectedErrorPattern != "" {
- errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
- }
- android.GroupFixturePreparers(
- prepareForJavaTest,
- createPreparer(info),
- ).
- ExtendWithErrorHandler(errorHandler).
- RunTest(t)
- })
- }
-
- errorMessage := "is not allowed across the partitions"
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: false,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: false,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "product",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- allowList: []string{"bar"},
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_library",
- fromPartition: "vendor",
- toPartition: "product",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, errorMessage)
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "product",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "vendor",
- toPartition: "system",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-
- runTest(t, testConfigInfo{
- libraryType: "java_sdk_library",
- fromPartition: "vendor",
- toPartition: "product",
- enforceVendorInterface: true,
- enforceProductInterface: true,
- enforceJavaSdkLibraryCheck: true,
- }, "")
-}
-
func TestDefaults(t *testing.T) {
ctx, _ := testJava(t, `
java_defaults {
@@ -1411,521 +1110,6 @@
})
}
-func TestJavaSdkLibrary(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithPrebuiltApis(map[string][]string{
- "28": {"foo"},
- "29": {"foo"},
- "30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"},
- }),
- ).RunTestWithBp(t, `
- droiddoc_exported_dir {
- name: "droiddoc-templates-sdk",
- path: ".",
- }
- java_sdk_library {
- name: "foo",
- srcs: ["a.java", "b.java"],
- api_packages: ["foo"],
- }
- java_sdk_library {
- name: "bar",
- srcs: ["a.java", "b.java"],
- api_packages: ["bar"],
- }
- java_library {
- name: "baz",
- srcs: ["c.java"],
- libs: ["foo", "bar.stubs"],
- sdk_version: "system_current",
- }
- java_sdk_library {
- name: "barney",
- srcs: ["c.java"],
- api_only: true,
- }
- java_sdk_library {
- name: "betty",
- srcs: ["c.java"],
- shared_library: false,
- }
- java_sdk_library_import {
- name: "quuz",
- public: {
- jars: ["c.jar"],
- },
- }
- java_sdk_library_import {
- name: "fred",
- public: {
- jars: ["b.jar"],
- },
- }
- java_sdk_library_import {
- name: "wilma",
- public: {
- jars: ["b.jar"],
- },
- shared_library: false,
- }
- java_library {
- name: "qux",
- srcs: ["c.java"],
- libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"],
- sdk_version: "system_current",
- }
- java_library {
- name: "baz-test",
- srcs: ["c.java"],
- libs: ["foo"],
- sdk_version: "test_current",
- }
- java_library {
- name: "baz-29",
- srcs: ["c.java"],
- libs: ["foo"],
- sdk_version: "system_29",
- }
- java_library {
- name: "baz-module-30",
- srcs: ["c.java"],
- libs: ["foo"],
- sdk_version: "module_30",
- }
- `)
-
- // check the existence of the internal modules
- result.ModuleForTests("foo", "android_common")
- result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
- result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common")
- result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
- result.ModuleForTests("foo.api.public.28", "")
- result.ModuleForTests("foo.api.system.28", "")
- result.ModuleForTests("foo.api.test.28", "")
-
- bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
- // tests if baz is actually linked to the stubs lib
- android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar")
- // ... and not to the impl lib
- android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.jar")
- // test if baz is not linked to the system variant of foo
- android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.jar")
-
- bazTestJavac := result.ModuleForTests("baz-test", "android_common").Rule("javac")
- // tests if baz-test is actually linked to the test stubs lib
- android.AssertStringDoesContain(t, "baz-test javac classpath", bazTestJavac.Args["classpath"], "foo.stubs.test.jar")
-
- baz29Javac := result.ModuleForTests("baz-29", "android_common").Rule("javac")
- // tests if baz-29 is actually linked to the system 29 stubs lib
- android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/29/system/foo.jar")
-
- bazModule30Javac := result.ModuleForTests("baz-module-30", "android_common").Rule("javac")
- // tests if "baz-module-30" is actually linked to the module 30 stubs lib
- android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar")
-
- // test if baz has exported SDK lib names foo and bar to qux
- qux := result.ModuleForTests("qux", "android_common")
- if quxLib, ok := qux.Module().(*Library); ok {
- sdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
- android.AssertDeepEquals(t, "qux exports", []string{"foo", "bar", "fred", "quuz"}, sdkLibs)
- }
-}
-
-func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("sdklib"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "sdklib",
- srcs: ["a.java"],
- libs: ["lib"],
- static_libs: ["static-lib"],
- impl_only_libs: ["impl-only-lib"],
- stub_only_libs: ["stub-only-lib"],
- stub_only_static_libs: ["stub-only-static-lib"],
- }
- java_defaults {
- name: "defaults",
- srcs: ["a.java"],
- sdk_version: "current",
- }
- java_library { name: "lib", defaults: ["defaults"] }
- java_library { name: "static-lib", defaults: ["defaults"] }
- java_library { name: "impl-only-lib", defaults: ["defaults"] }
- java_library { name: "stub-only-lib", defaults: ["defaults"] }
- java_library { name: "stub-only-static-lib", defaults: ["defaults"] }
- `)
- var expectations = []struct {
- lib string
- on_impl_classpath bool
- on_stub_classpath bool
- in_impl_combined bool
- in_stub_combined bool
- }{
- {lib: "lib", on_impl_classpath: true},
- {lib: "static-lib", in_impl_combined: true},
- {lib: "impl-only-lib", on_impl_classpath: true},
- {lib: "stub-only-lib", on_stub_classpath: true},
- {lib: "stub-only-static-lib", in_stub_combined: true},
- }
- verify := func(sdklib, dep string, cp, combined bool) {
- sdklibCp := result.ModuleForTests(sdklib, "android_common").Rule("javac").Args["classpath"]
- expected := cp || combined // Every combined jar is also on the classpath.
- android.AssertStringContainsEquals(t, "bad classpath for "+sdklib, sdklibCp, "/"+dep+".jar", expected)
-
- combineJarInputs := result.ModuleForTests(sdklib, "android_common").Rule("combineJar").Inputs.Strings()
- depPath := filepath.Join("out", "soong", ".intermediates", dep, "android_common", "turbine-combined", dep+".jar")
- android.AssertStringListContainsEquals(t, "bad combined inputs for "+sdklib, combineJarInputs, depPath, combined)
- }
- for _, expectation := range expectations {
- verify("sdklib", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
- verify("sdklib.impl", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
-
- stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
- verify(stubName, expectation.lib, expectation.on_stub_classpath, expectation.in_stub_combined)
- }
-}
-
-func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- api_only: true,
- public: {
- enabled: true,
- },
- }
-
- java_library {
- name: "bar",
- srcs: ["b.java"],
- libs: ["foo"],
- }
- `)
-
- // The bar library should depend on the stubs jar.
- barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
- t.Errorf("expected %q, found %#q", expected, actual)
- }
-}
-
-func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- api_packages: ["foo"],
- public: {
- enabled: true,
- },
- }
-
- java_library {
- name: "bar",
- srcs: ["b.java", ":foo{.public.stubs.source}"],
- }
- `)
-}
-
-func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"foo" does not provide api scope system`)).
- RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- api_packages: ["foo"],
- public: {
- enabled: true,
- },
- }
-
- java_library {
- name: "bar",
- srcs: ["b.java", ":foo{.system.stubs.source}"],
- }
- `)
-}
-
-func TestJavaSdkLibrary_Deps(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("sdklib"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "sdklib",
- srcs: ["a.java"],
- sdk_version: "none",
- system_modules: "none",
- public: {
- enabled: true,
- },
- }
- `)
-
- CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
- `dex2oatd`,
- `sdklib.impl`,
- `sdklib.stubs`,
- `sdklib.stubs.source`,
- `sdklib.xml`,
- })
-}
-
-func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
- prepareForJavaTest.RunTestWithBp(t, `
- java_sdk_library_import {
- name: "foo",
- public: {
- jars: ["a.jar"],
- stub_srcs: ["a.java"],
- current_api: "api/current.txt",
- removed_api: "api/removed.txt",
- },
- }
-
- java_library {
- name: "bar",
- srcs: [":foo{.public.stubs.source}"],
- java_resources: [
- ":foo{.public.api.txt}",
- ":foo{.public.removed-api.txt}",
- ],
- }
- `)
-}
-
-func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
- bp := `
- java_sdk_library_import {
- name: "foo",
- public: {
- jars: ["a.jar"],
- },
- }
- `
-
- t.Run("stubs.source", func(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`stubs.source not available for api scope public`)).
- RunTestWithBp(t, bp+`
- java_library {
- name: "bar",
- srcs: [":foo{.public.stubs.source}"],
- java_resources: [
- ":foo{.public.api.txt}",
- ":foo{.public.removed-api.txt}",
- ],
- }
- `)
- })
-
- t.Run("api.txt", func(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`api.txt not available for api scope public`)).
- RunTestWithBp(t, bp+`
- java_library {
- name: "bar",
- srcs: ["a.java"],
- java_resources: [
- ":foo{.public.api.txt}",
- ],
- }
- `)
- })
-
- t.Run("removed-api.txt", func(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`removed-api.txt not available for api scope public`)).
- RunTestWithBp(t, bp+`
- java_library {
- name: "bar",
- srcs: ["a.java"],
- java_resources: [
- ":foo{.public.removed-api.txt}",
- ],
- }
- `)
- })
-}
-
-func TestJavaSdkLibrary_InvalidScopes(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": enabled api scope "system" depends on disabled scope "public"`)).
- RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java", "b.java"],
- api_packages: ["foo"],
- // Explicitly disable public to test the check that ensures the set of enabled
- // scopes is consistent.
- public: {
- enabled: false,
- },
- system: {
- enabled: true,
- },
- }
- `)
-}
-
-func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java", "b.java"],
- api_packages: ["foo"],
- system: {
- enabled: true,
- sdk_version: "module_current",
- },
- }
- `)
-}
-
-func TestJavaSdkLibrary_ModuleLib(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java", "b.java"],
- api_packages: ["foo"],
- system: {
- enabled: true,
- },
- module_lib: {
- enabled: true,
- },
- }
- `)
-}
-
-func TestJavaSdkLibrary_SystemServer(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java", "b.java"],
- api_packages: ["foo"],
- system: {
- enabled: true,
- },
- system_server: {
- enabled: true,
- },
- }
- `)
-}
-
-func TestJavaSdkLibrary_MissingScope(t *testing.T) {
- prepareForJavaTest.
- ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).
- RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- public: {
- enabled: false,
- },
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- sdk_version: "module_current",
- }
- `)
-}
-
-func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
- android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- system: {
- enabled: true,
- },
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- // foo does not have module-lib scope so it should fallback to system
- sdk_version: "module_current",
- }
- `)
-}
-
-func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- PrepareForTestWithJavaSdkLibraryFiles,
- FixtureWithLastReleaseApis("foo"),
- ).RunTestWithBp(t, `
- java_sdk_library {
- name: "foo",
- srcs: ["a.java"],
- system: {
- enabled: true,
- },
- default_to_stubs: true,
- }
-
- java_library {
- name: "baz",
- srcs: ["a.java"],
- libs: ["foo"],
- // does not have sdk_version set, should fallback to module,
- // which will then fallback to system because the module scope
- // is not enabled.
- }
- `)
- // The baz library should depend on the system stubs jar.
- bazLibrary := result.ModuleForTests("baz", "android_common").Rule("javac")
- if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
- t.Errorf("expected %q, found %#q", expected, actual)
- }
-}
-
var compilerFlagsTestCases = []struct {
in string
out bool
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 8f36758..ecf2b1a 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -457,6 +457,11 @@
// * API incompatibilities baseline filegroup -> <dist-stem>-incompatibilities.api.<scope>.latest
Dist_stem *string
+ // The subdirectory for the artifacts that are copied to the dist directory. If not specified
+ // then defaults to "android". Should be set to "android" for anything that should be published
+ // in the public Android SDK.
+ Dist_group *string
+
// A compatibility mode that allows historical API-tracking files to not exist.
// Do not use.
Unsafe_ignore_missing_latest_api bool
@@ -1198,12 +1203,10 @@
// The dist path of the stub artifacts
func (module *SdkLibrary) apiDistPath(apiScope *apiScope) string {
- if module.ModuleBase.Owner() != "" {
- return path.Join("apistubs", module.ModuleBase.Owner(), apiScope.name)
- } else if Bool(module.sdkLibraryProperties.Core_lib) {
+ if Bool(module.sdkLibraryProperties.Core_lib) {
return path.Join("apistubs", "core", apiScope.name)
} else {
- return path.Join("apistubs", "android", apiScope.name)
+ return path.Join("apistubs", module.distGroup(), apiScope.name)
}
}
@@ -1228,6 +1231,19 @@
return proptools.StringDefault(module.sdkLibraryProperties.Dist_stem, module.BaseModuleName())
}
+// distGroup returns the subdirectory of the dist path of the stub artifacts.
+func (module *SdkLibrary) distGroup() string {
+ if group := proptools.String(module.sdkLibraryProperties.Dist_group); group != "" {
+ return group
+ }
+ // TODO(b/186723288): Remove this once everything uses dist_group.
+ if owner := module.ModuleBase.Owner(); owner != "" {
+ return owner
+ }
+ // TODO(b/186723288): Make this "unknown".
+ return "android"
+}
+
func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
return ":" + module.distStem() + ".api." + apiScope.name + ".latest"
}
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
new file mode 100644
index 0000000..0fe6e72
--- /dev/null
+++ b/java/sdk_library_test.go
@@ -0,0 +1,931 @@
+// 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 java
+
+import (
+ "android/soong/android"
+ "fmt"
+ "path/filepath"
+ "regexp"
+ "testing"
+
+ "github.com/google/blueprint/proptools"
+)
+
+func TestJavaSdkLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "28": {"foo"},
+ "29": {"foo"},
+ "30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"},
+ }),
+ ).RunTestWithBp(t, `
+ droiddoc_exported_dir {
+ name: "droiddoc-templates-sdk",
+ path: ".",
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ }
+ java_sdk_library {
+ name: "bar",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["bar"],
+ }
+ java_library {
+ name: "baz",
+ srcs: ["c.java"],
+ libs: ["foo", "bar.stubs"],
+ sdk_version: "system_current",
+ }
+ java_sdk_library {
+ name: "barney",
+ srcs: ["c.java"],
+ api_only: true,
+ }
+ java_sdk_library {
+ name: "betty",
+ srcs: ["c.java"],
+ shared_library: false,
+ }
+ java_sdk_library_import {
+ name: "quuz",
+ public: {
+ jars: ["c.jar"],
+ },
+ }
+ java_sdk_library_import {
+ name: "fred",
+ public: {
+ jars: ["b.jar"],
+ },
+ }
+ java_sdk_library_import {
+ name: "wilma",
+ public: {
+ jars: ["b.jar"],
+ },
+ shared_library: false,
+ }
+ java_library {
+ name: "qux",
+ srcs: ["c.java"],
+ libs: ["baz", "fred", "quuz.stubs", "wilma", "barney", "betty"],
+ sdk_version: "system_current",
+ }
+ java_library {
+ name: "baz-test",
+ srcs: ["c.java"],
+ libs: ["foo"],
+ sdk_version: "test_current",
+ }
+ java_library {
+ name: "baz-29",
+ srcs: ["c.java"],
+ libs: ["foo"],
+ sdk_version: "system_29",
+ }
+ java_library {
+ name: "baz-module-30",
+ srcs: ["c.java"],
+ libs: ["foo"],
+ sdk_version: "module_30",
+ }
+ `)
+
+ // check the existence of the internal modules
+ result.ModuleForTests("foo", "android_common")
+ result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
+ result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common")
+ result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
+ result.ModuleForTests("foo.api.public.28", "")
+ result.ModuleForTests("foo.api.system.28", "")
+ result.ModuleForTests("foo.api.test.28", "")
+
+ bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
+ // tests if baz is actually linked to the stubs lib
+ android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar")
+ // ... and not to the impl lib
+ android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.jar")
+ // test if baz is not linked to the system variant of foo
+ android.AssertStringDoesNotContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.jar")
+
+ bazTestJavac := result.ModuleForTests("baz-test", "android_common").Rule("javac")
+ // tests if baz-test is actually linked to the test stubs lib
+ android.AssertStringDoesContain(t, "baz-test javac classpath", bazTestJavac.Args["classpath"], "foo.stubs.test.jar")
+
+ baz29Javac := result.ModuleForTests("baz-29", "android_common").Rule("javac")
+ // tests if baz-29 is actually linked to the system 29 stubs lib
+ android.AssertStringDoesContain(t, "baz-29 javac classpath", baz29Javac.Args["classpath"], "prebuilts/sdk/29/system/foo.jar")
+
+ bazModule30Javac := result.ModuleForTests("baz-module-30", "android_common").Rule("javac")
+ // tests if "baz-module-30" is actually linked to the module 30 stubs lib
+ android.AssertStringDoesContain(t, "baz-module-30 javac classpath", bazModule30Javac.Args["classpath"], "prebuilts/sdk/30/module-lib/foo.jar")
+
+ // test if baz has exported SDK lib names foo and bar to qux
+ qux := result.ModuleForTests("qux", "android_common")
+ if quxLib, ok := qux.Module().(*Library); ok {
+ sdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
+ android.AssertDeepEquals(t, "qux exports", []string{"foo", "bar", "fred", "quuz"}, sdkLibs)
+ }
+}
+
+func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ libs: ["lib"],
+ static_libs: ["static-lib"],
+ impl_only_libs: ["impl-only-lib"],
+ stub_only_libs: ["stub-only-lib"],
+ stub_only_static_libs: ["stub-only-static-lib"],
+ }
+ java_defaults {
+ name: "defaults",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ }
+ java_library { name: "lib", defaults: ["defaults"] }
+ java_library { name: "static-lib", defaults: ["defaults"] }
+ java_library { name: "impl-only-lib", defaults: ["defaults"] }
+ java_library { name: "stub-only-lib", defaults: ["defaults"] }
+ java_library { name: "stub-only-static-lib", defaults: ["defaults"] }
+ `)
+ var expectations = []struct {
+ lib string
+ on_impl_classpath bool
+ on_stub_classpath bool
+ in_impl_combined bool
+ in_stub_combined bool
+ }{
+ {lib: "lib", on_impl_classpath: true},
+ {lib: "static-lib", in_impl_combined: true},
+ {lib: "impl-only-lib", on_impl_classpath: true},
+ {lib: "stub-only-lib", on_stub_classpath: true},
+ {lib: "stub-only-static-lib", in_stub_combined: true},
+ }
+ verify := func(sdklib, dep string, cp, combined bool) {
+ sdklibCp := result.ModuleForTests(sdklib, "android_common").Rule("javac").Args["classpath"]
+ expected := cp || combined // Every combined jar is also on the classpath.
+ android.AssertStringContainsEquals(t, "bad classpath for "+sdklib, sdklibCp, "/"+dep+".jar", expected)
+
+ combineJarInputs := result.ModuleForTests(sdklib, "android_common").Rule("combineJar").Inputs.Strings()
+ depPath := filepath.Join("out", "soong", ".intermediates", dep, "android_common", "turbine-combined", dep+".jar")
+ android.AssertStringListContainsEquals(t, "bad combined inputs for "+sdklib, combineJarInputs, depPath, combined)
+ }
+ for _, expectation := range expectations {
+ verify("sdklib", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
+ verify("sdklib.impl", expectation.lib, expectation.on_impl_classpath, expectation.in_impl_combined)
+
+ stubName := apiScopePublic.stubsLibraryModuleName("sdklib")
+ verify(stubName, expectation.lib, expectation.on_stub_classpath, expectation.in_stub_combined)
+ }
+}
+
+func TestJavaSdkLibrary_DoNotAccessImplWhenItIsNotBuilt(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ api_only: true,
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ libs: ["foo"],
+ }
+ `)
+
+ // The bar library should depend on the stubs jar.
+ barLibrary := result.ModuleForTests("bar", "android_common").Rule("javac")
+ if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs\.jar$`, barLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ t.Errorf("expected %q, found %#q", expected, actual)
+ }
+}
+
+func TestJavaSdkLibrary_UseSourcesFromAnotherSdkLibrary(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java", ":foo{.public.stubs.source}"],
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_AccessOutputFiles_MissingScope(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`"foo" does not provide api scope system`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ api_packages: ["foo"],
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java", ":foo{.system.stubs.source}"],
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_Deps(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+ `)
+
+ CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
+ `dex2oatd`,
+ `sdklib.impl`,
+ `sdklib.stubs`,
+ `sdklib.stubs.source`,
+ `sdklib.xml`,
+ })
+}
+
+func TestJavaSdkLibraryImport_AccessOutputFiles(t *testing.T) {
+ prepareForJavaTest.RunTestWithBp(t, `
+ java_sdk_library_import {
+ name: "foo",
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "api/current.txt",
+ removed_api: "api/removed.txt",
+ },
+ }
+
+ java_library {
+ name: "bar",
+ srcs: [":foo{.public.stubs.source}"],
+ java_resources: [
+ ":foo{.public.api.txt}",
+ ":foo{.public.removed-api.txt}",
+ ],
+ }
+ `)
+}
+
+func TestJavaSdkLibraryImport_AccessOutputFiles_Invalid(t *testing.T) {
+ bp := `
+ java_sdk_library_import {
+ name: "foo",
+ public: {
+ jars: ["a.jar"],
+ },
+ }
+ `
+
+ t.Run("stubs.source", func(t *testing.T) {
+ prepareForJavaTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`stubs.source not available for api scope public`)).
+ RunTestWithBp(t, bp+`
+ java_library {
+ name: "bar",
+ srcs: [":foo{.public.stubs.source}"],
+ java_resources: [
+ ":foo{.public.api.txt}",
+ ":foo{.public.removed-api.txt}",
+ ],
+ }
+ `)
+ })
+
+ t.Run("api.txt", func(t *testing.T) {
+ prepareForJavaTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`api.txt not available for api scope public`)).
+ RunTestWithBp(t, bp+`
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ java_resources: [
+ ":foo{.public.api.txt}",
+ ],
+ }
+ `)
+ })
+
+ t.Run("removed-api.txt", func(t *testing.T) {
+ prepareForJavaTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`removed-api.txt not available for api scope public`)).
+ RunTestWithBp(t, bp+`
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ java_resources: [
+ ":foo{.public.removed-api.txt}",
+ ],
+ }
+ `)
+ })
+}
+
+func TestJavaSdkLibrary_InvalidScopes(t *testing.T) {
+ prepareForJavaTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "foo": enabled api scope "system" depends on disabled scope "public"`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ // Explicitly disable public to test the check that ensures the set of enabled
+ // scopes is consistent.
+ public: {
+ enabled: false,
+ },
+ system: {
+ enabled: true,
+ },
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_SdkVersion_ForScope(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ sdk_version: "module_current",
+ },
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_ModuleLib(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_SystemServer(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ system_server: {
+ enabled: true,
+ },
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_MissingScope(t *testing.T) {
+ prepareForJavaTest.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`requires api scope module-lib from foo but it only has \[\] available`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: false,
+ },
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["a.java"],
+ libs: ["foo"],
+ sdk_version: "module_current",
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_FallbackScope(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ system: {
+ enabled: true,
+ },
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["a.java"],
+ libs: ["foo"],
+ // foo does not have module-lib scope so it should fallback to system
+ sdk_version: "module_current",
+ }
+ `)
+}
+
+func TestJavaSdkLibrary_DefaultToStubs(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ system: {
+ enabled: true,
+ },
+ default_to_stubs: true,
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["a.java"],
+ libs: ["foo"],
+ // does not have sdk_version set, should fallback to module,
+ // which will then fallback to system because the module scope
+ // is not enabled.
+ }
+ `)
+ // The baz library should depend on the system stubs jar.
+ bazLibrary := result.ModuleForTests("baz", "android_common").Rule("javac")
+ if expected, actual := `^-classpath .*:out/soong/[^:]*/turbine-combined/foo\.stubs.system\.jar$`, bazLibrary.Args["classpath"]; !regexp.MustCompile(expected).MatchString(actual) {
+ t.Errorf("expected %q, found %#q", expected, actual)
+ }
+}
+
+func TestJavaSdkLibraryImport(t *testing.T) {
+ result := prepareForJavaTest.RunTestWithBp(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "foo.system",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "system_current",
+ }
+
+ java_library {
+ name: "foo.test",
+ srcs: ["a.java"],
+ libs: ["sdklib"],
+ sdk_version: "test_current",
+ }
+
+ java_sdk_library_import {
+ name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ },
+ system: {
+ jars: ["b.jar"],
+ },
+ test: {
+ jars: ["c.jar"],
+ stub_srcs: ["c.java"],
+ },
+ }
+ `)
+
+ for _, scope := range []string{"", ".system", ".test"} {
+ fooModule := result.ModuleForTests("foo"+scope, "android_common")
+ javac := fooModule.Rule("javac")
+
+ sdklibStubsJar := result.ModuleForTests("sdklib.stubs"+scope, "android_common").Rule("combineJar").Output
+ android.AssertStringDoesContain(t, "foo classpath", javac.Args["classpath"], sdklibStubsJar.String())
+ }
+
+ CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
+ `prebuilt_sdklib.stubs`,
+ `prebuilt_sdklib.stubs.source.test`,
+ `prebuilt_sdklib.stubs.system`,
+ `prebuilt_sdklib.stubs.test`,
+ })
+}
+
+func TestJavaSdkLibraryImport_WithSource(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library_import {
+ name: "sdklib",
+ public: {
+ jars: ["a.jar"],
+ },
+ }
+ `)
+
+ CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
+ `dex2oatd`,
+ `prebuilt_sdklib`,
+ `sdklib.impl`,
+ `sdklib.stubs`,
+ `sdklib.stubs.source`,
+ `sdklib.xml`,
+ })
+
+ CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `prebuilt_sdklib.stubs`,
+ `sdklib.impl`,
+ // This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
+ // dependency is added after prebuilts may have been renamed and so has to use
+ // the renamed name.
+ `sdklib.xml`,
+ })
+}
+
+func TestJavaSdkLibraryImport_Preferred(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ }
+
+ java_sdk_library_import {
+ name: "sdklib",
+ prefer: true,
+ public: {
+ jars: ["a.jar"],
+ },
+ }
+ `)
+
+ CheckModuleDependencies(t, result.TestContext, "sdklib", "android_common", []string{
+ `dex2oatd`,
+ `prebuilt_sdklib`,
+ `sdklib.impl`,
+ `sdklib.stubs`,
+ `sdklib.stubs.source`,
+ `sdklib.xml`,
+ })
+
+ CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `prebuilt_sdklib.stubs`,
+ `sdklib.impl`,
+ `sdklib.xml`,
+ })
+}
+
+func TestJavaSdkLibraryEnforce(t *testing.T) {
+ partitionToBpOption := func(partition string) string {
+ switch partition {
+ case "system":
+ return ""
+ case "vendor":
+ return "soc_specific: true,"
+ case "product":
+ return "product_specific: true,"
+ default:
+ panic("Invalid partition group name: " + partition)
+ }
+ }
+
+ type testConfigInfo struct {
+ libraryType string
+ fromPartition string
+ toPartition string
+ enforceVendorInterface bool
+ enforceProductInterface bool
+ enforceJavaSdkLibraryCheck bool
+ allowList []string
+ }
+
+ createPreparer := func(info testConfigInfo) android.FixturePreparer {
+ bpFileTemplate := `
+ java_library {
+ name: "foo",
+ srcs: ["foo.java"],
+ libs: ["bar"],
+ sdk_version: "current",
+ %s
+ }
+
+ %s {
+ name: "bar",
+ srcs: ["bar.java"],
+ sdk_version: "current",
+ %s
+ }
+ `
+
+ bpFile := fmt.Sprintf(bpFileTemplate,
+ partitionToBpOption(info.fromPartition),
+ info.libraryType,
+ partitionToBpOption(info.toPartition))
+
+ return android.GroupFixturePreparers(
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("bar"),
+ android.FixtureWithRootAndroidBp(bpFile),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.EnforceProductPartitionInterface = proptools.BoolPtr(info.enforceProductInterface)
+ if info.enforceVendorInterface {
+ variables.DeviceVndkVersion = proptools.StringPtr("current")
+ }
+ variables.EnforceInterPartitionJavaSdkLibrary = proptools.BoolPtr(info.enforceJavaSdkLibraryCheck)
+ variables.InterPartitionJavaLibraryAllowList = info.allowList
+ }),
+ )
+ }
+
+ runTest := func(t *testing.T, info testConfigInfo, expectedErrorPattern string) {
+ t.Run(fmt.Sprintf("%v", info), func(t *testing.T) {
+ errorHandler := android.FixtureExpectsNoErrors
+ if expectedErrorPattern != "" {
+ errorHandler = android.FixtureExpectsAtLeastOneErrorMatchingPattern(expectedErrorPattern)
+ }
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ createPreparer(info),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTest(t)
+ })
+ }
+
+ errorMessage := "is not allowed across the partitions"
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_library",
+ fromPartition: "product",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: false,
+ }, "")
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_library",
+ fromPartition: "product",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: false,
+ enforceJavaSdkLibraryCheck: true,
+ }, "")
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_library",
+ fromPartition: "product",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ }, errorMessage)
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_library",
+ fromPartition: "vendor",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ }, errorMessage)
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_library",
+ fromPartition: "vendor",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ allowList: []string{"bar"},
+ }, "")
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_library",
+ fromPartition: "vendor",
+ toPartition: "product",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ }, errorMessage)
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_sdk_library",
+ fromPartition: "product",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ }, "")
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_sdk_library",
+ fromPartition: "vendor",
+ toPartition: "system",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ }, "")
+
+ runTest(t, testConfigInfo{
+ libraryType: "java_sdk_library",
+ fromPartition: "vendor",
+ toPartition: "product",
+ enforceVendorInterface: true,
+ enforceProductInterface: true,
+ enforceJavaSdkLibraryCheck: true,
+ }, "")
+}
+
+func TestJavaSdkLibraryDist(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib_no_owner",
+ unsafe_ignore_missing_latest_api: true,
+ srcs: ["foo.java"],
+ }
+
+ java_sdk_library {
+ name: "sdklib_group_foo",
+ unsafe_ignore_missing_latest_api: true,
+ srcs: ["foo.java"],
+ dist_group: "foo",
+ }
+
+ java_sdk_library {
+ name: "sdklib_owner_foo",
+ unsafe_ignore_missing_latest_api: true,
+ srcs: ["foo.java"],
+ owner: "foo",
+ }
+
+ java_sdk_library {
+ name: "sdklib_stem_foo",
+ unsafe_ignore_missing_latest_api: true,
+ srcs: ["foo.java"],
+ dist_stem: "foo",
+ }
+
+ java_sdk_library {
+ name: "sdklib_core_lib",
+ unsafe_ignore_missing_latest_api: true,
+ srcs: ["foo.java"],
+ core_lib: true,
+ }
+ `)
+
+ type testCase struct {
+ module string
+ distDir string
+ distStem string
+ }
+ testCases := []testCase{
+ {
+ module: "sdklib_no_owner",
+ distDir: "apistubs/android/public",
+ distStem: "sdklib_no_owner.jar",
+ },
+ {
+ module: "sdklib_group_foo",
+ distDir: "apistubs/foo/public",
+ distStem: "sdklib_group_foo.jar",
+ },
+ {
+ module: "sdklib_owner_foo",
+ distDir: "apistubs/foo/public",
+ distStem: "sdklib_owner_foo.jar",
+ },
+ {
+ module: "sdklib_stem_foo",
+ distDir: "apistubs/android/public",
+ distStem: "foo.jar",
+ },
+ {
+ module: "sdklib_core_lib",
+ distDir: "apistubs/core/public",
+ distStem: "sdklib_core_lib.jar",
+ },
+ }
+
+ for _, tt := range testCases {
+ t.Run(tt.module, func(t *testing.T) {
+ m := result.ModuleForTests(tt.module+".stubs", "android_common").Module().(*Library)
+ dists := m.Dists()
+ if len(dists) != 1 {
+ t.Fatalf("expected exactly 1 dist entry, got %d", len(dists))
+ }
+ if g, w := String(dists[0].Dir), tt.distDir; g != w {
+ t.Errorf("expected dist dir %q, got %q", w, g)
+ }
+ if g, w := String(dists[0].Dest), tt.distStem; g != w {
+ t.Errorf("expected dist stem %q, got %q", w, g)
+ }
+ })
+ }
+}
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/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index 30cb937..39c8fba 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -68,6 +68,9 @@
# Make sure this build builds from source, regardless of the default.
export SOONG_CONFIG_art_module_source_build=true
+# This script does not intend to handle compressed APEX
+export OVERRIDE_PRODUCT_COMPRESSED_APEX=false
+
OUT_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var OUT_DIR)
DIST_DIR=$(source build/envsetup.sh > /dev/null; TARGET_PRODUCT= get_build_var DIST_DIR)
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index 80774bf..b408fd3 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -14,7 +14,7 @@
setup
create_mock_bazel
- run_bazel info
+ STANDALONE_BAZEL=true run_bazel info
}
test_bazel_smoke
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index d17b464..37940ba 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -60,6 +60,7 @@
"path.go",
"proc_sync.go",
"rbe.go",
+ "sandbox_config.go",
"signal.go",
"soong.go",
"test_build.go",
@@ -86,5 +87,8 @@
"config_linux.go",
"sandbox_linux.go",
],
+ testSrcs: [
+ "sandbox_linux_test.go",
+ ],
},
}
diff --git a/ui/build/config.go b/ui/build/config.go
index 3ebde0d..f1f5989 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -57,6 +57,7 @@
katiSuffix string
targetDevice string
targetDeviceDir string
+ sandboxConfig *SandboxConfig
// Autodetected
totalRAM uint64
@@ -123,7 +124,8 @@
func NewConfig(ctx Context, args ...string) Config {
ret := &configImpl{
- environ: OsEnvironment(),
+ environ: OsEnvironment(),
+ sandboxConfig: &SandboxConfig{},
}
// Default matching ninja
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index 54aeda0..83c8865 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -225,6 +225,10 @@
// Extra environment variables to be exported to ninja
"BUILD_BROKEN_NINJA_USES_ENV_VARS",
+ // Used to restrict write access to source tree
+ "BUILD_BROKEN_SRC_DIR_IS_WRITABLE",
+ "BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST",
+
// Not used, but useful to be in the soong.log
"BOARD_VNDK_VERSION",
@@ -280,6 +284,8 @@
config.SetNinjaArgs(strings.Fields(makeVars["NINJA_GOALS"]))
config.SetTargetDevice(makeVars["TARGET_DEVICE"])
config.SetTargetDeviceDir(makeVars["TARGET_DEVICE_DIR"])
+ config.sandboxConfig.SetSrcDirIsRO(makeVars["BUILD_BROKEN_SRC_DIR_IS_WRITABLE"] == "false")
+ config.sandboxConfig.SetSrcDirRWAllowlist(strings.Fields(makeVars["BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST"]))
config.SetBuildBrokenDupRules(makeVars["BUILD_BROKEN_DUP_RULES"] == "true")
config.SetBuildBrokenUsesNetwork(makeVars["BUILD_BROKEN_USES_NETWORK"] == "true")
diff --git a/ui/build/sandbox_config.go b/ui/build/sandbox_config.go
new file mode 100644
index 0000000..1b46459
--- /dev/null
+++ b/ui/build/sandbox_config.go
@@ -0,0 +1,36 @@
+// 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 build
+
+type SandboxConfig struct {
+ srcDirIsRO bool
+ srcDirRWAllowlist []string
+}
+
+func (sc *SandboxConfig) SetSrcDirIsRO(ro bool) {
+ sc.srcDirIsRO = ro
+}
+
+func (sc *SandboxConfig) SrcDirIsRO() bool {
+ return sc.srcDirIsRO
+}
+
+func (sc *SandboxConfig) SetSrcDirRWAllowlist(allowlist []string) {
+ sc.srcDirRWAllowlist = allowlist
+}
+
+func (sc *SandboxConfig) SrcDirRWAllowlist() []string {
+ return sc.srcDirRWAllowlist
+}
diff --git a/ui/build/sandbox_linux.go b/ui/build/sandbox_linux.go
index dab0e75..b0a6748 100644
--- a/ui/build/sandbox_linux.go
+++ b/ui/build/sandbox_linux.go
@@ -145,6 +145,13 @@
func (c *Cmd) wrapSandbox() {
wd, _ := os.Getwd()
+ var srcDirMountFlag string
+ if c.config.sandboxConfig.SrcDirIsRO() {
+ srcDirMountFlag = "-R"
+ } else {
+ srcDirMountFlag = "-B" //Read-Write
+ }
+
sandboxArgs := []string{
// The executable to run
"-x", c.Path,
@@ -184,8 +191,8 @@
// Mount a writable tmp dir
"-B", "/tmp",
- // Mount source are read-write
- "-B", sandboxConfig.srcDir,
+ // Mount source
+ srcDirMountFlag, sandboxConfig.srcDir,
//Mount out dir as read-write
"-B", sandboxConfig.outDir,
@@ -198,6 +205,18 @@
"-q",
}
+ // Mount srcDir RW allowlists as Read-Write
+ if len(c.config.sandboxConfig.SrcDirRWAllowlist()) > 0 && !c.config.sandboxConfig.SrcDirIsRO() {
+ errMsg := `Product source tree has been set as ReadWrite, RW allowlist not necessary.
+ To recover, either
+ 1. Unset BUILD_BROKEN_SRC_DIR_IS_WRITABLE #or
+ 2. Unset BUILD_BROKEN_SRC_DIR_RW_ALLOWLIST`
+ c.ctx.Fatalln(errMsg)
+ }
+ for _, srcDirChild := range c.config.sandboxConfig.SrcDirRWAllowlist() {
+ sandboxArgs = append(sandboxArgs, "-B", srcDirChild)
+ }
+
if _, err := os.Stat(sandboxConfig.distDir); !os.IsNotExist(err) {
//Mount dist dir as read-write if it already exists
sandboxArgs = append(sandboxArgs, "-B", sandboxConfig.distDir)
diff --git a/ui/build/sandbox_linux_test.go b/ui/build/sandbox_linux_test.go
new file mode 100644
index 0000000..7bfd750
--- /dev/null
+++ b/ui/build/sandbox_linux_test.go
@@ -0,0 +1,104 @@
+// 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 build
+
+import (
+ "os"
+ "testing"
+)
+
+func TestMain(m *testing.M) {
+ // set src dir of sandbox
+ sandboxConfig.srcDir = "/my/src/dir"
+ os.Exit(m.Run())
+}
+
+func TestMountFlagsSrcDir(t *testing.T) {
+ testCases := []struct {
+ srcDirIsRO bool
+ expectedSrcDirFlag string
+ }{
+ {
+ srcDirIsRO: false,
+ expectedSrcDirFlag: "-B",
+ },
+ {
+ srcDirIsRO: true,
+ expectedSrcDirFlag: "-R",
+ },
+ }
+ for _, testCase := range testCases {
+ c := testCmd()
+ c.config.sandboxConfig.SetSrcDirIsRO(testCase.srcDirIsRO)
+ c.wrapSandbox()
+ if !isExpectedMountFlag(c.Args, sandboxConfig.srcDir, testCase.expectedSrcDirFlag) {
+ t.Error("Mount flag of srcDir is not correct")
+ }
+ }
+}
+
+func TestMountFlagsSrcDirRWAllowlist(t *testing.T) {
+ testCases := []struct {
+ srcDirRWAllowlist []string
+ }{
+ {
+ srcDirRWAllowlist: []string{},
+ },
+ {
+ srcDirRWAllowlist: []string{"my/path"},
+ },
+ {
+ srcDirRWAllowlist: []string{"my/path1", "my/path2"},
+ },
+ }
+ for _, testCase := range testCases {
+ c := testCmd()
+ c.config.sandboxConfig.SetSrcDirIsRO(true)
+ c.config.sandboxConfig.SetSrcDirRWAllowlist(testCase.srcDirRWAllowlist)
+ c.wrapSandbox()
+ for _, allowlistPath := range testCase.srcDirRWAllowlist {
+ if !isExpectedMountFlag(c.Args, allowlistPath, "-B") {
+ t.Error("Mount flag of srcDirRWAllowlist is not correct, expect -B")
+ }
+ }
+ }
+}
+
+// utils for setting up test
+func testConfig() Config {
+ // create a minimal testConfig
+ env := Environment([]string{})
+ sandboxConfig := SandboxConfig{}
+ return Config{&configImpl{environ: &env,
+ sandboxConfig: &sandboxConfig}}
+}
+
+func testCmd() *Cmd {
+ return Command(testContext(), testConfig(), "sandbox_test", "path/to/nsjail")
+}
+
+func isExpectedMountFlag(cmdArgs []string, dirName string, expectedFlag string) bool {
+ indexOfSrcDir := index(cmdArgs, dirName)
+ return cmdArgs[indexOfSrcDir-1] == expectedFlag
+}
+
+func index(arr []string, target string) int {
+ for idx, element := range arr {
+ if element == target {
+ return idx
+ }
+ }
+ panic("element could not be located in input array")
+}
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,
}
}