Merge "Add "provide_cpp_shared_libs/uses" props to "apex""
This commit is contained in:
42
apex/apex.go
42
apex/apex.go
@@ -111,6 +111,7 @@ var (
|
|||||||
testTag = dependencyTag{name: "test"}
|
testTag = dependencyTag{name: "test"}
|
||||||
keyTag = dependencyTag{name: "key"}
|
keyTag = dependencyTag{name: "key"}
|
||||||
certificateTag = dependencyTag{name: "certificate"}
|
certificateTag = dependencyTag{name: "certificate"}
|
||||||
|
usesTag = dependencyTag{name: "uses"}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -147,6 +148,7 @@ func init() {
|
|||||||
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
ctx.TopDown("apex_deps", apexDepsMutator)
|
ctx.TopDown("apex_deps", apexDepsMutator)
|
||||||
ctx.BottomUp("apex", apexMutator).Parallel()
|
ctx.BottomUp("apex", apexMutator).Parallel()
|
||||||
|
ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +189,11 @@ func apexMutator(mctx android.BottomUpMutatorContext) {
|
|||||||
mctx.CreateVariations(apexBundleName)
|
mctx.CreateVariations(apexBundleName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func apexUsesMutator(mctx android.BottomUpMutatorContext) {
|
||||||
|
if ab, ok := mctx.Module().(*apexBundle); ok {
|
||||||
|
mctx.AddFarVariationDependencies(nil, usesTag, ab.properties.Uses...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type apexNativeDependencies struct {
|
type apexNativeDependencies struct {
|
||||||
// List of native libraries
|
// List of native libraries
|
||||||
@@ -272,6 +279,12 @@ type apexBundleProperties struct {
|
|||||||
|
|
||||||
// List of sanitizer names that this APEX is enabled for
|
// List of sanitizer names that this APEX is enabled for
|
||||||
SanitizerNames []string `blueprint:"mutated"`
|
SanitizerNames []string `blueprint:"mutated"`
|
||||||
|
|
||||||
|
// Indicates this APEX provides C++ shared libaries to other APEXes. Default: false.
|
||||||
|
Provide_cpp_shared_libs *bool
|
||||||
|
|
||||||
|
// List of providing APEXes' names so that this APEX can depend on provided shared libraries.
|
||||||
|
Uses []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type apexTargetBundleProperties struct {
|
type apexTargetBundleProperties struct {
|
||||||
@@ -727,6 +740,30 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
|
|
||||||
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
|
handleSpecialLibs := !android.Bool(a.properties.Ignore_system_library_special_case)
|
||||||
|
|
||||||
|
// Check if "uses" requirements are met with dependent apexBundles
|
||||||
|
var providedNativeSharedLibs []string
|
||||||
|
useVendor := proptools.Bool(a.properties.Use_vendor)
|
||||||
|
ctx.VisitDirectDepsBlueprint(func(m blueprint.Module) {
|
||||||
|
if ctx.OtherModuleDependencyTag(m) != usesTag {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
otherName := ctx.OtherModuleName(m)
|
||||||
|
other, ok := m.(*apexBundle)
|
||||||
|
if !ok {
|
||||||
|
ctx.PropertyErrorf("uses", "%q is not a provider", otherName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if proptools.Bool(other.properties.Use_vendor) != useVendor {
|
||||||
|
ctx.PropertyErrorf("use_vendor", "%q has different value of use_vendor", otherName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !proptools.Bool(other.properties.Provide_cpp_shared_libs) {
|
||||||
|
ctx.PropertyErrorf("uses", "%q does not provide native_shared_libs", otherName)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
providedNativeSharedLibs = append(providedNativeSharedLibs, other.properties.Native_shared_libs...)
|
||||||
|
})
|
||||||
|
|
||||||
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
|
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool {
|
||||||
if _, ok := parent.(*apexBundle); ok {
|
if _, ok := parent.(*apexBundle); ok {
|
||||||
// direct dependencies
|
// direct dependencies
|
||||||
@@ -815,6 +852,11 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|||||||
// indirect dependencies
|
// indirect dependencies
|
||||||
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
|
if am, ok := child.(android.ApexModule); ok && am.CanHaveApexVariants() && am.IsInstallableToApex() {
|
||||||
if cc, ok := child.(*cc.Module); ok {
|
if cc, ok := child.(*cc.Module); ok {
|
||||||
|
if android.InList(cc.Name(), providedNativeSharedLibs) {
|
||||||
|
// If we're using a shared library which is provided from other APEX,
|
||||||
|
// don't include it in this APEX
|
||||||
|
return false
|
||||||
|
}
|
||||||
if !a.Host() && (cc.IsStubs() || cc.HasStubsVariants()) {
|
if !a.Host() && (cc.IsStubs() || cc.HasStubsVariants()) {
|
||||||
// If the dependency is a stubs lib, don't include it in this APEX,
|
// If the dependency is a stubs lib, don't include it in this APEX,
|
||||||
// but make sure that the lib is installed on the device.
|
// but make sure that the lib is installed on the device.
|
||||||
|
@@ -29,7 +29,32 @@ import (
|
|||||||
|
|
||||||
var buildDir string
|
var buildDir string
|
||||||
|
|
||||||
|
func testApexError(t *testing.T, pattern, bp string) {
|
||||||
|
ctx, config := testApexContext(t, bp)
|
||||||
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||||
|
if len(errs) > 0 {
|
||||||
|
android.FailIfNoMatchingErrors(t, pattern, errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
|
if len(errs) > 0 {
|
||||||
|
android.FailIfNoMatchingErrors(t, pattern, errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
|
||||||
|
}
|
||||||
|
|
||||||
func testApex(t *testing.T, bp string) *android.TestContext {
|
func testApex(t *testing.T, bp string) *android.TestContext {
|
||||||
|
ctx, config := testApexContext(t, bp)
|
||||||
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||||
|
android.FailIfErrored(t, errs)
|
||||||
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
|
android.FailIfErrored(t, errs)
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func testApexContext(t *testing.T, bp string) (*android.TestContext, android.Config) {
|
||||||
config := android.TestArchConfig(buildDir, nil)
|
config := android.TestArchConfig(buildDir, nil)
|
||||||
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
|
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
|
||||||
config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
|
config.TestProductVariables.DefaultAppCertificate = proptools.StringPtr("vendor/foo/devkeys/test")
|
||||||
@@ -48,6 +73,7 @@ func testApex(t *testing.T, bp string) *android.TestContext {
|
|||||||
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
||||||
ctx.TopDown("apex_deps", apexDepsMutator)
|
ctx.TopDown("apex_deps", apexDepsMutator)
|
||||||
ctx.BottomUp("apex", apexMutator)
|
ctx.BottomUp("apex", apexMutator)
|
||||||
|
ctx.BottomUp("apex_uses", apexUsesMutator)
|
||||||
ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
|
ctx.TopDown("prebuilt_select", android.PrebuiltSelectModuleMutator).Parallel()
|
||||||
ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
|
ctx.BottomUp("prebuilt_postdeps", android.PrebuiltPostDepsMutator).Parallel()
|
||||||
})
|
})
|
||||||
@@ -168,8 +194,10 @@ func testApex(t *testing.T, bp string) *android.TestContext {
|
|||||||
"system/sepolicy/apex/myapex-file_contexts": nil,
|
"system/sepolicy/apex/myapex-file_contexts": nil,
|
||||||
"system/sepolicy/apex/myapex_keytest-file_contexts": nil,
|
"system/sepolicy/apex/myapex_keytest-file_contexts": nil,
|
||||||
"system/sepolicy/apex/otherapex-file_contexts": nil,
|
"system/sepolicy/apex/otherapex-file_contexts": nil,
|
||||||
|
"system/sepolicy/apex/commonapex-file_contexts": nil,
|
||||||
"mylib.cpp": nil,
|
"mylib.cpp": nil,
|
||||||
"mytest.cpp": nil,
|
"mytest.cpp": nil,
|
||||||
|
"mylib_common.cpp": nil,
|
||||||
"myprebuilt": nil,
|
"myprebuilt": nil,
|
||||||
"my_include": nil,
|
"my_include": nil,
|
||||||
"vendor/foo/devkeys/test.x509.pem": nil,
|
"vendor/foo/devkeys/test.x509.pem": nil,
|
||||||
@@ -188,12 +216,8 @@ func testApex(t *testing.T, bp string) *android.TestContext {
|
|||||||
"myapex-arm.apex": nil,
|
"myapex-arm.apex": nil,
|
||||||
"frameworks/base/api/current.txt": nil,
|
"frameworks/base/api/current.txt": nil,
|
||||||
})
|
})
|
||||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
|
||||||
android.FailIfErrored(t, errs)
|
|
||||||
_, errs = ctx.PrepareBuildActions(config)
|
|
||||||
android.FailIfErrored(t, errs)
|
|
||||||
|
|
||||||
return ctx
|
return ctx, config
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUp() {
|
func setUp() {
|
||||||
@@ -210,6 +234,7 @@ func tearDown() {
|
|||||||
|
|
||||||
// ensure that 'result' contains 'expected'
|
// ensure that 'result' contains 'expected'
|
||||||
func ensureContains(t *testing.T, result string, expected string) {
|
func ensureContains(t *testing.T, result string, expected string) {
|
||||||
|
t.Helper()
|
||||||
if !strings.Contains(result, expected) {
|
if !strings.Contains(result, expected) {
|
||||||
t.Errorf("%q is not found in %q", expected, result)
|
t.Errorf("%q is not found in %q", expected, result)
|
||||||
}
|
}
|
||||||
@@ -217,18 +242,21 @@ func ensureContains(t *testing.T, result string, expected string) {
|
|||||||
|
|
||||||
// ensures that 'result' does not contain 'notExpected'
|
// ensures that 'result' does not contain 'notExpected'
|
||||||
func ensureNotContains(t *testing.T, result string, notExpected string) {
|
func ensureNotContains(t *testing.T, result string, notExpected string) {
|
||||||
|
t.Helper()
|
||||||
if strings.Contains(result, notExpected) {
|
if strings.Contains(result, notExpected) {
|
||||||
t.Errorf("%q is found in %q", notExpected, result)
|
t.Errorf("%q is found in %q", notExpected, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureListContains(t *testing.T, result []string, expected string) {
|
func ensureListContains(t *testing.T, result []string, expected string) {
|
||||||
|
t.Helper()
|
||||||
if !android.InList(expected, result) {
|
if !android.InList(expected, result) {
|
||||||
t.Errorf("%q is not found in %v", expected, result)
|
t.Errorf("%q is not found in %v", expected, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureListNotContains(t *testing.T, result []string, notExpected string) {
|
func ensureListNotContains(t *testing.T, result []string, notExpected string) {
|
||||||
|
t.Helper()
|
||||||
if android.InList(notExpected, result) {
|
if android.InList(notExpected, result) {
|
||||||
t.Errorf("%q is found in %v", notExpected, result)
|
t.Errorf("%q is found in %v", notExpected, result)
|
||||||
}
|
}
|
||||||
@@ -789,6 +817,30 @@ func TestUseVendor(t *testing.T) {
|
|||||||
ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib2.so")
|
ensureNotContains(t, inputsString, "android_arm64_armv8-a_core_shared_myapex/mylib2.so")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) {
|
||||||
|
testApexError(t, `dependency "mylib" of "myapex" missing variant:\n.*image:vendor`, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["mylib"],
|
||||||
|
use_vendor: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestStaticLinking(t *testing.T) {
|
func TestStaticLinking(t *testing.T) {
|
||||||
ctx := testApex(t, `
|
ctx := testApex(t, `
|
||||||
apex {
|
apex {
|
||||||
@@ -1321,6 +1373,122 @@ func TestApexWithTests(t *testing.T) {
|
|||||||
ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
|
ensureContains(t, copyCmds, "image.apex/bin/test/mytest")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApexUsesOtherApex(t *testing.T) {
|
||||||
|
ctx := testApex(t, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["mylib"],
|
||||||
|
uses: ["commonapex"],
|
||||||
|
}
|
||||||
|
|
||||||
|
apex {
|
||||||
|
name: "commonapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["libcommon"],
|
||||||
|
provide_cpp_shared_libs: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "mylib",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
shared_libs: ["libcommon"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "libcommon",
|
||||||
|
srcs: ["mylib_common.cpp"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
module1 := ctx.ModuleForTests("myapex", "android_common_myapex")
|
||||||
|
apexRule1 := module1.Rule("apexRule")
|
||||||
|
copyCmds1 := apexRule1.Args["copy_commands"]
|
||||||
|
|
||||||
|
module2 := ctx.ModuleForTests("commonapex", "android_common_commonapex")
|
||||||
|
apexRule2 := module2.Rule("apexRule")
|
||||||
|
copyCmds2 := apexRule2.Args["copy_commands"]
|
||||||
|
|
||||||
|
ensureListContains(t, ctx.ModuleVariantsForTests("mylib"), "android_arm64_armv8-a_core_shared_myapex")
|
||||||
|
ensureListContains(t, ctx.ModuleVariantsForTests("libcommon"), "android_arm64_armv8-a_core_shared_commonapex")
|
||||||
|
ensureContains(t, copyCmds1, "image.apex/lib64/mylib.so")
|
||||||
|
ensureContains(t, copyCmds2, "image.apex/lib64/libcommon.so")
|
||||||
|
ensureNotContains(t, copyCmds1, "image.apex/lib64/libcommon.so")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApexUsesFailsIfNotProvided(t *testing.T) {
|
||||||
|
testApexError(t, `uses: "commonapex" does not provide native_shared_libs`, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
uses: ["commonapex"],
|
||||||
|
}
|
||||||
|
|
||||||
|
apex {
|
||||||
|
name: "commonapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
testApexError(t, `uses: "commonapex" is not a provider`, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
uses: ["commonapex"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "commonapex",
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApexUsesFailsIfUseVenderMismatch(t *testing.T) {
|
||||||
|
testApexError(t, `use_vendor: "commonapex" has different value of use_vendor`, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
use_vendor: true,
|
||||||
|
uses: ["commonapex"],
|
||||||
|
}
|
||||||
|
|
||||||
|
apex {
|
||||||
|
name: "commonapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
provide_cpp_shared_libs: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
run := func() int {
|
run := func() int {
|
||||||
setUp()
|
setUp()
|
||||||
|
Reference in New Issue
Block a user