Merge "add options for LibFuzzer, HWASan, and ASan to fuzz_config"
diff --git a/apex/Android.bp b/apex/Android.bp
index 9e8c30d..e3a547c 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -7,6 +7,7 @@
"soong-android",
"soong-bpf",
"soong-cc",
+ "soong-filesystem",
"soong-java",
"soong-python",
"soong-rust",
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 69bf64f..adea9f0 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -384,6 +384,7 @@
libring(minSdkVersion:29)
libring-core(minSdkVersion:29)
librustc_demangle.rust_sysroot(minSdkVersion:29)
+libsdk_proto(minSdkVersion:30)
libsfplugin_ccodec_utils(minSdkVersion:29)
libsonivoxwithoutjet(minSdkVersion:29)
libspeexresampler(minSdkVersion:29)
diff --git a/apex/apex.go b/apex/apex.go
index 2182069..a18e34b 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -30,6 +30,7 @@
"android/soong/bpf"
"android/soong/cc"
prebuilt_etc "android/soong/etc"
+ "android/soong/filesystem"
"android/soong/java"
"android/soong/python"
"android/soong/rust"
@@ -96,6 +97,9 @@
// List of BPF programs inside this APEX bundle.
Bpfs []string
+ // List of filesystem images that are embedded inside this APEX bundle.
+ Filesystems []string
+
// Name of the apex_key module that provides the private key to sign this APEX bundle.
Key *string
@@ -530,6 +534,7 @@
bpfTag = dependencyTag{name: "bpf", payload: true}
certificateTag = dependencyTag{name: "certificate"}
executableTag = dependencyTag{name: "executable", payload: true}
+ fsTag = dependencyTag{name: "filesystem", payload: true}
javaLibTag = dependencyTag{name: "javaLib", payload: true}
jniLibTag = dependencyTag{name: "jniLib", payload: true}
keyTag = dependencyTag{name: "key"}
@@ -709,6 +714,7 @@
commonVariation := ctx.Config().AndroidCommonTarget.Variations()
ctx.AddFarVariationDependencies(commonVariation, javaLibTag, a.properties.Java_libs...)
ctx.AddFarVariationDependencies(commonVariation, bpfTag, a.properties.Bpfs...)
+ ctx.AddFarVariationDependencies(commonVariation, fsTag, a.properties.Filesystems...)
// With EMMA_INSTRUMENT_FRAMEWORK=true the ART boot image includes jacoco library.
if a.artApex && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
@@ -1481,6 +1487,11 @@
return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
}
+func apexFileForFilesystem(ctx android.BaseModuleContext, buildFile android.Path, fs filesystem.Filesystem) apexFile {
+ dirInApex := filepath.Join("etc", "fs")
+ return newApexFile(ctx, buildFile, buildFile.Base(), dirInApex, etc, fs)
+}
+
// WalyPayloadDeps visits dependencies that contributes to the payload of this APEX. For each of the
// visited module, the `do` callback is executed. Returning true in the callback continues the visit
// to the child modules. Returning false makes the visit to continue in the sibling or the parent
@@ -1655,6 +1666,12 @@
} else {
ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
}
+ case fsTag:
+ if fs, ok := child.(filesystem.Filesystem); ok {
+ filesInfo = append(filesInfo, apexFileForFilesystem(ctx, fs.OutputPath(), fs))
+ } else {
+ ctx.PropertyErrorf("filesystems", "%q is not a filesystem module", depName)
+ }
case prebuiltTag:
if prebuilt, ok := child.(prebuilt_etc.PrebuiltEtcModule); ok {
filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
diff --git a/bazel/aquery.go b/bazel/aquery.go
index 69d4fde..404be8c 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -16,6 +16,8 @@
import (
"encoding/json"
+ "fmt"
+ "path/filepath"
"strings"
"github.com/google/blueprint/proptools"
@@ -24,8 +26,14 @@
// artifact contains relevant portions of Bazel's aquery proto, Artifact.
// Represents a single artifact, whether it's a source file or a derived output file.
type artifact struct {
- Id string
- ExecPath string
+ Id int
+ PathFragmentId int
+}
+
+type pathFragment struct {
+ Id int
+ Label string
+ ParentId int
}
// KeyValuePair represents Bazel's aquery proto, KeyValuePair.
@@ -38,9 +46,9 @@
// Represents a data structure containing one or more files. Depsets in Bazel are an efficient
// data structure for storing large numbers of file paths.
type depSetOfFiles struct {
- Id string
+ Id int
// TODO(cparsons): Handle non-flat depsets.
- DirectArtifactIds []string
+ DirectArtifactIds []int
}
// action contains relevant portions of Bazel's aquery proto, Action.
@@ -48,9 +56,9 @@
type action struct {
Arguments []string
EnvironmentVariables []KeyValuePair
- InputDepSetIds []string
+ InputDepSetIds []int
Mnemonic string
- OutputIds []string
+ OutputIds []int
}
// actionGraphContainer contains relevant portions of Bazel's aquery proto, ActionGraphContainer.
@@ -59,6 +67,7 @@
Artifacts []artifact
Actions []action
DepSetOfFiles []depSetOfFiles
+ PathFragments []pathFragment
}
// BuildStatement contains information to register a build statement corresponding (one to one)
@@ -80,11 +89,20 @@
var aqueryResult actionGraphContainer
json.Unmarshal(aqueryJsonProto, &aqueryResult)
- artifactIdToPath := map[string]string{}
- for _, artifact := range aqueryResult.Artifacts {
- artifactIdToPath[artifact.Id] = artifact.ExecPath
+ pathFragments := map[int]pathFragment{}
+ for _, pathFragment := range aqueryResult.PathFragments {
+ pathFragments[pathFragment.Id] = pathFragment
}
- depsetIdToArtifactIds := map[string][]string{}
+ artifactIdToPath := map[int]string{}
+ for _, artifact := range aqueryResult.Artifacts {
+ artifactPath, err := expandPathFragment(artifact.PathFragmentId, pathFragments)
+ if err != nil {
+ // TODO(cparsons): Better error handling.
+ panic(err.Error())
+ }
+ artifactIdToPath[artifact.Id] = artifactPath
+ }
+ depsetIdToArtifactIds := map[int][]int{}
for _, depset := range aqueryResult.DepSetOfFiles {
depsetIdToArtifactIds[depset.Id] = depset.DirectArtifactIds
}
@@ -114,3 +132,18 @@
return buildStatements
}
+
+func expandPathFragment(id int, pathFragmentsMap map[int]pathFragment) (string, error) {
+ labels := []string{}
+ currId := id
+ // Only positive IDs are valid for path fragments. An ID of zero indicates a terminal node.
+ for currId > 0 {
+ currFragment, ok := pathFragmentsMap[currId]
+ if !ok {
+ return "", fmt.Errorf("undefined path fragment id '%s'", currId)
+ }
+ labels = append([]string{currFragment.Label}, labels...)
+ currId = currFragment.ParentId
+ }
+ return filepath.Join(labels...), nil
+}
diff --git a/cc/cc.go b/cc/cc.go
index 0d0aec7..7a7034f 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -57,14 +57,14 @@
})
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("asan_deps", sanitizerDepsMutator(asan))
- ctx.BottomUp("asan", sanitizerMutator(asan)).Parallel()
+ ctx.TopDown("asan_deps", sanitizerDepsMutator(Asan))
+ ctx.BottomUp("asan", sanitizerMutator(Asan)).Parallel()
ctx.TopDown("hwasan_deps", sanitizerDepsMutator(hwasan))
ctx.BottomUp("hwasan", sanitizerMutator(hwasan)).Parallel()
- ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(fuzzer))
- ctx.BottomUp("fuzzer", sanitizerMutator(fuzzer)).Parallel()
+ ctx.TopDown("fuzzer_deps", sanitizerDepsMutator(Fuzzer))
+ ctx.BottomUp("fuzzer", sanitizerMutator(Fuzzer)).Parallel()
// cfi mutator shouldn't run before sanitizers that return true for
// incompatibleWithCfi()
@@ -419,7 +419,7 @@
IsLLNDK bool `blueprint:"mutated"`
// IsLLNDKPrivate is set to true for the vendor variant of a cc_library module that has LLNDK
- // stubs and also sets llndk.vendor_available: false.
+ // stubs and also sets llndk.private: true.
IsLLNDKPrivate bool `blueprint:"mutated"`
}
@@ -785,6 +785,14 @@
hideApexVariantFromMake bool
}
+func (c *Module) SetPreventInstall() {
+ c.Properties.PreventInstall = true
+}
+
+func (c *Module) SetHideFromMake() {
+ c.Properties.HideFromMake = true
+}
+
func (c *Module) Toc() android.OptionalPath {
if c.linker != nil {
if library, ok := c.linker.(libraryInterface); ok {
@@ -1026,7 +1034,7 @@
// Returns true for dependency roots (binaries)
// TODO(ccross): also handle dlopenable libraries
-func (c *Module) isDependencyRoot() bool {
+func (c *Module) IsDependencyRoot() bool {
if root, ok := c.linker.(interface {
isDependencyRoot() bool
}); ok {
@@ -1079,11 +1087,11 @@
func (c *Module) isImplementationForLLNDKPublic() bool {
library, _ := c.library.(*libraryDecorator)
return library != nil && library.hasLLNDKStubs() &&
- (Bool(library.Properties.Llndk.Vendor_available) ||
+ (!Bool(library.Properties.Llndk.Private) ||
// TODO(b/170784825): until the LLNDK properties are moved into the cc_library,
// the non-Vendor variants of the cc_library don't know if the corresponding
- // llndk_library set vendor_available: false. Since libft2 is the only
- // private LLNDK library, hardcode it during the transition.
+ // llndk_library set private: true. Since libft2 is the only private LLNDK
+ // library, hardcode it during the transition.
c.BaseModuleName() != "libft2")
}
@@ -1091,20 +1099,12 @@
func (c *Module) IsVndkPrivate() bool {
// Check if VNDK-core-private or VNDK-SP-private
if c.IsVndk() {
- if Bool(c.vndkdep.Properties.Vndk.Private) {
- return true
- }
- // TODO(b/175768895) remove this when we clean up "vendor_available: false" use cases.
- if c.VendorProperties.Vendor_available != nil && !Bool(c.VendorProperties.Vendor_available) {
- return true
- }
- return false
+ return Bool(c.vndkdep.Properties.Vndk.Private)
}
// Check if LLNDK-private
if library, ok := c.library.(*libraryDecorator); ok && c.IsLlndk() {
- // TODO(b/175768895) replace this with 'private' property.
- return !Bool(library.Properties.Llndk.Vendor_available)
+ return Bool(library.Properties.Llndk.Private)
}
return false
@@ -1272,7 +1272,7 @@
}
func (ctx *moduleContextImpl) header() bool {
- return ctx.mod.header()
+ return ctx.mod.Header()
}
func (ctx *moduleContextImpl) binary() bool {
@@ -1429,6 +1429,10 @@
return nil
}
+func (c *Module) IsPrebuilt() bool {
+ return c.Prebuilt() != nil
+}
+
func (c *Module) Name() string {
name := c.ModuleBase.Name()
if p, ok := c.linker.(interface {
@@ -2855,7 +2859,7 @@
return baseName + ".vendor"
}
- if c.inVendor() && vendorSuffixModules[baseName] {
+ if c.InVendor() && vendorSuffixModules[baseName] {
return baseName + ".vendor"
} else if c.InRecovery() && recoverySuffixModules[baseName] {
return baseName + ".recovery"
@@ -2967,7 +2971,8 @@
return false
}
-func (c *Module) header() bool {
+// Header returns true if the module is a header-only variant. (See cc/library.go header()).
+func (c *Module) Header() bool {
if h, ok := c.linker.(interface {
header() bool
}); ok {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 71c6b70..3502d5f 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -234,9 +234,6 @@
t.Helper()
mod := ctx.ModuleForTests(name, variant).Module().(*Module)
- if !mod.HasVendorVariant() {
- t.Errorf("%q must have variant %q", name, variant)
- }
// Check library properties.
lib, ok := mod.compiler.(*libraryDecorator)
@@ -733,10 +730,11 @@
}
cc_library {
name: "libvndk-private",
- vendor_available: false,
- product_available: false,
+ vendor_available: true,
+ product_available: true,
vndk: {
enabled: true,
+ private: true,
},
nocrt: true,
}
@@ -760,7 +758,7 @@
func TestVndkModuleError(t *testing.T) {
// Check the error message for vendor_available and product_available properties.
- testCcErrorProductVndk(t, "vndk: vendor_available must be set to either true or false when `vndk: {enabled: true}`", `
+ testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
cc_library {
name: "libvndk",
vndk: {
@@ -770,7 +768,7 @@
}
`)
- testCcErrorProductVndk(t, "vndk: vendor_available must be set to either true or false when `vndk: {enabled: true}`", `
+ testCcErrorProductVndk(t, "vndk: vendor_available must be set to true when `vndk: {enabled: true}`", `
cc_library {
name: "libvndk",
product_available: true,
@@ -1248,6 +1246,15 @@
t.Errorf("%q expected but not found", jsonFile)
}
}
+
+ // 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 TestVendorSnapshotUse(t *testing.T) {
@@ -1679,6 +1686,8 @@
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
`module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+ `module "libvendor\{.+,image:vendor.+,arch:arm64_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
+ `module "libvendor\{.+,image:vendor.+,arch:arm_.+\}" in vendor proprietary path "device" may not use "exclude_from_vendor_snapshot: true"`,
})
}
@@ -1722,6 +1731,10 @@
`module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
`module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:vendor.+,arch:arm64_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
+ `module "libinclude\{.+,image:vendor.+,arch:arm_.+\}" may not use both "vendor_available: true" and "exclude_from_vendor_snapshot: true"`,
})
}
@@ -3139,7 +3152,7 @@
}
llndk_library {
name: "libllndkprivate.llndk",
- vendor_available: false,
+ private: true,
symbol_file: "",
}`
diff --git a/cc/fuzz.go b/cc/fuzz.go
index aa9038a..d7da5ab 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -321,7 +321,7 @@
module, binary := NewBinary(hod)
binary.baseInstaller = NewFuzzInstaller()
- module.sanitize.SetSanitizer(fuzzer, true)
+ module.sanitize.SetSanitizer(Fuzzer, true)
fuzz := &fuzzBinary{
binaryDecorator: binary,
diff --git a/cc/image.go b/cc/image.go
index 11ba55c..13095fc 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -26,36 +26,18 @@
var _ android.ImageInterface = (*Module)(nil)
-type imageVariantType string
+type ImageVariantType string
const (
- coreImageVariant imageVariantType = "core"
- vendorImageVariant imageVariantType = "vendor"
- productImageVariant imageVariantType = "product"
- ramdiskImageVariant imageVariantType = "ramdisk"
- vendorRamdiskImageVariant imageVariantType = "vendor_ramdisk"
- recoveryImageVariant imageVariantType = "recovery"
- hostImageVariant imageVariantType = "host"
+ coreImageVariant ImageVariantType = "core"
+ vendorImageVariant ImageVariantType = "vendor"
+ productImageVariant ImageVariantType = "product"
+ ramdiskImageVariant ImageVariantType = "ramdisk"
+ vendorRamdiskImageVariant ImageVariantType = "vendor_ramdisk"
+ recoveryImageVariant ImageVariantType = "recovery"
+ hostImageVariant ImageVariantType = "host"
)
-func (c *Module) getImageVariantType() imageVariantType {
- if c.Host() {
- return hostImageVariant
- } else if c.inVendor() {
- return vendorImageVariant
- } else if c.InProduct() {
- return productImageVariant
- } else if c.InRamdisk() {
- return ramdiskImageVariant
- } else if c.InVendorRamdisk() {
- return vendorRamdiskImageVariant
- } else if c.InRecovery() {
- return recoveryImageVariant
- } else {
- return coreImageVariant
- }
-}
-
const (
// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
// against the VNDK.
@@ -67,13 +49,15 @@
)
func (ctx *moduleContext) ProductSpecific() bool {
- return ctx.ModuleContext.ProductSpecific() ||
- (ctx.mod.HasProductVariant() && ctx.mod.InProduct())
+ // Additionally check if this module is inProduct() that means it is a "product" variant of a
+ // module. As well as product specific modules, product variants must be installed to /product.
+ return ctx.ModuleContext.ProductSpecific() || ctx.mod.InProduct()
}
func (ctx *moduleContext) SocSpecific() bool {
- return ctx.ModuleContext.SocSpecific() ||
- (ctx.mod.HasVendorVariant() && ctx.mod.inVendor())
+ // Additionally check if this module is inVendor() that means it is a "vendor" variant of a
+ // module. As well as SoC specific modules, vendor variants must be installed to /vendor.
+ return ctx.ModuleContext.SocSpecific() || ctx.mod.InVendor()
}
func (ctx *moduleContextImpl) inProduct() bool {
@@ -81,7 +65,7 @@
}
func (ctx *moduleContextImpl) inVendor() bool {
- return ctx.mod.inVendor()
+ return ctx.mod.InVendor()
}
func (ctx *moduleContextImpl) inRamdisk() bool {
@@ -98,18 +82,12 @@
// Returns true when this module is configured to have core and vendor variants.
func (c *Module) HasVendorVariant() bool {
- // In case of a VNDK, 'vendor_available: false' still creates a vendor variant.
- return c.IsVndk() || Bool(c.VendorProperties.Vendor_available)
+ return Bool(c.VendorProperties.Vendor_available)
}
// Returns true when this module is configured to have core and product variants.
func (c *Module) HasProductVariant() bool {
- if c.VendorProperties.Product_available == nil {
- // Without 'product_available', product variant will not be created even for VNDKs.
- return false
- }
- // However, 'product_available: false' in a VNDK still creates a product variant.
- return c.IsVndk() || Bool(c.VendorProperties.Product_available)
+ return Bool(c.VendorProperties.Product_available)
}
// Returns true when this module is configured to have core and either product or vendor variants.
@@ -123,7 +101,7 @@
}
// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
-func (c *Module) inVendor() bool {
+func (c *Module) InVendor() bool {
return c.Properties.ImageVariationPrefix == VendorVariationPrefix
}
@@ -186,7 +164,7 @@
// This function is used only for the VNDK modules that is available to both vendor
// and product partitions.
func (c *Module) compareVendorAndProductProps() bool {
- if !c.IsVndk() && c.VendorProperties.Product_available != nil {
+ if !c.IsVndk() && !Bool(c.VendorProperties.Product_available) {
panic(fmt.Errorf("This is only for product available VNDK libs. %q is not a VNDK library or not product available", c.Name()))
}
for _, properties := range c.GetProperties() {
@@ -202,14 +180,14 @@
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
productSpecific := mctx.ProductSpecific()
- if m.VendorProperties.Vendor_available != nil {
+ if Bool(m.VendorProperties.Vendor_available) {
if vendorSpecific {
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
}
}
- if m.VendorProperties.Product_available != nil {
+ if Bool(m.VendorProperties.Product_available) {
if productSpecific {
mctx.PropertyErrorf("product_available",
"doesn't make sense at the same time as `product_specific: true`")
@@ -226,10 +204,10 @@
if !vndkdep.isVndkExt() {
mctx.PropertyErrorf("vndk",
"must set `extends: \"...\"` to vndk extension")
- } else if m.VendorProperties.Vendor_available != nil {
+ } else if Bool(m.VendorProperties.Vendor_available) {
mctx.PropertyErrorf("vendor_available",
"must not set at the same time as `vndk: {extends: \"...\"}`")
- } else if m.VendorProperties.Product_available != nil {
+ } else if Bool(m.VendorProperties.Product_available) {
mctx.PropertyErrorf("product_available",
"must not set at the same time as `vndk: {extends: \"...\"}`")
}
@@ -239,11 +217,11 @@
"must set `vendor: true` or `product_specific: true` to set `extends: %q`",
m.getVndkExtendsModuleName())
}
- if m.VendorProperties.Vendor_available == nil {
+ if !Bool(m.VendorProperties.Vendor_available) {
mctx.PropertyErrorf("vndk",
- "vendor_available must be set to either true or false when `vndk: {enabled: true}`")
+ "vendor_available must be set to true when `vndk: {enabled: true}`")
}
- if m.VendorProperties.Product_available != nil {
+ if Bool(m.VendorProperties.Product_available) {
// If a VNDK module creates both product and vendor variants, they
// must have the same properties since they share a single VNDK
// library on runtime.
diff --git a/cc/linkable.go b/cc/linkable.go
index 489063f..ab5a552 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -6,6 +6,59 @@
"github.com/google/blueprint"
)
+// PlatformSanitizeable is an interface for sanitizing platform modules.
+type PlatformSanitizeable interface {
+ LinkableInterface
+
+ // SanitizePropDefined returns whether the Sanitizer properties struct for this module is defined.
+ SanitizePropDefined() bool
+
+ // IsDependencyRoot returns whether a module is of a type which cannot be a linkage dependency
+ // of another module. For example, cc_binary and rust_binary represent dependency roots as other
+ // modules cannot have linkage dependencies against these types.
+ IsDependencyRoot() bool
+
+ // IsSanitizerEnabled returns whether a sanitizer is enabled.
+ IsSanitizerEnabled(t SanitizerType) bool
+
+ // IsSanitizerExplicitlyDisabled returns whether a sanitizer has been explicitly disabled (set to false) rather
+ // than left undefined.
+ IsSanitizerExplicitlyDisabled(t SanitizerType) bool
+
+ // SanitizeDep returns the value of the SanitizeDep flag, which is set if a module is a dependency of a
+ // sanitized module.
+ SanitizeDep() bool
+
+ // SetSanitizer enables or disables the specified sanitizer type if it's supported, otherwise this should panic.
+ SetSanitizer(t SanitizerType, b bool)
+
+ // SetSanitizerDep returns true if the module is statically linked.
+ SetSanitizeDep(b bool)
+
+ // StaticallyLinked returns true if the module is statically linked.
+ StaticallyLinked() bool
+
+ // SetInSanitizerDir sets the module installation to the sanitizer directory.
+ SetInSanitizerDir()
+
+ // SanitizeNever returns true if this module should never be sanitized.
+ SanitizeNever() bool
+
+ // SanitizerSupported returns true if a sanitizer type is supported by this modules compiler.
+ SanitizerSupported(t SanitizerType) bool
+
+ // SanitizableDepTagChecker returns a SantizableDependencyTagChecker function type.
+ SanitizableDepTagChecker() SantizableDependencyTagChecker
+}
+
+// SantizableDependencyTagChecker functions check whether or not a dependency
+// tag can be sanitized. These functions should return true if the tag can be
+// sanitized, otherwise they should return false. These functions should also
+// handle all possible dependency tags in the dependency tree. For example,
+// Rust modules can depend on both Rust and CC libraries, so the Rust module
+// implementation should handle tags from both.
+type SantizableDependencyTagChecker func(tag blueprint.DependencyTag) bool
+
// LinkableInterface is an interface for a type of module that is linkable in a C++ library.
type LinkableInterface interface {
android.Module
@@ -27,6 +80,8 @@
SetShared()
Static() bool
Shared() bool
+ Header() bool
+ IsPrebuilt() bool
Toc() android.OptionalPath
Host() bool
@@ -40,6 +95,8 @@
InRecovery() bool
OnlyInRecovery() bool
+ InVendor() bool
+
UseSdk() bool
UseVndk() bool
MustUseVendorVariant() bool
@@ -56,6 +113,11 @@
IsSdkVariant() bool
SplitPerApiLevel() bool
+
+ // SetPreventInstall sets the PreventInstall property to 'true' for this module.
+ SetPreventInstall()
+ // SetHideFromMake sets the HideFromMake property to 'true' for this module.
+ SetHideFromMake()
}
var (
@@ -67,6 +129,26 @@
CoverageDepTag = dependencyTag{name: "coverage"}
)
+// GetImageVariantType returns the ImageVariantType string value for the given module
+// (these are defined in cc/image.go).
+func GetImageVariantType(c LinkableInterface) ImageVariantType {
+ if c.Host() {
+ return hostImageVariant
+ } else if c.InVendor() {
+ return vendorImageVariant
+ } else if c.InProduct() {
+ return productImageVariant
+ } else if c.InRamdisk() {
+ return ramdiskImageVariant
+ } else if c.InVendorRamdisk() {
+ return vendorRamdiskImageVariant
+ } else if c.InRecovery() {
+ return recoveryImageVariant
+ } else {
+ return coreImageVariant
+ }
+}
+
// SharedDepTag returns the dependency tag for any C++ shared libraries.
func SharedDepTag() blueprint.DependencyTag {
return libraryDependencyTag{Kind: sharedLibraryDependency}
diff --git a/cc/llndk_library.go b/cc/llndk_library.go
index 0c4bcfd..bd48501 100644
--- a/cc/llndk_library.go
+++ b/cc/llndk_library.go
@@ -55,13 +55,6 @@
// Whether the system library uses symbol versions.
Unversioned *bool
- // whether this module can be directly depended upon by libs that are installed
- // to /vendor and /product.
- // When set to false, this module can only be depended on by VNDK libraries, not
- // vendor nor product libraries. This effectively hides this module from
- // non-system modules. Default value is true.
- Vendor_available *bool
-
// list of llndk headers to re-export include directories from.
Export_llndk_headers []string `android:"arch_variant"`
@@ -136,7 +129,6 @@
stub := &llndkStubDecorator{
libraryDecorator: library,
}
- stub.Properties.Vendor_available = BoolPtr(true)
module.compiler = stub
module.linker = stub
module.installer = nil
diff --git a/cc/sanitize.go b/cc/sanitize.go
index bb92a88..5992611 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -71,7 +71,7 @@
"export_memory_stats=0", "max_malloc_fill_size=0"}
)
-type sanitizerType int
+type SanitizerType int
func boolPtr(v bool) *bool {
if v {
@@ -82,19 +82,19 @@
}
const (
- asan sanitizerType = iota + 1
+ Asan SanitizerType = iota + 1
hwasan
tsan
intOverflow
cfi
scs
- fuzzer
+ Fuzzer
)
// Name of the sanitizer variation for this sanitizer type
-func (t sanitizerType) variationName() string {
+func (t SanitizerType) variationName() string {
switch t {
- case asan:
+ case Asan:
return "asan"
case hwasan:
return "hwasan"
@@ -106,17 +106,17 @@
return "cfi"
case scs:
return "scs"
- case fuzzer:
+ case Fuzzer:
return "fuzzer"
default:
- panic(fmt.Errorf("unknown sanitizerType %d", t))
+ panic(fmt.Errorf("unknown SanitizerType %d", t))
}
}
// This is the sanitizer names in SANITIZE_[TARGET|HOST]
-func (t sanitizerType) name() string {
+func (t SanitizerType) name() string {
switch t {
- case asan:
+ case Asan:
return "address"
case hwasan:
return "hwaddress"
@@ -128,15 +128,37 @@
return "cfi"
case scs:
return "shadow-call-stack"
- case fuzzer:
+ case Fuzzer:
return "fuzzer"
default:
- panic(fmt.Errorf("unknown sanitizerType %d", t))
+ panic(fmt.Errorf("unknown SanitizerType %d", t))
}
}
-func (t sanitizerType) incompatibleWithCfi() bool {
- return t == asan || t == fuzzer || t == hwasan
+func (*Module) SanitizerSupported(t SanitizerType) bool {
+ switch t {
+ case Asan:
+ return true
+ case hwasan:
+ return true
+ case tsan:
+ return true
+ case intOverflow:
+ return true
+ case cfi:
+ return true
+ case scs:
+ return true
+ case Fuzzer:
+ return true
+ default:
+ return false
+ }
+}
+
+// incompatibleWithCfi returns true if a sanitizer is incompatible with CFI.
+func (t SanitizerType) incompatibleWithCfi() bool {
+ return t == Asan || t == Fuzzer || t == hwasan
}
type SanitizeUserProps struct {
@@ -680,9 +702,10 @@
return sanitize.Properties.InSanitizerDir
}
-func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool {
+// getSanitizerBoolPtr returns the SanitizerTypes associated bool pointer from SanitizeProperties.
+func (sanitize *sanitize) getSanitizerBoolPtr(t SanitizerType) *bool {
switch t {
- case asan:
+ case Asan:
return sanitize.Properties.Sanitize.Address
case hwasan:
return sanitize.Properties.Sanitize.Hwaddress
@@ -694,32 +717,34 @@
return sanitize.Properties.Sanitize.Cfi
case scs:
return sanitize.Properties.Sanitize.Scs
- case fuzzer:
+ case Fuzzer:
return sanitize.Properties.Sanitize.Fuzzer
default:
- panic(fmt.Errorf("unknown sanitizerType %d", t))
+ panic(fmt.Errorf("unknown SanitizerType %d", t))
}
}
+// isUnsanitizedVariant returns true if no sanitizers are enabled.
func (sanitize *sanitize) isUnsanitizedVariant() bool {
- return !sanitize.isSanitizerEnabled(asan) &&
+ return !sanitize.isSanitizerEnabled(Asan) &&
!sanitize.isSanitizerEnabled(hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
!sanitize.isSanitizerEnabled(cfi) &&
!sanitize.isSanitizerEnabled(scs) &&
- !sanitize.isSanitizerEnabled(fuzzer)
+ !sanitize.isSanitizerEnabled(Fuzzer)
}
+// isVariantOnProductionDevice returns true if variant is for production devices (no non-production sanitizers enabled).
func (sanitize *sanitize) isVariantOnProductionDevice() bool {
- return !sanitize.isSanitizerEnabled(asan) &&
+ return !sanitize.isSanitizerEnabled(Asan) &&
!sanitize.isSanitizerEnabled(hwasan) &&
!sanitize.isSanitizerEnabled(tsan) &&
- !sanitize.isSanitizerEnabled(fuzzer)
+ !sanitize.isSanitizerEnabled(Fuzzer)
}
-func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) {
+func (sanitize *sanitize) SetSanitizer(t SanitizerType, b bool) {
switch t {
- case asan:
+ case Asan:
sanitize.Properties.Sanitize.Address = boolPtr(b)
case hwasan:
sanitize.Properties.Sanitize.Hwaddress = boolPtr(b)
@@ -731,10 +756,10 @@
sanitize.Properties.Sanitize.Cfi = boolPtr(b)
case scs:
sanitize.Properties.Sanitize.Scs = boolPtr(b)
- case fuzzer:
+ case Fuzzer:
sanitize.Properties.Sanitize.Fuzzer = boolPtr(b)
default:
- panic(fmt.Errorf("unknown sanitizerType %d", t))
+ panic(fmt.Errorf("unknown SanitizerType %d", t))
}
if b {
sanitize.Properties.SanitizerEnabled = true
@@ -743,7 +768,7 @@
// Check if the sanitizer is explicitly disabled (as opposed to nil by
// virtue of not being set).
-func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool {
+func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t SanitizerType) bool {
if sanitize == nil {
return false
}
@@ -757,7 +782,7 @@
// indirectly (via a mutator) sets the bool ptr to true, and you can't
// distinguish between the cases. It isn't needed though - both cases can be
// treated identically.
-func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool {
+func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool {
if sanitize == nil {
return false
}
@@ -766,7 +791,8 @@
return sanitizerVal != nil && *sanitizerVal == true
}
-func isSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
+// IsSanitizableDependencyTag returns true if the dependency tag is sanitizable.
+func IsSanitizableDependencyTag(tag blueprint.DependencyTag) bool {
switch t := tag.(type) {
case dependencyTag:
return t == reuseObjTag || t == objDepTag
@@ -777,6 +803,10 @@
}
}
+func (m *Module) SanitizableDepTagChecker() SantizableDependencyTagChecker {
+ return IsSanitizableDependencyTag
+}
+
// Determines if the current module is a static library going to be captured
// as vendor snapshot. Such modules must create both cfi and non-cfi variants,
// except for ones which explicitly disable cfi.
@@ -785,51 +815,58 @@
return false
}
- c := mctx.Module().(*Module)
+ c := mctx.Module().(PlatformSanitizeable)
- if !c.inVendor() {
+ if !c.InVendor() {
return false
}
- if !c.static() {
+ if !c.StaticallyLinked() {
return false
}
- if c.Prebuilt() != nil {
+ if c.IsPrebuilt() {
return false
}
- return c.sanitize != nil &&
- !Bool(c.sanitize.Properties.Sanitize.Never) &&
- !c.sanitize.isSanitizerExplicitlyDisabled(cfi)
+ if !c.SanitizerSupported(cfi) {
+ return false
+ }
+
+ return c.SanitizePropDefined() &&
+ !c.SanitizeNever() &&
+ !c.IsSanitizerExplicitlyDisabled(cfi)
}
// Propagate sanitizer requirements down from binaries
-func sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) {
+func sanitizerDepsMutator(t SanitizerType) func(android.TopDownMutatorContext) {
return func(mctx android.TopDownMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok {
- enabled := c.sanitize.isSanitizerEnabled(t)
+ if c, ok := mctx.Module().(PlatformSanitizeable); ok {
+ enabled := c.IsSanitizerEnabled(t)
if t == cfi && needsCfiForVendorSnapshot(mctx) {
// We shouldn't change the result of isSanitizerEnabled(cfi) to correctly
// determine defaultVariation in sanitizerMutator below.
// Instead, just mark SanitizeDep to forcefully create cfi variant.
enabled = true
- c.sanitize.Properties.SanitizeDep = true
+ c.SetSanitizeDep(true)
}
if enabled {
+ isSanitizableDependencyTag := c.SanitizableDepTagChecker()
mctx.WalkDeps(func(child, parent android.Module) bool {
if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
return false
}
- if d, ok := child.(*Module); ok && d.sanitize != nil &&
- !Bool(d.sanitize.Properties.Sanitize.Never) &&
- !d.sanitize.isSanitizerExplicitlyDisabled(t) {
+ if d, ok := child.(PlatformSanitizeable); ok && d.SanitizePropDefined() &&
+ !d.SanitizeNever() &&
+ !d.IsSanitizerExplicitlyDisabled(t) {
if t == cfi || t == hwasan || t == scs {
- if d.static() {
- d.sanitize.Properties.SanitizeDep = true
+ if d.StaticallyLinked() && d.SanitizerSupported(t) {
+ // Rust does not support some of these sanitizers, so we need to check if it's
+ // supported before setting this true.
+ d.SetSanitizeDep(true)
}
} else {
- d.sanitize.Properties.SanitizeDep = true
+ d.SetSanitizeDep(true)
}
}
return true
@@ -847,9 +884,19 @@
}
}
+func (c *Module) SanitizeNever() bool {
+ return Bool(c.sanitize.Properties.Sanitize.Never)
+}
+
+func (c *Module) IsSanitizerExplicitlyDisabled(t SanitizerType) bool {
+ return c.sanitize.isSanitizerExplicitlyDisabled(t)
+}
+
// Propagate the ubsan minimal runtime dependency when there are integer overflow sanitized static dependencies.
func sanitizerRuntimeDepsMutator(mctx android.TopDownMutatorContext) {
+ // Change this to PlatformSanitizable when/if non-cc modules support ubsan sanitizers.
if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
+ isSanitizableDependencyTag := c.SanitizableDepTagChecker()
mctx.WalkDeps(func(child, parent android.Module) bool {
if !isSanitizableDependencyTag(mctx.OtherModuleDependencyTag(child)) {
return false
@@ -1057,7 +1104,7 @@
variations = append(variations, c.ImageVariation())
}
mctx.AddFarVariationDependencies(variations, depTag, deps...)
- } else if !c.static() && !c.header() {
+ } else if !c.static() && !c.Header() {
// If we're using snapshots and in vendor, redirect to snapshot whenever possible
if c.VndkVersion() == mctx.DeviceConfig().VndkVersion() {
snapshots := vendorSnapshotSharedLibs(mctx.Config())
@@ -1098,16 +1145,52 @@
AddSanitizerDependencies(ctx android.BottomUpMutatorContext, sanitizerName string)
}
+func (c *Module) SanitizePropDefined() bool {
+ return c.sanitize != nil
+}
+
+func (c *Module) IsSanitizerEnabled(t SanitizerType) bool {
+ return c.sanitize.isSanitizerEnabled(t)
+}
+
+func (c *Module) SanitizeDep() bool {
+ return c.sanitize.Properties.SanitizeDep
+}
+
+func (c *Module) StaticallyLinked() bool {
+ return c.static()
+}
+
+func (c *Module) SetInSanitizerDir() {
+ if c.sanitize != nil {
+ c.sanitize.Properties.InSanitizerDir = true
+ }
+}
+
+func (c *Module) SetSanitizer(t SanitizerType, b bool) {
+ if c.sanitize != nil {
+ c.sanitize.SetSanitizer(t, b)
+ }
+}
+
+func (c *Module) SetSanitizeDep(b bool) {
+ if c.sanitize != nil {
+ c.sanitize.Properties.SanitizeDep = b
+ }
+}
+
+var _ PlatformSanitizeable = (*Module)(nil)
+
// Create sanitized variants for modules that need them
-func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) {
+func sanitizerMutator(t SanitizerType) func(android.BottomUpMutatorContext) {
return func(mctx android.BottomUpMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.sanitize != nil {
- if c.isDependencyRoot() && c.sanitize.isSanitizerEnabled(t) {
+ if c, ok := mctx.Module().(PlatformSanitizeable); ok && c.SanitizePropDefined() {
+ if c.IsDependencyRoot() && c.IsSanitizerEnabled(t) {
modules := mctx.CreateVariations(t.variationName())
- modules[0].(*Module).sanitize.SetSanitizer(t, true)
- } else if c.sanitize.isSanitizerEnabled(t) || c.sanitize.Properties.SanitizeDep {
- isSanitizerEnabled := c.sanitize.isSanitizerEnabled(t)
- if c.static() || c.header() || t == asan || t == fuzzer {
+ modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
+ } else if c.IsSanitizerEnabled(t) || c.SanitizeDep() {
+ isSanitizerEnabled := c.IsSanitizerEnabled(t)
+ if c.StaticallyLinked() || c.Header() || t == Asan || t == Fuzzer {
// Static and header libs are split into non-sanitized and sanitized variants.
// Shared libs are not split. However, for asan and fuzzer, we split even for shared
// libs because a library sanitized for asan/fuzzer can't be linked from a library
@@ -1121,17 +1204,20 @@
// module. By setting it to the name of the sanitized variation, the dangling dependency
// is redirected to the sanitized variant of the dependent module.
defaultVariation := t.variationName()
+ // Not all PlatformSanitizeable modules support the CFI sanitizer
+ cfiSupported := mctx.Module().(PlatformSanitizeable).SanitizerSupported(cfi)
mctx.SetDefaultDependencyVariation(&defaultVariation)
- modules := mctx.CreateVariations("", t.variationName())
- modules[0].(*Module).sanitize.SetSanitizer(t, false)
- modules[1].(*Module).sanitize.SetSanitizer(t, true)
- modules[0].(*Module).sanitize.Properties.SanitizeDep = false
- modules[1].(*Module).sanitize.Properties.SanitizeDep = false
- if mctx.Device() && t.incompatibleWithCfi() {
+ modules := mctx.CreateVariations("", t.variationName())
+ modules[0].(PlatformSanitizeable).SetSanitizer(t, false)
+ modules[1].(PlatformSanitizeable).SetSanitizer(t, true)
+ modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
+ modules[1].(PlatformSanitizeable).SetSanitizeDep(false)
+
+ if mctx.Device() && t.incompatibleWithCfi() && cfiSupported {
// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
// are incompatible with cfi
- modules[1].(*Module).sanitize.SetSanitizer(cfi, false)
+ modules[1].(PlatformSanitizeable).SetSanitizer(cfi, false)
}
// For cfi/scs/hwasan, we can export both sanitized and un-sanitized variants
@@ -1139,46 +1225,48 @@
// For other types of sanitizers, suppress the variation that is disabled.
if t != cfi && t != scs && t != hwasan {
if isSanitizerEnabled {
- modules[0].(*Module).Properties.PreventInstall = true
- modules[0].(*Module).Properties.HideFromMake = true
+ modules[0].(PlatformSanitizeable).SetPreventInstall()
+ modules[0].(PlatformSanitizeable).SetHideFromMake()
} else {
- modules[1].(*Module).Properties.PreventInstall = true
- modules[1].(*Module).Properties.HideFromMake = true
+ modules[1].(PlatformSanitizeable).SetPreventInstall()
+ modules[1].(PlatformSanitizeable).SetHideFromMake()
}
}
// Export the static lib name to make
- if c.static() && c.ExportedToMake() {
+ if c.StaticallyLinked() && c.ExportedToMake() {
if t == cfi {
- cfiStaticLibs(mctx.Config()).add(c, c.Name())
+ cfiStaticLibs(mctx.Config()).add(c, c.Module().Name())
} else if t == hwasan {
- hwasanStaticLibs(mctx.Config()).add(c, c.Name())
+ hwasanStaticLibs(mctx.Config()).add(c, c.Module().Name())
}
}
} else {
// Shared libs are not split. Only the sanitized variant is created.
modules := mctx.CreateVariations(t.variationName())
- modules[0].(*Module).sanitize.SetSanitizer(t, true)
- modules[0].(*Module).sanitize.Properties.SanitizeDep = false
+ modules[0].(PlatformSanitizeable).SetSanitizer(t, true)
+ modules[0].(PlatformSanitizeable).SetSanitizeDep(false)
// locate the asan libraries under /data/asan
- if mctx.Device() && t == asan && isSanitizerEnabled {
- modules[0].(*Module).sanitize.Properties.InSanitizerDir = true
+ if mctx.Device() && t == Asan && isSanitizerEnabled {
+ modules[0].(PlatformSanitizeable).SetInSanitizerDir()
}
if mctx.Device() && t.incompatibleWithCfi() {
// TODO: Make sure that cfi mutator runs "after" any of the sanitizers that
// are incompatible with cfi
- modules[0].(*Module).sanitize.SetSanitizer(cfi, false)
+ modules[0].(PlatformSanitizeable).SetSanitizer(cfi, false)
}
}
}
- c.sanitize.Properties.SanitizeDep = false
+ c.SetSanitizeDep(false)
} else if sanitizeable, ok := mctx.Module().(Sanitizeable); ok && sanitizeable.IsSanitizerEnabled(mctx, t.name()) {
// APEX modules fall here
sanitizeable.AddSanitizerDependencies(mctx, t.name())
mctx.CreateVariations(t.variationName())
} else if c, ok := mctx.Module().(*Module); ok {
+ //TODO: When Rust modules have vendor support, enable this path for PlatformSanitizeable
+
// Check if it's a snapshot module supporting sanitizer
if s, ok := c.linker.(snapshotSanitizer); ok && s.isSanitizerEnabled(t) {
// Set default variation as above.
@@ -1203,23 +1291,23 @@
type sanitizerStaticLibsMap struct {
// libsMap contains one list of modules per each image and each arch.
// e.g. libs[vendor]["arm"] contains arm modules installed to vendor
- libsMap map[imageVariantType]map[string][]string
+ libsMap map[ImageVariantType]map[string][]string
libsMapLock sync.Mutex
- sanitizerType sanitizerType
+ sanitizerType SanitizerType
}
-func newSanitizerStaticLibsMap(t sanitizerType) *sanitizerStaticLibsMap {
+func newSanitizerStaticLibsMap(t SanitizerType) *sanitizerStaticLibsMap {
return &sanitizerStaticLibsMap{
sanitizerType: t,
- libsMap: make(map[imageVariantType]map[string][]string),
+ libsMap: make(map[ImageVariantType]map[string][]string),
}
}
// Add the current module to sanitizer static libs maps
// Each module should pass its exported name as names of Make and Soong can differ.
-func (s *sanitizerStaticLibsMap) add(c *Module, name string) {
- image := c.getImageVariantType()
- arch := c.Arch().ArchType.String()
+func (s *sanitizerStaticLibsMap) add(c LinkableInterface, name string) {
+ image := GetImageVariantType(c)
+ arch := c.Module().Target().Arch.ArchType.String()
s.libsMapLock.Lock()
defer s.libsMapLock.Unlock()
@@ -1238,7 +1326,7 @@
// See build/make/core/binary.mk for more details.
func (s *sanitizerStaticLibsMap) exportToMake(ctx android.MakeVarsContext) {
for _, image := range android.SortedStringKeys(s.libsMap) {
- archMap := s.libsMap[imageVariantType(image)]
+ archMap := s.libsMap[ImageVariantType(image)]
for _, arch := range android.SortedStringKeys(archMap) {
libs := archMap[arch]
sort.Strings(libs)
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 8c5d1a4..8979846 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -94,6 +94,8 @@
android.RegisterModuleType("vendor_snapshot_header", VendorSnapshotHeaderFactory)
android.RegisterModuleType("vendor_snapshot_binary", VendorSnapshotBinaryFactory)
android.RegisterModuleType("vendor_snapshot_object", VendorSnapshotObjectFactory)
+
+ android.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
}
func (vendorSnapshotImage) shouldGenerateSnapshot(ctx android.SingletonContext) bool {
@@ -102,7 +104,7 @@
}
func (vendorSnapshotImage) inImage(m *Module) func() bool {
- return m.inVendor
+ return m.InVendor
}
func (vendorSnapshotImage) available(m *Module) *bool {
@@ -505,8 +507,8 @@
}
type snapshotSanitizer interface {
- isSanitizerEnabled(t sanitizerType) bool
- setSanitizerVariation(t sanitizerType, enabled bool)
+ isSanitizerEnabled(t SanitizerType) bool
+ setSanitizerVariation(t SanitizerType, enabled bool)
}
type snapshotLibraryDecorator struct {
@@ -544,7 +546,7 @@
func (p *snapshotLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path {
m := ctx.Module().(*Module)
- if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ if m.InVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
p.androidMkSuffix = vendorSuffix
} else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
p.androidMkSuffix = recoverySuffix
@@ -611,7 +613,7 @@
return false
}
-func (p *snapshotLibraryDecorator) isSanitizerEnabled(t sanitizerType) bool {
+func (p *snapshotLibraryDecorator) isSanitizerEnabled(t SanitizerType) bool {
switch t {
case cfi:
return p.sanitizerProperties.Cfi.Src != nil
@@ -620,7 +622,7 @@
}
}
-func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) {
+func (p *snapshotLibraryDecorator) setSanitizerVariation(t SanitizerType, enabled bool) {
if !enabled {
return
}
@@ -767,7 +769,7 @@
binName := in.Base()
m := ctx.Module().(*Module)
- if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ if m.InVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
p.androidMkSuffix = vendorSuffix
} else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
p.androidMkSuffix = recoverySuffix
@@ -866,7 +868,7 @@
m := ctx.Module().(*Module)
- if m.inVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
+ if m.InVendor() && vendorSuffixModules(ctx.Config())[m.BaseModuleName()] {
p.androidMkSuffix = vendorSuffix
} else if m.InRecovery() && recoverySuffixModules(ctx.Config())[m.BaseModuleName()] {
p.androidMkSuffix = recoverySuffix
diff --git a/cc/snapshot_utils.go b/cc/snapshot_utils.go
index 77d82f1..3e6444b 100644
--- a/cc/snapshot_utils.go
+++ b/cc/snapshot_utils.go
@@ -77,9 +77,12 @@
}
if _, _, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo); ok {
return ctx.Config().VndkSnapshotBuildArtifacts()
- } else if isVendorSnapshotAware(m, isVendorProprietaryPath(ctx.ModuleDir()), apexInfo) ||
- isRecoverySnapshotAware(m, isRecoveryProprietaryPath(ctx.ModuleDir()), apexInfo) {
- return true
+ }
+
+ for _, image := range []snapshotImage{vendorSnapshotImageSingleton, recoverySnapshotImageSingleton} {
+ if isSnapshotAware(m, image.isProprietaryPath(ctx.ModuleDir()), apexInfo, image) {
+ return true
+ }
}
return false
}
diff --git a/cc/testing.go b/cc/testing.go
index f834205..8d92ea2 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -299,7 +299,7 @@
llndk_library {
name: "libft2.llndk",
symbol_file: "",
- vendor_available: false,
+ private: true,
sdk_version: "current",
}
cc_library {
@@ -577,6 +577,7 @@
RegisterRequiredBuildComponentsForTest(ctx)
ctx.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
ctx.RegisterSingletonType("vendor-snapshot", VendorSnapshotSingleton)
+ ctx.RegisterSingletonType("vendor-fake-snapshot", VendorFakeSnapshotSingleton)
ctx.RegisterSingletonType("recovery-snapshot", RecoverySnapshotSingleton)
return ctx
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 417516b..0a89e47 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -34,6 +34,16 @@
android.OptionalPath{},
true,
vendorSnapshotImageSingleton,
+ false, /* fake */
+}
+
+var vendorFakeSnapshotSingleton = snapshotSingleton{
+ "vendor",
+ "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP",
+ android.OptionalPath{},
+ true,
+ vendorSnapshotImageSingleton,
+ true, /* fake */
}
var recoverySnapshotSingleton = snapshotSingleton{
@@ -42,12 +52,17 @@
android.OptionalPath{},
false,
recoverySnapshotImageSingleton,
+ false, /* fake */
}
func VendorSnapshotSingleton() android.Singleton {
return &vendorSnapshotSingleton
}
+func VendorFakeSnapshotSingleton() android.Singleton {
+ return &vendorFakeSnapshotSingleton
+}
+
func RecoverySnapshotSingleton() android.Singleton {
return &recoverySnapshotSingleton
}
@@ -70,6 +85,11 @@
// associated with this snapshot (e.g., specific to the vendor image,
// recovery image, etc.).
image snapshotImage
+
+ // Whether this singleton is for fake snapshot or not.
+ // Fake snapshot is a snapshot whose prebuilt binaries and headers are empty.
+ // It is much faster to generate, and can be used to inspect dependencies.
+ fake bool
}
var (
@@ -177,25 +197,6 @@
return false
}
-// Determine if a module is going to be included in vendor snapshot or not.
-//
-// Targets of vendor snapshot are "vendor: true" or "vendor_available: true" modules in
-// AOSP. They are not guaranteed to be compatible with older vendor images. (e.g. might
-// depend on newer VNDK) So they are captured as vendor snapshot To build older vendor
-// image and newer system image altogether.
-func isVendorSnapshotAware(m *Module, inVendorProprietaryPath bool, apexInfo android.ApexInfo) bool {
- return isSnapshotAware(m, inVendorProprietaryPath, apexInfo, vendorSnapshotImageSingleton)
-}
-
-// Determine if a module is going to be included in recovery snapshot or not.
-//
-// Targets of recovery snapshot are "recovery: true" or "recovery_available: true"
-// modules in AOSP. They are not guaranteed to be compatible with older recovery images.
-// So they are captured as recovery snapshot To build older recovery image.
-func isRecoverySnapshotAware(m *Module, inRecoveryProprietaryPath bool, apexInfo android.ApexInfo) bool {
- return isSnapshotAware(m, inRecoveryProprietaryPath, apexInfo, recoverySnapshotImageSingleton)
-}
-
// Determines if the module is a candidate for snapshot.
func isSnapshotAware(m *Module, inProprietaryPath bool, apexInfo android.ApexInfo, image snapshotImage) bool {
if !m.Enabled() || m.Properties.HideFromMake {
@@ -246,7 +247,7 @@
if m.sanitize != nil {
// scs and hwasan export both sanitized and unsanitized variants for static and header
// Always use unsanitized variants of them.
- for _, t := range []sanitizerType{scs, hwasan} {
+ for _, t := range []SanitizerType{scs, hwasan} {
if !l.shared() && m.sanitize.isSanitizerEnabled(t) {
return false
}
@@ -351,6 +352,11 @@
*/
snapshotDir := c.name + "-snapshot"
+ if c.fake {
+ // If this is a fake snapshot singleton, place all files under fake/ subdirectory to avoid
+ // collision with real snapshot files
+ snapshotDir = filepath.Join("fake", snapshotDir)
+ }
snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())
includeDir := filepath.Join(snapshotArchDir, "include")
@@ -362,6 +368,15 @@
var headers android.Paths
+ copyFile := copyFileRule
+ if c.fake {
+ // All prebuilt binaries and headers are installed by copyFile function. This makes a fake
+ // snapshot just touch prebuilts and headers, rather than installing real files.
+ copyFile = func(ctx android.SingletonContext, path android.Path, out string) android.OutputPath {
+ return writeStringToFileRule(ctx, "", out)
+ }
+ }
+
// installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file.
// For executables, init_rc and vintf_fragments files are also copied.
installSnapshot := func(m *Module) android.Paths {
@@ -400,7 +415,7 @@
out := filepath.Join(configsDir, path.Base())
if !installedConfigs[out] {
installedConfigs[out] = true
- ret = append(ret, copyFileRule(ctx, path, out))
+ ret = append(ret, copyFile(ctx, path, out))
}
}
@@ -451,7 +466,7 @@
prop.ModuleName += ".cfi"
}
snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem)
- ret = append(ret, copyFileRule(ctx, libPath, snapshotLibOut))
+ ret = append(ret, copyFile(ctx, libPath, snapshotLibOut))
} else {
stem = ctx.ModuleName(m)
}
@@ -465,7 +480,7 @@
// install bin
binPath := m.outputFile.Path()
snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base())
- ret = append(ret, copyFileRule(ctx, binPath, snapshotBinOut))
+ ret = append(ret, copyFile(ctx, binPath, snapshotBinOut))
propOut = snapshotBinOut + ".json"
} else if m.object() {
// object files aren't installed to the device, so their names can conflict.
@@ -473,7 +488,7 @@
objPath := m.outputFile.Path()
snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object",
ctx.ModuleName(m)+filepath.Ext(objPath.Base()))
- ret = append(ret, copyFileRule(ctx, objPath, snapshotObjOut))
+ ret = append(ret, copyFile(ctx, objPath, snapshotObjOut))
propOut = snapshotObjOut + ".json"
} else {
ctx.Errorf("unknown module %q in vendor snapshot", m.String())
@@ -538,16 +553,14 @@
// skip already copied notice file
if !installedNotices[noticeOut] {
installedNotices[noticeOut] = true
- snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
- ctx, m.NoticeFiles(), noticeOut))
+ snapshotOutputs = append(snapshotOutputs, combineNoticesRule(ctx, m.NoticeFiles(), noticeOut))
}
}
})
// install all headers after removing duplicates
for _, header := range android.FirstUniquePaths(headers) {
- snapshotOutputs = append(snapshotOutputs, copyFileRule(
- ctx, header, filepath.Join(includeDir, header.String())))
+ snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String())))
}
// All artifacts are ready. Sort them to normalize ninja and then zip.
diff --git a/cc/vndk.go b/cc/vndk.go
index 31c7787..daae1f7 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -302,7 +302,7 @@
llndkLibraries(mctx.Config())[name] = filename
m.VendorProperties.IsLLNDK = true
- if !Bool(lib.Properties.Vendor_available) {
+ if Bool(lib.Properties.Private) {
vndkPrivateLibraries(mctx.Config())[name] = filename
m.VendorProperties.IsLLNDKPrivate = true
}
@@ -349,7 +349,7 @@
if m.IsVndkPrivate() {
vndkPrivateLibraries(mctx.Config())[name] = filename
}
- if m.VendorProperties.Product_available != nil {
+ if Bool(m.VendorProperties.Product_available) {
vndkProductLibraries(mctx.Config())[name] = filename
}
}
@@ -394,7 +394,7 @@
useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
- return lib.shared() && m.inVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant
+ return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant
}
return false
}
@@ -586,7 +586,7 @@
// !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants.
// !installable: Snapshot only cares about "installable" modules.
// isSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense.
- if !m.inVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() {
+ if !m.InVendor() || !m.installable(apexInfo) || m.isSnapshotPrebuilt() {
return nil, "", false
}
l, ok := m.linker.(snapshotLibraryInterface)
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index ab789aa..532d8fc 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -255,24 +255,13 @@
// Add class loader context for the given library to the map entry for the given SDK version.
func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
- hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) error {
-
- // If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
- // not found. However, this is likely to result is disabling dexpreopt, as it won't be
- // possible to construct class loader context without on-host and on-device library paths.
- strict = strict && !ctx.Config().AllowMissingDependencies()
-
- if hostPath == nil && strict {
- return fmt.Errorf("unknown build path to <uses-library> \"%s\"", lib)
- }
+ hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {
devicePath := UnknownInstallLibraryPath
if installPath == nil {
if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
// Assume that compatibility libraries are installed in /system/framework.
installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
- } else if strict {
- return fmt.Errorf("unknown install path to <uses-library> \"%s\"", lib)
} else {
// For some stub libraries the only known thing is the name of their implementation
// library, but the library itself is unavailable (missing or part of a prebuilt). In
@@ -310,40 +299,17 @@
return nil
}
-// Wrapper around addContext that reports errors.
-func (clcMap ClassLoaderContextMap) addContextOrReportError(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
- hostPath, installPath android.Path, strict bool, nestedClcMap ClassLoaderContextMap) {
-
- err := clcMap.addContext(ctx, sdkVer, lib, hostPath, installPath, strict, nestedClcMap)
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- }
-}
-
-// Add class loader context. Fail on unknown build/install paths.
-func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, lib string,
- hostPath, installPath android.Path) {
-
- clcMap.addContextOrReportError(ctx, AnySdkVersion, lib, hostPath, installPath, true, nil)
-}
-
-// Add class loader context if the library exists. Don't fail on unknown build/install paths.
-func (clcMap ClassLoaderContextMap) MaybeAddContext(ctx android.ModuleInstallPathContext, lib *string,
- hostPath, installPath android.Path) {
-
- if lib != nil {
- clcMap.addContextOrReportError(ctx, AnySdkVersion, *lib, hostPath, installPath, false, nil)
- }
-}
-
// Add class loader context for the given SDK version. Don't fail on unknown build/install paths, as
// libraries with unknown paths still need to be processed by manifest_fixer (which doesn't care
// about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
// are validated later before CLC is used (in validateClassLoaderContext).
-func (clcMap ClassLoaderContextMap) AddContextForSdk(ctx android.ModuleInstallPathContext, sdkVer int,
+func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, sdkVer int,
lib string, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
- clcMap.addContextOrReportError(ctx, sdkVer, lib, hostPath, installPath, false, nestedClcMap)
+ err := clcMap.addContext(ctx, sdkVer, lib, hostPath, installPath, nestedClcMap)
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ }
}
// Merge the other class loader context map into this one, do not override existing entries.
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index 6b6b162..86f7871 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -18,6 +18,7 @@
// For class loader context tests involving .bp files, see TestUsesLibraries in java package.
import (
+ "fmt"
"reflect"
"strings"
"testing"
@@ -50,36 +51,30 @@
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, "a", buildPath(ctx, "a"), installPath(ctx, "a"))
- m.AddContext(ctx, "b", buildPath(ctx, "b"), installPath(ctx, "b"))
-
- // "Maybe" variant in the good case: add as usual.
- c := "c"
- m.MaybeAddContext(ctx, &c, buildPath(ctx, "c"), installPath(ctx, "c"))
-
- // "Maybe" variant in the bad case: don't add library with unknown name, keep going.
- m.MaybeAddContext(ctx, nil, nil, nil)
+ m.AddContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, AnySdkVersion, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, AnySdkVersion, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
// Add some libraries with nested subcontexts.
m1 := make(ClassLoaderContextMap)
- m1.AddContext(ctx, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"))
- m1.AddContext(ctx, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"))
+ m1.AddContext(ctx, AnySdkVersion, "a1", buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
+ m1.AddContext(ctx, AnySdkVersion, "b1", buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
m2 := make(ClassLoaderContextMap)
- m2.AddContext(ctx, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"))
- m2.AddContext(ctx, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"))
- m2.AddContextForSdk(ctx, AnySdkVersion, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
+ m2.AddContext(ctx, AnySdkVersion, "a2", buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
+ m2.AddContext(ctx, AnySdkVersion, "b2", buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
+ m2.AddContext(ctx, AnySdkVersion, "c2", buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
m3 := make(ClassLoaderContextMap)
- m3.AddContext(ctx, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"))
- m3.AddContext(ctx, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"))
+ m3.AddContext(ctx, AnySdkVersion, "a3", buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
+ m3.AddContext(ctx, AnySdkVersion, "b3", buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
- m.AddContextForSdk(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), m2)
+ m.AddContext(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), m2)
// When the same library is both in conditional and unconditional context, it should be removed
// from conditional context.
- m.AddContextForSdk(ctx, 42, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
- m.AddContextForSdk(ctx, AnySdkVersion, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContext(ctx, 42, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContext(ctx, AnySdkVersion, "f", buildPath(ctx, "f"), installPath(ctx, "f"), nil)
// Merge map with implicit root library that is among toplevel contexts => does nothing.
m.AddContextMap(m1, "c")
@@ -88,12 +83,12 @@
m.AddContextMap(m3, "m_g")
// Compatibility libraries with unknown install paths get default paths.
- m.AddContextForSdk(ctx, 29, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil, nil)
- m.AddContextForSdk(ctx, 29, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil, nil)
+ m.AddContext(ctx, 29, AndroidHidlManager, buildPath(ctx, AndroidHidlManager), nil, nil)
+ m.AddContext(ctx, 29, AndroidHidlBase, buildPath(ctx, AndroidHidlBase), nil, nil)
// Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
// needed as a compatibility library if "android.test.runner" is in CLC as well.
- m.AddContextForSdk(ctx, 30, AndroidTestMock, buildPath(ctx, AndroidTestMock), nil, nil)
+ m.AddContext(ctx, 30, AndroidTestMock, buildPath(ctx, AndroidTestMock), nil, nil)
valid, validationError := validateClassLoaderContext(m)
@@ -160,31 +155,19 @@
})
}
-// Test that an unexpected unknown build path causes immediate error.
-func TestCLCUnknownBuildPath(t *testing.T) {
- ctx := testContext()
- m := make(ClassLoaderContextMap)
- err := m.addContext(ctx, AnySdkVersion, "a", nil, nil, true, nil)
- checkError(t, err, "unknown build path to <uses-library> \"a\"")
-}
-
-// Test that an unexpected unknown install path causes immediate error.
-func TestCLCUnknownInstallPath(t *testing.T) {
- ctx := testContext()
- m := make(ClassLoaderContextMap)
- err := m.addContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), nil, true, nil)
- checkError(t, err, "unknown install path to <uses-library> \"a\"")
-}
-
-func TestCLCMaybeAdd(t *testing.T) {
+// Test that unknown library paths cause a validation error.
+func testCLCUnknownPath(t *testing.T, whichPath string) {
ctx := testContext()
m := make(ClassLoaderContextMap)
- a := "a"
- m.MaybeAddContext(ctx, &a, nil, nil)
+ if whichPath == "build" {
+ m.AddContext(ctx, AnySdkVersion, "a", nil, nil, nil)
+ } else {
+ m.AddContext(ctx, AnySdkVersion, "a", buildPath(ctx, "a"), nil, nil)
+ }
// The library should be added to <uses-library> tags by the manifest_fixer.
- t.Run("maybe add", func(t *testing.T) {
+ t.Run("uses libs", func(t *testing.T) {
haveUsesLibs := m.UsesLibs()
wantUsesLibs := []string{"a"}
if !reflect.DeepEqual(wantUsesLibs, haveUsesLibs) {
@@ -192,20 +175,28 @@
}
})
- // But class loader context in such cases should raise an error on validation.
- t.Run("validate", func(t *testing.T) {
- _, err := validateClassLoaderContext(m)
- checkError(t, err, "invalid build path for <uses-library> \"a\"")
- })
+ // But CLC cannot be constructed: there is a validation error.
+ _, err := validateClassLoaderContext(m)
+ checkError(t, err, fmt.Sprintf("invalid %s path for <uses-library> \"a\"", whichPath))
+}
+
+// Test that unknown build path is an error.
+func TestCLCUnknownBuildPath(t *testing.T) {
+ testCLCUnknownPath(t, "build")
+}
+
+// Test that unknown install path is an error.
+func TestCLCUnknownInstallPath(t *testing.T) {
+ testCLCUnknownPath(t, "install")
}
// An attempt to add conditional nested subcontext should fail.
func TestCLCNestedConditional(t *testing.T) {
ctx := testContext()
m1 := make(ClassLoaderContextMap)
- m1.AddContextForSdk(ctx, 42, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m1.AddContext(ctx, 42, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
m := make(ClassLoaderContextMap)
- err := m.addContext(ctx, AnySdkVersion, "b", buildPath(ctx, "b"), installPath(ctx, "b"), true, m1)
+ err := m.addContext(ctx, AnySdkVersion, "b", buildPath(ctx, "b"), installPath(ctx, "b"), m1)
checkError(t, err, "nested class loader context shouldn't have conditional part")
}
@@ -214,10 +205,10 @@
func TestCLCSdkVersionOrder(t *testing.T) {
ctx := testContext()
m := make(ClassLoaderContextMap)
- m.AddContextForSdk(ctx, 28, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContextForSdk(ctx, 29, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContextForSdk(ctx, 30, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
- m.AddContextForSdk(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+ m.AddContext(ctx, 28, "a", buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, 29, "b", buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, 30, "c", buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "d", buildPath(ctx, "d"), installPath(ctx, "d"), nil)
valid, validationError := validateClassLoaderContext(m)
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index c6181bc..2b3fbae 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -46,7 +46,10 @@
return module
}
-var dependencyTag = struct{ blueprint.BaseDependencyTag }{}
+var dependencyTag = struct {
+ blueprint.BaseDependencyTag
+ android.InstallAlwaysNeededDependencyTag
+}{}
func (f *filesystem) DepsMutator(ctx android.BottomUpMutatorContext) {
f.AddDeps(ctx, dependencyTag)
@@ -80,7 +83,7 @@
Text(">").Output(propFile).
Implicit(mkuserimg)
- f.output = android.PathForModuleOut(ctx, "filesystem.img").OutputPath
+ f.output = android.PathForModuleOut(ctx, f.installFileName()).OutputPath
builder.Command().BuiltTool("build_image").
Text(rootDir.String()). // input directory
Input(propFile).
@@ -109,3 +112,16 @@
},
}}
}
+
+// Filesystem is the public interface for the filesystem struct. Currently, it's only for the apex
+// package to have access to the output file.
+type Filesystem interface {
+ android.Module
+ OutputPath() android.Path
+}
+
+var _ Filesystem = (*filesystem)(nil)
+
+func (f *filesystem) OutputPath() android.Path {
+ return f.output
+}
diff --git a/go.mod b/go.mod
index 117fa65..7297dea 100644
--- a/go.mod
+++ b/go.mod
@@ -8,4 +8,4 @@
replace github.com/google/blueprint v0.0.0 => ../blueprint
-go 1.15.6
+go 1.15
diff --git a/java/app.go b/java/app.go
index 574472c..e6c9a2d 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1226,7 +1226,7 @@
if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
dep := ctx.OtherModuleName(m)
if lib, ok := m.(UsesLibraryDependency); ok {
- clcMap.AddContextForSdk(ctx, tag.sdkVersion, dep,
+ clcMap.AddContext(ctx, tag.sdkVersion, dep,
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
diff --git a/java/java.go b/java/java.go
index 82b53be..f684a00 100644
--- a/java/java.go
+++ b/java/java.go
@@ -3305,7 +3305,7 @@
}
if implicitSdkLib != nil {
- clcMap.AddContextForSdk(ctx, dexpreopt.AnySdkVersion, *implicitSdkLib,
+ clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *implicitSdkLib,
dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
depName := ctx.OtherModuleName(depModule)
diff --git a/rust/binary.go b/rust/binary.go
index c2d97f3..ca07d07 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -164,3 +164,7 @@
}
return binary.baseCompiler.stdLinkage(ctx)
}
+
+func (binary *binaryDecorator) isDependencyRoot() bool {
+ return true
+}
diff --git a/rust/compiler.go b/rust/compiler.go
index ee88a27..bcea6cc 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -236,6 +236,10 @@
panic(fmt.Errorf("baseCrater doesn't know how to crate things!"))
}
+func (compiler *baseCompiler) isDependencyRoot() bool {
+ return false
+}
+
func (compiler *baseCompiler) compilerDeps(ctx DepsContext, deps Deps) Deps {
deps.Rlibs = append(deps.Rlibs, compiler.Properties.Rlibs...)
deps.Dylibs = append(deps.Dylibs, compiler.Properties.Dylibs...)
diff --git a/rust/config/global.go b/rust/config/global.go
index 22d9567..b7fff4a 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -44,6 +44,7 @@
GlobalRustFlags = []string{
"--remap-path-prefix $$(pwd)=",
"-C codegen-units=1",
+ "-C debuginfo=2",
"-C opt-level=3",
"-C relocation-model=pic",
}
diff --git a/rust/image.go b/rust/image.go
index af8c3b2..5e55e22 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -100,13 +100,13 @@
platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
// Rust does not support installing to the product image yet.
- if mod.VendorProperties.Product_available != nil {
+ if Bool(mod.VendorProperties.Product_available) {
mctx.PropertyErrorf("product_available",
"Rust modules do not yet support being available to the product image")
} else if mctx.ProductSpecific() {
mctx.PropertyErrorf("product_specific",
"Rust modules do not yet support installing to the product image.")
- } else if mod.VendorProperties.Double_loadable != nil {
+ } else if Bool(mod.VendorProperties.Double_loadable) {
mctx.PropertyErrorf("double_loadable",
"Rust modules do not yet support double loading")
}
@@ -114,7 +114,7 @@
coreVariantNeeded := true
var vendorVariants []string
- if mod.VendorProperties.Vendor_available != nil {
+ if Bool(mod.VendorProperties.Vendor_available) {
if vendorSpecific {
mctx.PropertyErrorf("vendor_available",
"doesn't make sense at the same time as `vendor: true`, `proprietary: true`, or `device_specific:true`")
diff --git a/rust/rust.go b/rust/rust.go
index 1053846..1fa97af 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -106,6 +106,42 @@
hideApexVariantFromMake bool
}
+func (mod *Module) Header() bool {
+ //TODO: If Rust libraries provide header variants, this needs to be updated.
+ return false
+}
+
+func (mod *Module) SetPreventInstall() {
+ mod.Properties.PreventInstall = true
+}
+
+// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
+func (mod *Module) InVendor() bool {
+ return mod.Properties.ImageVariationPrefix == cc.VendorVariationPrefix
+}
+
+func (mod *Module) SetHideFromMake() {
+ mod.Properties.HideFromMake = true
+}
+
+func (mod *Module) SanitizePropDefined() bool {
+ return false
+}
+
+func (mod *Module) IsDependencyRoot() bool {
+ if mod.compiler != nil {
+ return mod.compiler.isDependencyRoot()
+ }
+ panic("IsDependencyRoot called on a non-compiler Rust module")
+}
+
+func (mod *Module) IsPrebuilt() bool {
+ if _, ok := mod.compiler.(*prebuiltLibraryDecorator); ok {
+ return true
+ }
+ return false
+}
+
func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
@@ -281,6 +317,7 @@
SetDisabled()
stdLinkage(ctx *depsContext) RustLinkage
+ isDependencyRoot() bool
}
type exportedFlagsProducer interface {
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 8db33a3..18749b5 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -345,15 +345,8 @@
depTag := ctx.OtherModuleDependencyTag(dep)
switch depTag {
case shTestDataBinsTag, shTestDataDeviceBinsTag:
- if cc, isCc := dep.(*cc.Module); isCc {
- s.addToDataModules(ctx, cc.OutputFile().Path().Base(), cc.OutputFile().Path())
- return
- }
- property := "data_bins"
- if depTag == shTestDataDeviceBinsTag {
- property = "data_device_bins"
- }
- ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
+ path := android.OutputFileForModule(ctx, dep, "")
+ s.addToDataModules(ctx, path.Base(), path)
case shTestDataLibsTag, shTestDataDeviceLibsTag:
if cc, isCc := dep.(*cc.Module); isCc {
// Copy to an intermediate output directory to append "lib[64]" to the path,