Merge changes from topic "stub_from_rust" into sc-dev-plus-aosp
* changes: Add platform_apis property to APEX module type Rust module in APEX uses stub libraries across APEX boundaries
This commit is contained in:
@@ -54,6 +54,10 @@ type ApexInfo struct {
|
|||||||
// True if this module comes from an updatable apexBundle.
|
// True if this module comes from an updatable apexBundle.
|
||||||
Updatable bool
|
Updatable bool
|
||||||
|
|
||||||
|
// True if this module can use private platform APIs. Only non-updatable APEX can set this
|
||||||
|
// to true.
|
||||||
|
UsePlatformApis bool
|
||||||
|
|
||||||
// The list of SDK modules that the containing apexBundle depends on.
|
// The list of SDK modules that the containing apexBundle depends on.
|
||||||
RequiredSdks SdkRefs
|
RequiredSdks SdkRefs
|
||||||
|
|
||||||
@@ -91,12 +95,17 @@ var ApexInfoProvider = blueprint.NewMutatorProvider(ApexInfo{}, "apex")
|
|||||||
// of a module can be deduped into one variation. For example, if libfoo is included in both apex.a
|
// of a module can be deduped into one variation. For example, if libfoo is included in both apex.a
|
||||||
// and apex.b, and if the two APEXes have the same min_sdk_version (say 29), then libfoo doesn't
|
// and apex.b, and if the two APEXes have the same min_sdk_version (say 29), then libfoo doesn't
|
||||||
// have to be built twice, but only once. In that case, the two apex variations apex.a and apex.b
|
// have to be built twice, but only once. In that case, the two apex variations apex.a and apex.b
|
||||||
// are configured to have the same alias variation named apex29.
|
// are configured to have the same alias variation named apex29. Whether platform APIs is allowed
|
||||||
|
// or not also matters; if two APEXes don't have the same allowance, they get different names and
|
||||||
|
// thus wouldn't be merged.
|
||||||
func (i ApexInfo) mergedName(ctx PathContext) string {
|
func (i ApexInfo) mergedName(ctx PathContext) string {
|
||||||
name := "apex" + strconv.Itoa(i.MinSdkVersion.FinalOrFutureInt())
|
name := "apex" + strconv.Itoa(i.MinSdkVersion.FinalOrFutureInt())
|
||||||
for _, sdk := range i.RequiredSdks {
|
for _, sdk := range i.RequiredSdks {
|
||||||
name += "_" + sdk.Name + "_" + sdk.Version
|
name += "_" + sdk.Name + "_" + sdk.Version
|
||||||
}
|
}
|
||||||
|
if i.UsePlatformApis {
|
||||||
|
name += "_private"
|
||||||
|
}
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,6 +536,10 @@ func mergeApexVariations(ctx PathContext, apexInfos []ApexInfo) (merged []ApexIn
|
|||||||
merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...)
|
merged[index].InApexModules = append(merged[index].InApexModules, apexInfo.InApexModules...)
|
||||||
merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...)
|
merged[index].ApexContents = append(merged[index].ApexContents, apexInfo.ApexContents...)
|
||||||
merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
|
merged[index].Updatable = merged[index].Updatable || apexInfo.Updatable
|
||||||
|
if merged[index].UsePlatformApis != apexInfo.UsePlatformApis {
|
||||||
|
panic(fmt.Errorf("variants having different UsePlatformApis can't be merged"))
|
||||||
|
}
|
||||||
|
merged[index].UsePlatformApis = apexInfo.UsePlatformApis
|
||||||
} else {
|
} else {
|
||||||
seen[mergedName] = len(merged)
|
seen[mergedName] = len(merged)
|
||||||
apexInfo.ApexVariationName = mergedName
|
apexInfo.ApexVariationName = mergedName
|
||||||
|
@@ -33,10 +33,10 @@ func Test_mergeApexVariations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "single",
|
name: "single",
|
||||||
in: []ApexInfo{
|
in: []ApexInfo{
|
||||||
{"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"foo", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantMerged: []ApexInfo{
|
wantMerged: []ApexInfo{
|
||||||
{"apex10000", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"apex10000", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantAliases: [][2]string{
|
wantAliases: [][2]string{
|
||||||
{"foo", "apex10000"},
|
{"foo", "apex10000"},
|
||||||
@@ -45,11 +45,11 @@ func Test_mergeApexVariations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "merge",
|
name: "merge",
|
||||||
in: []ApexInfo{
|
in: []ApexInfo{
|
||||||
{"foo", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"foo", FutureApiLevel, false, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
{"bar", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"bar", FutureApiLevel, false, false, SdkRefs{{"baz", "1"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantMerged: []ApexInfo{
|
wantMerged: []ApexInfo{
|
||||||
{"apex10000_baz_1", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, false}},
|
{"apex10000_baz_1", FutureApiLevel, false, false, SdkRefs{{"baz", "1"}}, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, false}},
|
||||||
wantAliases: [][2]string{
|
wantAliases: [][2]string{
|
||||||
{"bar", "apex10000_baz_1"},
|
{"bar", "apex10000_baz_1"},
|
||||||
{"foo", "apex10000_baz_1"},
|
{"foo", "apex10000_baz_1"},
|
||||||
@@ -58,12 +58,12 @@ func Test_mergeApexVariations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "don't merge version",
|
name: "don't merge version",
|
||||||
in: []ApexInfo{
|
in: []ApexInfo{
|
||||||
{"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"foo", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
{"bar", uncheckedFinalApiLevel(30), false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"bar", uncheckedFinalApiLevel(30), false, false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantMerged: []ApexInfo{
|
wantMerged: []ApexInfo{
|
||||||
{"apex30", uncheckedFinalApiLevel(30), false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"apex30", uncheckedFinalApiLevel(30), false, false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
{"apex10000", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"apex10000", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantAliases: [][2]string{
|
wantAliases: [][2]string{
|
||||||
{"bar", "apex30"},
|
{"bar", "apex30"},
|
||||||
@@ -73,11 +73,11 @@ func Test_mergeApexVariations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "merge updatable",
|
name: "merge updatable",
|
||||||
in: []ApexInfo{
|
in: []ApexInfo{
|
||||||
{"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"foo", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
{"bar", FutureApiLevel, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"bar", FutureApiLevel, true, false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantMerged: []ApexInfo{
|
wantMerged: []ApexInfo{
|
||||||
{"apex10000", FutureApiLevel, true, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
|
{"apex10000", FutureApiLevel, true, false, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantAliases: [][2]string{
|
wantAliases: [][2]string{
|
||||||
{"bar", "apex10000"},
|
{"bar", "apex10000"},
|
||||||
@@ -87,12 +87,12 @@ func Test_mergeApexVariations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "don't merge sdks",
|
name: "don't merge sdks",
|
||||||
in: []ApexInfo{
|
in: []ApexInfo{
|
||||||
{"foo", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"foo", FutureApiLevel, false, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
{"bar", FutureApiLevel, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"bar", FutureApiLevel, false, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantMerged: []ApexInfo{
|
wantMerged: []ApexInfo{
|
||||||
{"apex10000_baz_2", FutureApiLevel, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"apex10000_baz_2", FutureApiLevel, false, false, SdkRefs{{"baz", "2"}}, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
{"apex10000_baz_1", FutureApiLevel, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"apex10000_baz_1", FutureApiLevel, false, false, SdkRefs{{"baz", "1"}}, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantAliases: [][2]string{
|
wantAliases: [][2]string{
|
||||||
{"bar", "apex10000_baz_2"},
|
{"bar", "apex10000_baz_2"},
|
||||||
@@ -102,21 +102,36 @@ func Test_mergeApexVariations(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "don't merge when for prebuilt_apex",
|
name: "don't merge when for prebuilt_apex",
|
||||||
in: []ApexInfo{
|
in: []ApexInfo{
|
||||||
{"foo", FutureApiLevel, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
{"foo", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
{"bar", FutureApiLevel, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
{"bar", FutureApiLevel, true, false, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
// This one should not be merged in with the others because it is for
|
// This one should not be merged in with the others because it is for
|
||||||
// a prebuilt_apex.
|
// a prebuilt_apex.
|
||||||
{"baz", FutureApiLevel, true, nil, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
|
{"baz", FutureApiLevel, true, false, nil, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantMerged: []ApexInfo{
|
wantMerged: []ApexInfo{
|
||||||
{"apex10000", FutureApiLevel, true, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
|
{"apex10000", FutureApiLevel, true, false, nil, []string{"bar", "foo"}, []string{"bar", "foo"}, nil, NotForPrebuiltApex},
|
||||||
{"baz", FutureApiLevel, true, nil, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
|
{"baz", FutureApiLevel, true, false, nil, []string{"baz"}, []string{"baz"}, nil, ForPrebuiltApex},
|
||||||
},
|
},
|
||||||
wantAliases: [][2]string{
|
wantAliases: [][2]string{
|
||||||
{"bar", "apex10000"},
|
{"bar", "apex10000"},
|
||||||
{"foo", "apex10000"},
|
{"foo", "apex10000"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "don't merge different UsePlatformApis",
|
||||||
|
in: []ApexInfo{
|
||||||
|
{"foo", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
|
{"bar", FutureApiLevel, false, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
|
},
|
||||||
|
wantMerged: []ApexInfo{
|
||||||
|
{"apex10000_private", FutureApiLevel, false, true, nil, []string{"bar"}, []string{"bar"}, nil, NotForPrebuiltApex},
|
||||||
|
{"apex10000", FutureApiLevel, false, false, nil, []string{"foo"}, []string{"foo"}, nil, NotForPrebuiltApex},
|
||||||
|
},
|
||||||
|
wantAliases: [][2]string{
|
||||||
|
{"bar", "apex10000_private"},
|
||||||
|
{"foo", "apex10000"},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
12
apex/apex.go
12
apex/apex.go
@@ -130,6 +130,10 @@ type apexBundleProperties struct {
|
|||||||
// symlinking to the system libs. Default is true.
|
// symlinking to the system libs. Default is true.
|
||||||
Updatable *bool
|
Updatable *bool
|
||||||
|
|
||||||
|
// Whether this APEX can use platform APIs or not. Can be set to true only when `updatable:
|
||||||
|
// false`. Default is false.
|
||||||
|
Platform_apis *bool
|
||||||
|
|
||||||
// Whether this APEX is installable to one of the partitions like system, vendor, etc.
|
// Whether this APEX is installable to one of the partitions like system, vendor, etc.
|
||||||
// Default: true.
|
// Default: true.
|
||||||
Installable *bool
|
Installable *bool
|
||||||
@@ -908,6 +912,7 @@ func (a *apexBundle) ApexInfoMutator(mctx android.TopDownMutatorContext) {
|
|||||||
MinSdkVersion: minSdkVersion,
|
MinSdkVersion: minSdkVersion,
|
||||||
RequiredSdks: a.RequiredSdks(),
|
RequiredSdks: a.RequiredSdks(),
|
||||||
Updatable: a.Updatable(),
|
Updatable: a.Updatable(),
|
||||||
|
UsePlatformApis: a.UsePlatformApis(),
|
||||||
InApexVariants: []string{mctx.ModuleName()}, // could be com.android.foo
|
InApexVariants: []string{mctx.ModuleName()}, // could be com.android.foo
|
||||||
InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
|
InApexModules: []string{a.Name()}, // could be com.mycompany.android.foo
|
||||||
ApexContents: []*android.ApexContents{apexContents},
|
ApexContents: []*android.ApexContents{apexContents},
|
||||||
@@ -1274,6 +1279,10 @@ func (a *apexBundle) Updatable() bool {
|
|||||||
return proptools.BoolDefault(a.properties.Updatable, true)
|
return proptools.BoolDefault(a.properties.Updatable, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *apexBundle) UsePlatformApis() bool {
|
||||||
|
return proptools.BoolDefault(a.properties.Platform_apis, false)
|
||||||
|
}
|
||||||
|
|
||||||
// getCertString returns the name of the cert that should be used to sign this APEX. This is
|
// getCertString returns the name of the cert that should be used to sign this APEX. This is
|
||||||
// basically from the "certificate" property, but could be overridden by the device config.
|
// basically from the "certificate" property, but could be overridden by the device config.
|
||||||
func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
|
func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
|
||||||
@@ -2317,6 +2326,9 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
|
|||||||
if String(a.properties.Min_sdk_version) == "" {
|
if String(a.properties.Min_sdk_version) == "" {
|
||||||
ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
|
ctx.PropertyErrorf("updatable", "updatable APEXes should set min_sdk_version as well")
|
||||||
}
|
}
|
||||||
|
if a.UsePlatformApis() {
|
||||||
|
ctx.PropertyErrorf("updatable", "updatable APEXes can't use platform APIs")
|
||||||
|
}
|
||||||
a.checkJavaStableSdkVersion(ctx)
|
a.checkJavaStableSdkVersion(ctx)
|
||||||
a.checkClasspathFragments(ctx)
|
a.checkClasspathFragments(ctx)
|
||||||
}
|
}
|
||||||
|
@@ -839,6 +839,7 @@ func TestApexWithStubs(t *testing.T) {
|
|||||||
name: "myapex",
|
name: "myapex",
|
||||||
key: "myapex.key",
|
key: "myapex.key",
|
||||||
native_shared_libs: ["mylib", "mylib3"],
|
native_shared_libs: ["mylib", "mylib3"],
|
||||||
|
binaries: ["foo.rust"],
|
||||||
updatable: false,
|
updatable: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -887,6 +888,25 @@ func TestApexWithStubs(t *testing.T) {
|
|||||||
stl: "none",
|
stl: "none",
|
||||||
apex_available: [ "myapex" ],
|
apex_available: [ "myapex" ],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rust_binary {
|
||||||
|
name: "foo.rust",
|
||||||
|
srcs: ["foo.rs"],
|
||||||
|
shared_libs: ["libfoo.shared_from_rust"],
|
||||||
|
prefer_rlib: true,
|
||||||
|
apex_available: ["myapex"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library_shared {
|
||||||
|
name: "libfoo.shared_from_rust",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
stubs: {
|
||||||
|
versions: ["10", "11", "12"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
|
||||||
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
|
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
|
||||||
@@ -924,7 +944,90 @@ func TestApexWithStubs(t *testing.T) {
|
|||||||
"lib64/mylib.so",
|
"lib64/mylib.so",
|
||||||
"lib64/mylib3.so",
|
"lib64/mylib3.so",
|
||||||
"lib64/mylib4.so",
|
"lib64/mylib4.so",
|
||||||
|
"bin/foo.rust",
|
||||||
|
"lib64/libc++.so", // by the implicit dependency from foo.rust
|
||||||
|
"lib64/liblog.so", // by the implicit dependency from foo.rust
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Ensure that stub dependency from a rust module is not included
|
||||||
|
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
|
||||||
|
// The rust module is linked to the stub cc library
|
||||||
|
rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
|
||||||
|
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
|
||||||
|
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApexCanUsePrivateApis(t *testing.T) {
|
||||||
|
ctx := testApex(t, `
|
||||||
|
apex {
|
||||||
|
name: "myapex",
|
||||||
|
key: "myapex.key",
|
||||||
|
native_shared_libs: ["mylib"],
|
||||||
|
binaries: ["foo.rust"],
|
||||||
|
updatable: false,
|
||||||
|
platform_apis: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
apex_key {
|
||||||
|
name: "myapex.key",
|
||||||
|
public_key: "testkey.avbpubkey",
|
||||||
|
private_key: "testkey.pem",
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "mylib",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
shared_libs: ["mylib2"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
apex_available: [ "myapex" ],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "mylib2",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
cflags: ["-include mylib.h"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
stubs: {
|
||||||
|
versions: ["1", "2", "3"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_binary {
|
||||||
|
name: "foo.rust",
|
||||||
|
srcs: ["foo.rs"],
|
||||||
|
shared_libs: ["libfoo.shared_from_rust"],
|
||||||
|
prefer_rlib: true,
|
||||||
|
apex_available: ["myapex"],
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_library_shared {
|
||||||
|
name: "libfoo.shared_from_rust",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
system_shared_libs: [],
|
||||||
|
stl: "none",
|
||||||
|
stubs: {
|
||||||
|
versions: ["10", "11", "12"],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexRule")
|
||||||
|
copyCmds := apexRule.Args["copy_commands"]
|
||||||
|
|
||||||
|
// Ensure that indirect stubs dep is not included
|
||||||
|
ensureNotContains(t, copyCmds, "image.apex/lib64/mylib2.so")
|
||||||
|
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
|
||||||
|
|
||||||
|
// Ensure that we are using non-stub variants of mylib2 and libfoo.shared_from_rust (because
|
||||||
|
// of the platform_apis: true)
|
||||||
|
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000_private").Rule("ld").Args["libFlags"]
|
||||||
|
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
|
||||||
|
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
|
||||||
|
rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000_private").Rule("rustc").Args["linkFlags"]
|
||||||
|
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
|
||||||
|
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
|
func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
|
||||||
|
158
cc/cc.go
158
cc/cc.go
@@ -1259,7 +1259,7 @@ func (c *Module) ImplementationModuleNameForMake(ctx android.BaseModuleContext)
|
|||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Module) bootstrap() bool {
|
func (c *Module) Bootstrap() bool {
|
||||||
return Bool(c.Properties.Bootstrap)
|
return Bool(c.Properties.Bootstrap)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1504,7 +1504,7 @@ func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *moduleContextImpl) bootstrap() bool {
|
func (ctx *moduleContextImpl) bootstrap() bool {
|
||||||
return ctx.mod.bootstrap()
|
return ctx.mod.Bootstrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *moduleContextImpl) nativeCoverage() bool {
|
func (ctx *moduleContextImpl) nativeCoverage() bool {
|
||||||
@@ -2646,64 +2646,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
|
sharedLibraryInfo, returnedDepExporterInfo := ChooseStubOrImpl(ctx, dep)
|
||||||
sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryStubsProvider).(SharedLibraryStubsInfo)
|
depExporterInfo = returnedDepExporterInfo
|
||||||
|
|
||||||
if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
|
|
||||||
useStubs := false
|
|
||||||
|
|
||||||
if lib := moduleLibraryInterface(dep); lib.buildStubs() && c.UseVndk() { // LLNDK
|
|
||||||
if !apexInfo.IsForPlatform() {
|
|
||||||
// For platform libraries, use current version of LLNDK
|
|
||||||
useStubs = true
|
|
||||||
}
|
|
||||||
} else if apexInfo.IsForPlatform() {
|
|
||||||
// If not building for APEX, use stubs only when it is from
|
|
||||||
// an APEX (and not from platform)
|
|
||||||
// However, for host, ramdisk, vendor_ramdisk, recovery or bootstrap modules,
|
|
||||||
// always link to non-stub variant
|
|
||||||
useStubs = dep.(android.ApexModule).NotInPlatform() && !c.bootstrap()
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If building for APEX, use stubs when the parent is in any APEX that
|
|
||||||
// the child is not in.
|
|
||||||
useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// when to use (unspecified) stubs, use the latest one.
|
|
||||||
if useStubs {
|
|
||||||
stubs := sharedLibraryStubsInfo.SharedStubLibraries
|
|
||||||
toUse := stubs[len(stubs)-1]
|
|
||||||
sharedLibraryInfo = toUse.SharedLibraryInfo
|
|
||||||
depExporterInfo = toUse.FlagExporterInfo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stubs lib doesn't link to the shared lib dependencies. Don't set
|
// Stubs lib doesn't link to the shared lib dependencies. Don't set
|
||||||
// linkFile, depFile, and ptr.
|
// linkFile, depFile, and ptr.
|
||||||
@@ -2916,6 +2860,100 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
return depPaths
|
return depPaths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ChooseStubOrImpl determines whether a given dependency should be redirected to the stub variant
|
||||||
|
// of the dependency or not, and returns the SharedLibraryInfo and FlagExporterInfo for the right
|
||||||
|
// dependency. The stub variant is selected when the dependency crosses a boundary where each side
|
||||||
|
// has different level of updatability. For example, if a library foo in an APEX depends on a
|
||||||
|
// library bar which provides stable interface and exists in the platform, foo uses the stub variant
|
||||||
|
// of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
|
||||||
|
// same APEX as foo, the non-stub variant of bar is used.
|
||||||
|
func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
|
||||||
|
depName := ctx.OtherModuleName(dep)
|
||||||
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
||||||
|
libDepTag, ok := depTag.(libraryDependencyTag)
|
||||||
|
if !ok || !libDepTag.shared() {
|
||||||
|
panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
|
||||||
|
}
|
||||||
|
|
||||||
|
thisModule, ok := ctx.Module().(android.ApexModule)
|
||||||
|
if !ok {
|
||||||
|
panic(fmt.Errorf("Not an APEX module: %q", ctx.ModuleName()))
|
||||||
|
}
|
||||||
|
|
||||||
|
useVndk := false
|
||||||
|
bootstrap := false
|
||||||
|
if linkable, ok := ctx.Module().(LinkableInterface); !ok {
|
||||||
|
panic(fmt.Errorf("Not a Linkable module: %q", ctx.ModuleName()))
|
||||||
|
} else {
|
||||||
|
useVndk = linkable.UseVndk()
|
||||||
|
bootstrap = linkable.Bootstrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
|
||||||
|
depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
|
||||||
|
sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryStubsProvider).(SharedLibraryStubsInfo)
|
||||||
|
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
||||||
|
|
||||||
|
if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
|
||||||
|
useStubs := false
|
||||||
|
|
||||||
|
if lib := moduleLibraryInterface(dep); lib.buildStubs() && useVndk { // LLNDK
|
||||||
|
if !apexInfo.IsForPlatform() {
|
||||||
|
// For platform libraries, use current version of LLNDK
|
||||||
|
// If this is for use_vendor apex we will apply the same rules
|
||||||
|
// of apex sdk enforcement below to choose right version.
|
||||||
|
useStubs = true
|
||||||
|
}
|
||||||
|
} else if apexInfo.IsForPlatform() || apexInfo.UsePlatformApis {
|
||||||
|
// If not building for APEX or the containing APEX allows the use of
|
||||||
|
// platform APIs, use stubs only when it is from an APEX (and not from
|
||||||
|
// platform) However, for host, ramdisk, vendor_ramdisk, recovery or
|
||||||
|
// bootstrap modules, always link to non-stub variant
|
||||||
|
useStubs = dep.(android.ApexModule).NotInPlatform() && !bootstrap
|
||||||
|
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(thisModule, dep.(android.ApexModule)) {
|
||||||
|
useStubs = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If building for APEX, use stubs when the parent is in any APEX that
|
||||||
|
// the child is not in.
|
||||||
|
useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// when to use (unspecified) stubs, use the latest one.
|
||||||
|
if useStubs {
|
||||||
|
stubs := sharedLibraryStubsInfo.SharedStubLibraries
|
||||||
|
toUse := stubs[len(stubs)-1]
|
||||||
|
sharedLibraryInfo = toUse.SharedLibraryInfo
|
||||||
|
depExporterInfo = toUse.FlagExporterInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sharedLibraryInfo, depExporterInfo
|
||||||
|
}
|
||||||
|
|
||||||
// orderStaticModuleDeps rearranges the order of the static library dependencies of the module
|
// orderStaticModuleDeps rearranges the order of the static library dependencies of the module
|
||||||
// to match the topological order of the dependency tree, including any static analogues of
|
// to match the topological order of the dependency tree, including any static analogues of
|
||||||
// direct shared libraries. It returns the ordered static dependencies, and an android.DepSet
|
// direct shared libraries. It returns the ordered static dependencies, and an android.DepSet
|
||||||
|
@@ -165,6 +165,9 @@ type LinkableInterface interface {
|
|||||||
// "product_specific: true" modules are included here.
|
// "product_specific: true" modules are included here.
|
||||||
UseVndk() bool
|
UseVndk() bool
|
||||||
|
|
||||||
|
// Bootstrap tests if this module is allowed to use non-APEX version of libraries.
|
||||||
|
Bootstrap() bool
|
||||||
|
|
||||||
// IsVndkSp returns true if this is a VNDK-SP module.
|
// IsVndkSp returns true if this is a VNDK-SP module.
|
||||||
IsVndkSp() bool
|
IsVndkSp() bool
|
||||||
|
|
||||||
|
27
rust/rust.go
27
rust/rust.go
@@ -288,6 +288,10 @@ func (mod *Module) UseVndk() bool {
|
|||||||
return mod.Properties.VndkVersion != ""
|
return mod.Properties.VndkVersion != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mod *Module) Bootstrap() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (mod *Module) MustUseVendorVariant() bool {
|
func (mod *Module) MustUseVendorVariant() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -952,7 +956,7 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
directRlibDeps := []*Module{}
|
directRlibDeps := []*Module{}
|
||||||
directDylibDeps := []*Module{}
|
directDylibDeps := []*Module{}
|
||||||
directProcMacroDeps := []*Module{}
|
directProcMacroDeps := []*Module{}
|
||||||
directSharedLibDeps := [](cc.LinkableInterface){}
|
directSharedLibDeps := []cc.SharedLibraryInfo{}
|
||||||
directStaticLibDeps := [](cc.LinkableInterface){}
|
directStaticLibDeps := [](cc.LinkableInterface){}
|
||||||
directSrcProvidersDeps := []*Module{}
|
directSrcProvidersDeps := []*Module{}
|
||||||
directSrcDeps := [](android.SourceFileProducer){}
|
directSrcDeps := [](android.SourceFileProducer){}
|
||||||
@@ -1073,14 +1077,23 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
directStaticLibDeps = append(directStaticLibDeps, ccDep)
|
directStaticLibDeps = append(directStaticLibDeps, ccDep)
|
||||||
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName)
|
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, makeLibName)
|
||||||
case cc.IsSharedDepTag(depTag):
|
case cc.IsSharedDepTag(depTag):
|
||||||
|
// For the shared lib dependencies, we may link to the stub variant
|
||||||
|
// of the dependency depending on the context (e.g. if this
|
||||||
|
// dependency crosses the APEX boundaries).
|
||||||
|
sharedLibraryInfo, exportedInfo := cc.ChooseStubOrImpl(ctx, dep)
|
||||||
|
|
||||||
|
// Re-get linkObject as ChooseStubOrImpl actually tells us which
|
||||||
|
// object (either from stub or non-stub) to use.
|
||||||
|
linkObject = android.OptionalPathForPath(sharedLibraryInfo.SharedLibrary)
|
||||||
|
linkPath = linkPathFromFilePath(linkObject.Path())
|
||||||
|
|
||||||
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
|
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
|
||||||
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
|
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
|
||||||
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
|
|
||||||
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
||||||
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
||||||
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
|
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
|
||||||
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
|
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
|
||||||
directSharedLibDeps = append(directSharedLibDeps, ccDep)
|
directSharedLibDeps = append(directSharedLibDeps, sharedLibraryInfo)
|
||||||
|
|
||||||
// Record baseLibName for snapshots.
|
// Record baseLibName for snapshots.
|
||||||
mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))
|
mod.Properties.SnapshotSharedLibs = append(mod.Properties.SnapshotSharedLibs, cc.BaseLibName(depName))
|
||||||
@@ -1135,11 +1148,11 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
var sharedLibFiles android.Paths
|
var sharedLibFiles android.Paths
|
||||||
var sharedLibDepFiles android.Paths
|
var sharedLibDepFiles android.Paths
|
||||||
for _, dep := range directSharedLibDeps {
|
for _, dep := range directSharedLibDeps {
|
||||||
sharedLibFiles = append(sharedLibFiles, dep.OutputFile().Path())
|
sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary)
|
||||||
if dep.Toc().Valid() {
|
if dep.TableOfContents.Valid() {
|
||||||
sharedLibDepFiles = append(sharedLibDepFiles, dep.Toc().Path())
|
sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path())
|
||||||
} else {
|
} else {
|
||||||
sharedLibDepFiles = append(sharedLibDepFiles, dep.OutputFile().Path())
|
sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user