diff --git a/cc/androidmk.go b/cc/androidmk.go index a9ba1a9e6..58bb57ca4 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -546,7 +546,7 @@ func (c *snapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entrie entries.SubName += c.baseProperties.Androidmk_suffix - entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { + entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) { c.libraryDecorator.androidMkWriteExportedFlags(entries) if c.shared() || c.static() { @@ -567,6 +567,10 @@ func (c *snapshotLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entrie if c.tocFile.Valid() { entries.SetString("LOCAL_SOONG_TOC", c.tocFile.String()) } + + if c.shared() && len(c.Properties.Overrides) > 0 { + entries.SetString("LOCAL_OVERRIDES_MODULES", strings.Join(makeOverrideModuleNames(ctx, c.Properties.Overrides), " ")) + } } if !c.shared() { // static or header diff --git a/cc/binary.go b/cc/binary.go index 3351fd732..69cf4ac38 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -540,6 +540,12 @@ func (binary *binaryDecorator) hostToolPath() android.OptionalPath { return binary.toolPath } +func (binary *binaryDecorator) overriddenModules() []string { + return binary.Properties.Overrides +} + +var _ overridable = (*binaryDecorator)(nil) + func init() { pctx.HostBinToolVariable("verifyHostBionicCmd", "host_bionic_verify") } diff --git a/cc/cc.go b/cc/cc.go index 1c845f622..598f6be23 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -616,6 +616,10 @@ type xref interface { XrefCcFiles() android.Paths } +type overridable interface { + overriddenModules() []string +} + type libraryDependencyKind int const ( @@ -3637,6 +3641,13 @@ func (c *Module) UniqueApexVariations() bool { return c.UseVndk() && c.IsVndk() } +func (c *Module) overriddenModules() []string { + if o, ok := c.linker.(overridable); ok { + return o.overriddenModules() + } + return nil +} + var _ snapshot.RelativeInstallPath = (*Module)(nil) type moduleType int diff --git a/cc/library.go b/cc/library.go index 441eb7905..659480890 100644 --- a/cc/library.go +++ b/cc/library.go @@ -2231,6 +2231,12 @@ func (library *libraryDecorator) getAPIListCoverageXMLPath() android.ModuleOutPa return library.apiListCoverageXmlPath } +func (library *libraryDecorator) overriddenModules() []string { + return library.Properties.Overrides +} + +var _ overridable = (*libraryDecorator)(nil) + var versioningMacroNamesListKey = android.NewOnceKey("versioningMacroNamesList") // versioningMacroNamesList returns a singleton map, where keys are "version macro names", diff --git a/cc/testing.go b/cc/testing.go index e42b9fab7..6a655db9e 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -15,6 +15,7 @@ package cc import ( + "encoding/json" "path/filepath" "testing" @@ -736,3 +737,21 @@ func AssertExcludeFromRecoverySnapshotIs(t *testing.T, ctx *android.TestContext, t.Errorf("expected %q ExcludeFromRecoverySnapshot to be %t", m.String(), expected) } } + +func checkOverrides(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, jsonPath string, expected []string) { + out := singleton.MaybeOutput(jsonPath) + content := android.ContentFromFileRuleForTests(t, out) + + var flags snapshotJsonFlags + if err := json.Unmarshal([]byte(content), &flags); err != nil { + t.Errorf("Error while unmarshalling json %q: %w", jsonPath, err) + return + } + + for _, moduleName := range expected { + if !android.InList(moduleName, flags.Overrides) { + t.Errorf("expected %q to be in %q: %q", moduleName, flags.Overrides, content) + return + } + } +} diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 77e6f6ffe..2dcf26eac 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -239,6 +239,9 @@ var ccSnapshotAction snapshot.GenerateSnapshotAction = func(s snapshot.SnapshotS } prop.RuntimeLibs = m.SnapshotRuntimeLibs() prop.Required = m.RequiredModuleNames() + if o, ok := m.(overridable); ok { + prop.Overrides = o.overriddenModules() + } for _, path := range m.InitRc() { prop.InitRc = append(prop.InitRc, filepath.Join("configs", path.Base())) } diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go index 2bb43abe8..6a9877885 100644 --- a/cc/vendor_snapshot_test.go +++ b/cc/vendor_snapshot_test.go @@ -41,6 +41,13 @@ func TestVendorSnapshotCapture(t *testing.T) { nocrt: true, } + cc_library { + name: "libvendor_override", + vendor: true, + nocrt: true, + overrides: ["libvendor"], + } + cc_library { name: "libvendor_available", vendor_available: true, @@ -65,6 +72,13 @@ func TestVendorSnapshotCapture(t *testing.T) { nocrt: true, } + cc_binary { + name: "vendor_bin_override", + vendor: true, + nocrt: true, + overrides: ["vendor_bin"], + } + cc_prebuilt_library_static { name: "libb", vendor_available: true, @@ -150,6 +164,8 @@ func TestVendorSnapshotCapture(t *testing.T) { jsonFiles = append(jsonFiles, filepath.Join(binaryDir, "vendor_bin.json"), filepath.Join(binaryDir, "vendor_available_bin.json")) + + checkOverrides(t, ctx, snapshotSingleton, filepath.Join(binaryDir, "vendor_bin_override.json"), []string{"vendor_bin"}) } // For header libraries, all vendor:true and vendor_available modules are captured. @@ -161,6 +177,8 @@ func TestVendorSnapshotCapture(t *testing.T) { objectDir := filepath.Join(snapshotVariantPath, archDir, "object") CheckSnapshot(t, ctx, snapshotSingleton, "obj", "obj.o", objectDir, objectVariant) jsonFiles = append(jsonFiles, filepath.Join(objectDir, "obj.o.json")) + + checkOverrides(t, ctx, snapshotSingleton, filepath.Join(sharedDir, "libvendor_override.so.json"), []string{"libvendor"}) } for _, jsonFile := range jsonFiles { @@ -506,11 +524,13 @@ func TestVendorSnapshotUse(t *testing.T) { ], shared_libs: [ "libvendor", + "libvendor_override", "libvendor_available", "lib64", ], binaries: [ "bin", + "bin_override", ], }, arm: { @@ -526,6 +546,7 @@ func TestVendorSnapshotUse(t *testing.T) { ], shared_libs: [ "libvendor", + "libvendor_override", "libvendor_available", "lib32", ], @@ -577,6 +598,30 @@ func TestVendorSnapshotUse(t *testing.T) { }, } + vendor_snapshot_shared { + name: "libvendor_override", + version: "31", + target_arch: "arm64", + compile_multilib: "both", + vendor: true, + overrides: ["libvendor"], + shared_libs: [ + "libvendor_without_snapshot", + "libvendor_available", + "libvndk", + ], + arch: { + arm64: { + src: "override/libvendor.so", + export_include_dirs: ["include/libvendor"], + }, + arm: { + src: "override/libvendor.so", + export_include_dirs: ["include/libvendor"], + }, + }, + } + vendor_snapshot_static { name: "lib32", version: "31", @@ -744,6 +789,21 @@ func TestVendorSnapshotUse(t *testing.T) { symlinks: ["binfoo", "binbar"], } + vendor_snapshot_binary { + name: "bin_override", + version: "31", + target_arch: "arm64", + compile_multilib: "64", + vendor: true, + overrides: ["bin"], + arch: { + arm64: { + src: "override/bin", + }, + }, + symlinks: ["binfoo", "binbar"], + } + vendor_snapshot_binary { name: "bin32", version: "31", @@ -793,6 +853,7 @@ func TestVendorSnapshotUse(t *testing.T) { "framework/symbol.txt": nil, "vendor/Android.bp": []byte(vendorProprietaryBp), "vendor/bin": nil, + "vendor/override/bin": nil, "vendor/bin32": nil, "vendor/bin.cpp": nil, "vendor/client.cpp": nil, @@ -806,6 +867,7 @@ func TestVendorSnapshotUse(t *testing.T) { "vendor/libvendor.a": nil, "vendor/libvendor.cfi.a": nil, "vendor/libvendor.so": nil, + "vendor/override/libvendor.so": nil, "vendor/lib32.a": nil, "vendor/lib32.so": nil, "vendor/lib64.a": nil, @@ -958,6 +1020,23 @@ func TestVendorSnapshotUse(t *testing.T) { if inList(binaryVariant, binVariants) { t.Errorf("bin must not have variant %#v, but it does", sharedVariant) } + + // test overrides property + binOverrideModule := ctx.ModuleForTests("bin_override.vendor_binary.31.arm64", binaryVariant) + binOverrideModule.Output("bin") + binOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, binOverrideModule.Module()) + binOverrideEntry := binOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"] + if !inList("bin", binOverrideEntry) { + t.Errorf("bin_override must override bin but was %q\n", binOverrideEntry) + } + + libvendorOverrideModule := ctx.ModuleForTests("libvendor_override.vendor_shared.31.arm64", sharedVariant) + libvendorOverrideModule.Output("libvendor.so") + libvendorOverrideMkEntries := android.AndroidMkEntriesForTest(t, ctx, libvendorOverrideModule.Module()) + libvendorOverrideEntry := libvendorOverrideMkEntries[0].EntryMap["LOCAL_OVERRIDES_MODULES"] + if !inList("libvendor", libvendorOverrideEntry) { + t.Errorf("libvendor_override must override libvendor but was %q\n", libvendorOverrideEntry) + } } func TestVendorSnapshotSanitizer(t *testing.T) { diff --git a/snapshot/snapshot_base.go b/snapshot/snapshot_base.go index 8e5dfe4a2..809ca3d11 100644 --- a/snapshot/snapshot_base.go +++ b/snapshot/snapshot_base.go @@ -118,5 +118,6 @@ type SnapshotJsonFlags struct { CrateName string `json:",omitempty"` // dependencies - Required []string `json:",omitempty"` + Required []string `json:",omitempty"` + Overrides []string `json:",omitempty"` }