diff options
| -rw-r--r-- | apex/Android.bp | 1 | ||||
| -rw-r--r-- | apex/allowed_deps.txt | 1 | ||||
| -rw-r--r-- | apex/apex.go | 17 | ||||
| -rw-r--r-- | bazel/aquery.go | 51 | ||||
| -rw-r--r-- | cc/cc.go | 49 | ||||
| -rw-r--r-- | cc/cc_test.go | 29 | ||||
| -rw-r--r-- | cc/fuzz.go | 2 | ||||
| -rw-r--r-- | cc/image.go | 74 | ||||
| -rw-r--r-- | cc/linkable.go | 82 | ||||
| -rw-r--r-- | cc/llndk_library.go | 8 | ||||
| -rw-r--r-- | cc/sanitize.go | 248 | ||||
| -rw-r--r-- | cc/snapshot_prebuilt.go | 18 | ||||
| -rw-r--r-- | cc/snapshot_utils.go | 9 | ||||
| -rw-r--r-- | cc/testing.go | 3 | ||||
| -rw-r--r-- | cc/vendor_snapshot.go | 69 | ||||
| -rw-r--r-- | cc/vndk.go | 8 | ||||
| -rw-r--r-- | dexpreopt/class_loader_context.go | 46 | ||||
| -rw-r--r-- | dexpreopt/class_loader_context_test.go | 97 | ||||
| -rw-r--r-- | filesystem/filesystem.go | 20 | ||||
| -rw-r--r-- | go.mod | 2 | ||||
| -rwxr-xr-x | java/app.go | 2 | ||||
| -rw-r--r-- | java/java.go | 2 | ||||
| -rw-r--r-- | rust/binary.go | 4 | ||||
| -rw-r--r-- | rust/compiler.go | 4 | ||||
| -rw-r--r-- | rust/config/global.go | 1 | ||||
| -rw-r--r-- | rust/image.go | 6 | ||||
| -rw-r--r-- | rust/rust.go | 37 | ||||
| -rw-r--r-- | sh/sh_binary.go | 11 |
28 files changed, 571 insertions, 330 deletions
diff --git a/apex/Android.bp b/apex/Android.bp index 9e8c30d26..e3a547cbf 100644 --- a/apex/Android.bp +++ b/apex/Android.bp @@ -7,6 +7,7 @@ bootstrap_go_package { "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 69bf64f00..adea9f0c0 100644 --- a/apex/allowed_deps.txt +++ b/apex/allowed_deps.txt @@ -384,6 +384,7 @@ libquiche_ffi(minSdkVersion:29) 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 21820696e..a18e34bb2 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -30,6 +30,7 @@ import ( "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 @@ type apexBundleProperties struct { // 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 @@ var ( 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 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) { 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 @@ func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path 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 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { } 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 69d4fde14..404be8ce0 100644 --- a/bazel/aquery.go +++ b/bazel/aquery.go @@ -16,6 +16,8 @@ package bazel import ( "encoding/json" + "fmt" + "path/filepath" "strings" "github.com/google/blueprint/proptools" @@ -24,8 +26,14 @@ import ( // 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 @@ type KeyValuePair struct { // 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 depSetOfFiles struct { 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 @@ type actionGraphContainer struct { Artifacts []artifact Actions []action DepSetOfFiles []depSetOfFiles + PathFragments []pathFragment } // BuildStatement contains information to register a build statement corresponding (one to one) @@ -80,11 +89,20 @@ func AqueryBuildStatements(aqueryJsonProto []byte) []BuildStatement { var aqueryResult actionGraphContainer json.Unmarshal(aqueryJsonProto, &aqueryResult) - artifactIdToPath := map[string]string{} + pathFragments := map[int]pathFragment{} + for _, pathFragment := range aqueryResult.PathFragments { + pathFragments[pathFragment.Id] = pathFragment + } + artifactIdToPath := map[int]string{} for _, artifact := range aqueryResult.Artifacts { - artifactIdToPath[artifact.Id] = artifact.ExecPath + artifactPath, err := expandPathFragment(artifact.PathFragmentId, pathFragments) + if err != nil { + // TODO(cparsons): Better error handling. + panic(err.Error()) + } + artifactIdToPath[artifact.Id] = artifactPath } - depsetIdToArtifactIds := map[string][]string{} + depsetIdToArtifactIds := map[int][]int{} for _, depset := range aqueryResult.DepSetOfFiles { depsetIdToArtifactIds[depset.Id] = depset.DirectArtifactIds } @@ -114,3 +132,18 @@ func AqueryBuildStatements(aqueryJsonProto []byte) []BuildStatement { 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 +} @@ -57,14 +57,14 @@ func RegisterCCBuildComponents(ctx android.RegistrationContext) { }) 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 @@ type VendorProperties struct { 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 @@ type Module struct { 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 @@ func (c *Module) Init() android.Module { // 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) IsLlndkPublic() bool { 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) isImplementationForLLNDKPublic() bool { 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) staticBinary() bool { } func (ctx *moduleContextImpl) header() bool { - return ctx.mod.header() + return ctx.mod.Header() } func (ctx *moduleContextImpl) binary() bool { @@ -1429,6 +1429,10 @@ func (c *Module) Prebuilt() *android.Prebuilt { 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 @@ func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, 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 @@ func (c *Module) staticBinary() bool { 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 71c6b7091..3502d5f36 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -234,9 +234,6 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string 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 @@ func TestVndkWhenVndkVersionIsNotSet(t *testing.T) { } 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 TestVndkWhenVndkVersionIsNotSet(t *testing.T) { 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 @@ func TestVndkModuleError(t *testing.T) { } `) - 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 @@ func TestVendorSnapshotCapture(t *testing.T) { 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 @@ func TestVendorSnapshotExcludeInVendorProprietaryPathErrors(t *testing.T) { `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 @@ func TestVendorSnapshotExcludeWithVendorAvailable(t *testing.T) { `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 @@ func TestMakeLinkType(t *testing.T) { } llndk_library { name: "libllndkprivate.llndk", - vendor_available: false, + private: true, symbol_file: "", }` diff --git a/cc/fuzz.go b/cc/fuzz.go index aa9038ae2..d7da5abea 100644 --- a/cc/fuzz.go +++ b/cc/fuzz.go @@ -321,7 +321,7 @@ func NewFuzz(hod android.HostOrDeviceSupported) *Module { 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 11ba55c84..13095fca5 100644 --- a/cc/image.go +++ b/cc/image.go @@ -26,36 +26,18 @@ import ( 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 @@ const ( ) 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) inProduct() bool { } func (ctx *moduleContextImpl) inVendor() bool { - return ctx.mod.inVendor() + return ctx.mod.InVendor() } func (ctx *moduleContextImpl) inRamdisk() bool { @@ -98,18 +82,12 @@ func (ctx *moduleContextImpl) inRecovery() bool { // 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 @@ func (c *Module) InProduct() bool { } // 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 @@ func visitPropsAndCompareVendorAndProductProps(v reflect.Value) bool { // 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 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { 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 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { 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 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { "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 489063f1f..ab5a552c1 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -6,6 +6,59 @@ import ( "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 @@ type LinkableInterface interface { SetShared() Static() bool Shared() bool + Header() bool + IsPrebuilt() bool Toc() android.OptionalPath Host() bool @@ -40,6 +95,8 @@ type LinkableInterface interface { InRecovery() bool OnlyInRecovery() bool + InVendor() bool + UseSdk() bool UseVndk() bool MustUseVendorVariant() bool @@ -56,6 +113,11 @@ type LinkableInterface interface { 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 @@ var ( 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 0c4bcfdbc..bd48501a3 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -55,13 +55,6 @@ type llndkLibraryProperties struct { // 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 @@ func NewLLndkStubLibrary() *Module { 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 bb92a882d..599261167 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -71,7 +71,7 @@ var ( "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 @@ func boolPtr(v bool) *bool { } 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 @@ func (t sanitizerType) variationName() string { 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 @@ func (t sanitizerType) name() string { 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 @@ func (sanitize *sanitize) inSanitizerDir() bool { 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 @@ func (sanitize *sanitize) getSanitizerBoolPtr(t sanitizerType) *bool { 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 @@ func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { 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 @@ func (sanitize *sanitize) SetSanitizer(t sanitizerType, b bool) { // 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 @@ func (sanitize *sanitize) isSanitizerExplicitlyDisabled(t sanitizerType) bool { // 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 @@ func (sanitize *sanitize) isSanitizerEnabled(t sanitizerType) bool { 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 isSanitizableDependencyTag(tag blueprint.DependencyTag) bool { } } +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 @@ func needsCfiForVendorSnapshot(mctx android.TopDownMutatorContext) bool { return false } - c := mctx.Module().(*Module) + c := mctx.Module().(PlatformSanitizeable) + + if !c.InVendor() { + return false + } - if !c.inVendor() { + if !c.StaticallyLinked() { return false } - if !c.static() { + if c.IsPrebuilt() { return false } - if c.Prebuilt() != nil { + if !c.SanitizerSupported(cfi) { return false } - return c.sanitize != nil && - !Bool(c.sanitize.Properties.Sanitize.Never) && - !c.sanitize.isSanitizerExplicitlyDisabled(cfi) + 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 sanitizerDepsMutator(t sanitizerType) func(android.TopDownMutatorContext) { } } +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 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { 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 @@ type Sanitizeable interface { 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 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { // 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 + 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() { + 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 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { // 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 @@ func sanitizerMutator(t sanitizerType) func(android.BottomUpMutatorContext) { 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 @@ func (s *sanitizerStaticLibsMap) add(c *Module, name string) { // 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 8c5d1a405..89798468c 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -94,6 +94,8 @@ func (vendorSnapshotImage) init() { 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) shouldGenerateSnapshot(ctx android.SingletonContext) } func (vendorSnapshotImage) inImage(m *Module) func() bool { - return m.inVendor + return m.InVendor } func (vendorSnapshotImage) available(m *Module) *bool { @@ -505,8 +507,8 @@ type snapshotLibraryProperties struct { } 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) matchesWithDevice(config android.DeviceConfig 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 @@ func (p *snapshotLibraryDecorator) nativeCoverage() bool { 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) isSanitizerEnabled(t sanitizerType) bool { } } -func (p *snapshotLibraryDecorator) setSanitizerVariation(t sanitizerType, enabled bool) { +func (p *snapshotLibraryDecorator) setSanitizerVariation(t SanitizerType, enabled bool) { if !enabled { return } @@ -767,7 +769,7 @@ func (p *snapshotBinaryDecorator) link(ctx ModuleContext, flags Flags, deps Path 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 @@ func (p *snapshotObjectLinker) link(ctx ModuleContext, flags Flags, deps PathDep 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 77d82f1b5..3e6444bc0 100644 --- a/cc/snapshot_utils.go +++ b/cc/snapshot_utils.go @@ -77,9 +77,12 @@ func shouldCollectHeadersForSnapshot(ctx android.ModuleContext, m *Module, apexI } 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 f834205cf..8d92ea2ac 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -299,7 +299,7 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { llndk_library { name: "libft2.llndk", symbol_file: "", - vendor_available: false, + private: true, sdk_version: "current", } cc_library { @@ -577,6 +577,7 @@ func CreateTestContext(config android.Config) *android.TestContext { 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 417516bf9..0a89e471c 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -34,6 +34,16 @@ var vendorSnapshotSingleton = snapshotSingleton{ 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 @@ var recoverySnapshotSingleton = snapshotSingleton{ 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 @@ type snapshotSingleton struct { // 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 @@ func isRecoveryProprietaryModule(ctx android.BaseModuleContext) bool { 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 @@ func isSnapshotAware(m *Module, inProprietaryPath bool, apexInfo android.ApexInf 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { */ 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { 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 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // 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 31c77874e..daae1f7bd 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -302,7 +302,7 @@ func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { 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 @@ func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { 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 @@ func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool { 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 @@ func isVndkSnapshotAware(config android.DeviceConfig, m *Module, // !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 ab789aa23..532d8fc06 100644 --- a/dexpreopt/class_loader_context.go +++ b/dexpreopt/class_loader_context.go @@ -255,24 +255,13 @@ const AnySdkVersion int = android.FutureApiLevelInt // 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 @@ func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathCont 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 6b6b1629a..86f7871a0 100644 --- a/dexpreopt/class_loader_context_test.go +++ b/dexpreopt/class_loader_context_test.go @@ -18,6 +18,7 @@ package dexpreopt // For class loader context tests involving .bp files, see TestUsesLibraries in java package. import ( + "fmt" "reflect" "strings" "testing" @@ -50,36 +51,30 @@ func TestCLC(t *testing.T) { 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 @@ func TestCLC(t *testing.T) { 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 @@ func TestCLC(t *testing.T) { }) } -// 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 @@ func TestCLCMaybeAdd(t *testing.T) { } }) - // 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 TestCLCNestedConditional(t *testing.T) { 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 c6181bc15..2b3fbaeac 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -46,7 +46,10 @@ func filesystemFactory() android.Module { 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 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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 @@ func (f *filesystem) AndroidMkEntries() []android.AndroidMkEntries { }, }} } + +// 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 +} @@ -8,4 +8,4 @@ replace github.com/golang/protobuf v0.0.0 => ../../external/golang-protobuf 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 574472c1b..e6c9a2d98 100755 --- a/java/app.go +++ b/java/app.go @@ -1226,7 +1226,7 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext 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 82b53be1d..f684a00e7 100644 --- a/java/java.go +++ b/java/java.go @@ -3305,7 +3305,7 @@ func addCLCFromDep(ctx android.ModuleContext, depModule android.Module, } 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 c2d97f3ab..ca07d07c1 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -164,3 +164,7 @@ func (binary *binaryDecorator) stdLinkage(ctx *depsContext) RustLinkage { } return binary.baseCompiler.stdLinkage(ctx) } + +func (binary *binaryDecorator) isDependencyRoot() bool { + return true +} diff --git a/rust/compiler.go b/rust/compiler.go index ee88a273f..bcea6cccc 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -236,6 +236,10 @@ func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathD 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 22d9567df..b7fff4a32 100644 --- a/rust/config/global.go +++ b/rust/config/global.go @@ -44,6 +44,7 @@ var ( 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 af8c3b2fd..5e55e22c9 100644 --- a/rust/image.go +++ b/rust/image.go @@ -100,13 +100,13 @@ func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { 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 @@ func (mod *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { 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 105384676..1fa97af96 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -106,6 +106,42 @@ type Module struct { 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 @@ type compiler interface { SetDisabled() stdLinkage(ctx *depsContext) RustLinkage + isDependencyRoot() bool } type exportedFlagsProducer interface { diff --git a/sh/sh_binary.go b/sh/sh_binary.go index 8db33a3a9..18749b533 100644 --- a/sh/sh_binary.go +++ b/sh/sh_binary.go @@ -345,15 +345,8 @@ func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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, |