diff options
| -rw-r--r-- | android/apex.go | 17 | ||||
| -rw-r--r-- | apex/apex_test.go | 84 | ||||
| -rw-r--r-- | cc/cc.go | 31 |
3 files changed, 111 insertions, 21 deletions
diff --git a/android/apex.go b/android/apex.go index a5ff44264..257bdad03 100644 --- a/android/apex.go +++ b/android/apex.go @@ -453,6 +453,23 @@ func (m *ApexModuleBase) checkApexAvailableProperty(mctx BaseModuleContext) { } } +// AvailableToSameApexes returns true if the two modules are apex_available to +// exactly the same set of APEXes (and platform), i.e. if their apex_available +// properties have the same elements. +func AvailableToSameApexes(mod1, mod2 ApexModule) bool { + mod1ApexAvail := SortedUniqueStrings(mod1.apexModuleBase().ApexProperties.Apex_available) + mod2ApexAvail := SortedUniqueStrings(mod2.apexModuleBase().ApexProperties.Apex_available) + if len(mod1ApexAvail) != len(mod2ApexAvail) { + return false + } + for i, v := range mod1ApexAvail { + if v != mod2ApexAvail[i] { + return false + } + } + return true +} + type byApexName []ApexInfo func (a byApexName) Len() int { return len(a) } diff --git a/apex/apex_test.go b/apex/apex_test.go index e0cefa1f9..4fb2109a3 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -6859,21 +6859,77 @@ func TestTestFor(t *testing.T) { } `) - // the test 'mytest' is a test for the apex, therefore is linked to the + ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) { + ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").RelativeToTop().Args["libFlags"], " ") + mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) }) + android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags) + } + + // These modules are tests for the apex, therefore are linked to the // actual implementation of mylib instead of its stub. - ldFlags := ctx.ModuleForTests("mytest", "android_arm64_armv8-a").Rule("ld").Args["libFlags"] - ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so") - ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so") - - // The same should be true for cc_library - ldFlags = ctx.ModuleForTests("mytestlib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"] - ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so") - ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so") - - // ... and for cc_benchmark - ldFlags = ctx.ModuleForTests("mybench", "android_arm64_armv8-a").Rule("ld").Args["libFlags"] - ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so") - ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so") + ensureLinkedLibIs("mytest", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") + ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") + ensureLinkedLibIs("mybench", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") +} + +func TestIndirectTestFor(t *testing.T) { + ctx := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib", "myprivlib"], + updatable: false, + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + stubs: { + versions: ["1"], + }, + apex_available: ["myapex"], + } + + cc_library { + name: "myprivlib", + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + shared_libs: ["mylib"], + apex_available: ["myapex"], + } + + cc_library { + name: "mytestlib", + srcs: ["mylib.cpp"], + system_shared_libs: [], + shared_libs: ["myprivlib"], + stl: "none", + test_for: ["myapex"], + } + `) + + ensureLinkedLibIs := func(mod, variant, linkedLib, expectedVariant string) { + ldFlags := strings.Split(ctx.ModuleForTests(mod, variant).Rule("ld").RelativeToTop().Args["libFlags"], " ") + mylibLdFlags := android.FilterListPred(ldFlags, func(s string) bool { return strings.HasPrefix(s, linkedLib) }) + android.AssertArrayString(t, "unexpected "+linkedLib+" link library for "+mod, []string{linkedLib + expectedVariant}, mylibLdFlags) + } + + // The platform variant of mytestlib links to the platform variant of the + // internal myprivlib. + ensureLinkedLibIs("mytestlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/myprivlib/", "android_arm64_armv8-a_shared/myprivlib.so") + + // The platform variant of myprivlib links to the platform variant of mylib + // and bypasses its stubs. + ensureLinkedLibIs("myprivlib", "android_arm64_armv8-a_shared", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so") } // TODO(jungjw): Move this to proptools @@ -2631,14 +2631,31 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules, // always link to non-stub variant useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap() - // Another exception: if this module is bundled with an APEX, then - // it is linked with the non-stub variant of a module in the APEX - // as if this is part of the APEX. - testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo) - for _, apexContents := range testFor.ApexContents { - if apexContents.DirectlyInApex(depName) { + if useStubs { + // Another exception: if this module is a test for an APEX, then + // it is linked with the non-stub variant of a module in the APEX + // as if this is part of the APEX. + testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo) + for _, apexContents := range testFor.ApexContents { + if apexContents.DirectlyInApex(depName) { + useStubs = false + break + } + } + } + if useStubs { + // Yet another exception: If this module and the dependency are + // available to the same APEXes then skip stubs between their + // platform variants. This complements the test_for case above, + // which avoids the stubs on a direct APEX library dependency, by + // avoiding stubs for indirect test dependencies as well. + // + // TODO(b/183882457): This doesn't work if the two libraries have + // only partially overlapping apex_available. For that test_for + // modules would need to be split into APEX variants and resolved + // separately for each APEX they have access to. + if android.AvailableToSameApexes(c, dep.(android.ApexModule)) { useStubs = false - break } } } else { |