diff --git a/android/apex.go b/android/apex.go index 839a03af0..398fbaee1 100644 --- a/android/apex.go +++ b/android/apex.go @@ -108,6 +108,11 @@ type ApexModule interface { // Tests if the module comes from an updatable APEX. Updatable() bool + + // List of APEXes that this module tests. The module has access to + // the private part of the listed APEXes even when it is not included in the + // APEXes. + TestFor() []string } type ApexProperties struct { @@ -151,6 +156,11 @@ func (m *ApexModuleBase) ApexAvailable() []string { return m.ApexProperties.Apex_available } +func (m *ApexModuleBase) TestFor() []string { + // To be implemented by concrete types inheriting ApexModuleBase + return nil +} + func (m *ApexModuleBase) BuildForApexes(apexes []ApexInfo) { m.apexVariationsLock.Lock() defer m.apexVariationsLock.Unlock() diff --git a/apex/apex_test.go b/apex/apex_test.go index b1e7bc9c1..8807d00c4 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -4533,6 +4533,58 @@ func TestNoUpdatableJarsInBootImage(t *testing.T) { testNoUpdatableJarsInBootImage(t, "", bp, transform) } +func TestTestFor(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib", "myprivlib"], + } + + 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", + apex_available: ["myapex"], + } + + + cc_test { + name: "mytest", + gtest: false, + srcs: ["mylib.cpp"], + system_shared_libs: [], + stl: "none", + shared_libs: ["mylib", "myprivlib"], + test_for: ["myapex"] + } + `) + + // the test 'mytest' is a test for the apex, therefore is 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") +} + func TestMain(m *testing.M) { run := func() int { setUp() diff --git a/cc/cc.go b/cc/cc.go index 24173ee32..66425c7de 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -2338,6 +2338,15 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // always link to non-stub variant useThisDep = !depIsStubs } + for _, testFor := range c.TestFor() { + // 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. + if android.DirectlyInApex(testFor, depName) { + useThisDep = !depIsStubs + break + } + } } else { // If building for APEX, use stubs only when it is not from // the same APEX @@ -2764,6 +2773,16 @@ func (c *Module) AvailableFor(what string) bool { } } +func (c *Module) TestFor() []string { + if test, ok := c.linker.(interface { + testFor() []string + }); ok { + return test.testFor() + } else { + return c.ApexModuleBase.TestFor() + } +} + // Return true if the module is ever installable. func (c *Module) EverInstallable() bool { return c.installer != nil && diff --git a/cc/test.go b/cc/test.go index 1085d3a69..f51cf01f2 100644 --- a/cc/test.go +++ b/cc/test.go @@ -29,6 +29,11 @@ type TestProperties struct { // if set, use the isolated gtest runner. Defaults to false. Isolated *bool + + // List of APEXes that this module tests. The module has access to + // the private part of the listed APEXes even when it is not included in the + // APEXes. + Test_for []string } // Test option struct. @@ -215,6 +220,10 @@ func (test *testDecorator) gtest() bool { return BoolDefault(test.Properties.Gtest, true) } +func (test *testDecorator) testFor() []string { + return test.Properties.Test_for +} + func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { if !test.gtest() { return flags