Merge changes Iaa6411b5,I2118b8a2,Ibbdd3cbd,I2d1bbda2 am: 38e9f0b82f
am: 99f29d244a
am: c5c5d80d30
Original change: https://android-review.googlesource.com/c/platform/build/soong/+/1652620 Change-Id: I09a93351bcae2c27531fd258ddacdd8bc5ddd474
This commit is contained in:
commit
2f1e93ef36
|
@ -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
|
type byApexName []ApexInfo
|
||||||
|
|
||||||
func (a byApexName) Len() int { return len(a) }
|
func (a byApexName) Len() int { return len(a) }
|
||||||
|
|
|
@ -1642,16 +1642,10 @@ type InstallPath struct {
|
||||||
|
|
||||||
// Will panic if called from outside a test environment.
|
// Will panic if called from outside a test environment.
|
||||||
func ensureTestOnly() {
|
func ensureTestOnly() {
|
||||||
// Normal soong test environment
|
if PrefixInList(os.Args, "-test.") {
|
||||||
if InList("-test.short", os.Args) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// IntelliJ test environment
|
panic(fmt.Errorf("Not in test. Command line:\n %s", strings.Join(os.Args, "\n ")))
|
||||||
if InList("-test.v", os.Args) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
panic(fmt.Errorf("Not in test\n%s", strings.Join(os.Args, "\n")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p InstallPath) RelativeToTop() Path {
|
func (p InstallPath) RelativeToTop() Path {
|
||||||
|
|
|
@ -193,6 +193,17 @@ func FilterList(list []string, filter []string) (remainder []string, filtered []
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FilterListPred returns the elements of the given list for which the predicate
|
||||||
|
// returns true. Order is kept.
|
||||||
|
func FilterListPred(list []string, pred func(s string) bool) (filtered []string) {
|
||||||
|
for _, l := range list {
|
||||||
|
if pred(l) {
|
||||||
|
filtered = append(filtered, l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// RemoveListFromList removes the strings belonging to the filter list from the
|
// RemoveListFromList removes the strings belonging to the filter list from the
|
||||||
// given list and returns the result
|
// given list and returns the result
|
||||||
func RemoveListFromList(list []string, filter_out []string) (result []string) {
|
func RemoveListFromList(list []string, filter_out []string) (result []string) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -299,6 +300,14 @@ func TestFilterList(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFilterListPred(t *testing.T) {
|
||||||
|
pred := func(s string) bool { return strings.HasPrefix(s, "a/") }
|
||||||
|
AssertArrayString(t, "filter", FilterListPred([]string{"a/c", "b/a", "a/b"}, pred), []string{"a/c", "a/b"})
|
||||||
|
AssertArrayString(t, "filter", FilterListPred([]string{"b/c", "a/a", "b/b"}, pred), []string{"a/a"})
|
||||||
|
AssertArrayString(t, "filter", FilterListPred([]string{"c/c", "b/a", "c/b"}, pred), []string{})
|
||||||
|
AssertArrayString(t, "filter", FilterListPred([]string{"a/c", "a/a", "a/b"}, pred), []string{"a/c", "a/a", "a/b"})
|
||||||
|
}
|
||||||
|
|
||||||
func TestRemoveListFromList(t *testing.T) {
|
func TestRemoveListFromList(t *testing.T) {
|
||||||
input := []string{"a", "b", "c", "d", "a", "c", "d"}
|
input := []string{"a", "b", "c", "d", "a", "c", "d"}
|
||||||
filter := []string{"a", "c"}
|
filter := []string{"a", "c"}
|
||||||
|
|
|
@ -6863,21 +6863,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.
|
// actual implementation of mylib instead of its stub.
|
||||||
ldFlags := ctx.ModuleForTests("mytest", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
|
ensureLinkedLibIs("mytest", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
|
||||||
ensureContains(t, ldFlags, "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")
|
||||||
ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
|
ensureLinkedLibIs("mybench", "android_arm64_armv8-a", "out/soong/.intermediates/mylib/", "android_arm64_armv8-a_shared/mylib.so")
|
||||||
|
}
|
||||||
|
|
||||||
// The same should be true for cc_library
|
func TestIndirectTestFor(t *testing.T) {
|
||||||
ldFlags = ctx.ModuleForTests("mytestlib", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"]
|
ctx := testApex(t, `
|
||||||
ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so")
|
apex {
|
||||||
ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["mylib", "myprivlib"],
|
||||||
|
updatable: false,
|
||||||
|
}
|
||||||
|
|
||||||
// ... and for cc_benchmark
|
apex_key {
|
||||||
ldFlags = ctx.ModuleForTests("mybench", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
|
name: "myapex.key",
|
||||||
ensureContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared/mylib.so")
|
public_key: "testkey.avbpubkey",
|
||||||
ensureNotContains(t, ldFlags, "mylib/android_arm64_armv8-a_shared_1/mylib.so")
|
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
|
// TODO(jungjw): Move this to proptools
|
||||||
|
|
21
cc/cc.go
21
cc/cc.go
|
@ -363,7 +363,7 @@ type BaseProperties struct {
|
||||||
// List of APEXes that this module has private access to for testing purpose. The module
|
// List of APEXes that this module has private access to for testing purpose. The module
|
||||||
// can depend on libraries that are not exported by the APEXes and use private symbols
|
// can depend on libraries that are not exported by the APEXes and use private symbols
|
||||||
// from the exported libraries.
|
// from the exported libraries.
|
||||||
Test_for []string
|
Test_for []string `android:"arch_variant"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VendorProperties struct {
|
type VendorProperties struct {
|
||||||
|
@ -2631,7 +2631,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||||
// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
|
// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
|
||||||
// always link to non-stub variant
|
// always link to non-stub variant
|
||||||
useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap()
|
useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap()
|
||||||
// Another exception: if this module is bundled with an APEX, then
|
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
|
// it is linked with the non-stub variant of a module in the APEX
|
||||||
// as if this is part of the APEX.
|
// as if this is part of the APEX.
|
||||||
testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
|
testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
|
||||||
|
@ -2641,6 +2642,22 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||||
break
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If building for APEX, use stubs when the parent is in any APEX that
|
// If building for APEX, use stubs when the parent is in any APEX that
|
||||||
// the child is not in.
|
// the child is not in.
|
||||||
|
|
Loading…
Reference in New Issue