Enforce stub libraries should have a single apex_available
If a library contributes to an API surface, it will have only a single copy on device. Therefore, we should disallow installation to muliple apexes/platform. There are some exceptions to this rule today, and they have been relaxed using allowlists. Bug: 277651159 Test: go test ./apex Change-Id: Ice3023ecd28412a2610d8b98628cb727b58c5c3b
This commit is contained in:
@@ -3131,10 +3131,7 @@ func TestStaticLinking(t *testing.T) {
|
||||
stubs: {
|
||||
versions: ["1", "2", "3"],
|
||||
},
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"myapex",
|
||||
],
|
||||
apex_available: ["myapex"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
@@ -4134,7 +4131,7 @@ func TestDependenciesInApexManifest(t *testing.T) {
|
||||
apex {
|
||||
name: "myapex_selfcontained",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["lib_dep", "libfoo"],
|
||||
native_shared_libs: ["lib_dep_on_bar", "libbar"],
|
||||
compile_multilib: "both",
|
||||
file_contexts: ":myapex-file_contexts",
|
||||
updatable: false,
|
||||
@@ -4167,6 +4164,18 @@ func TestDependenciesInApexManifest(t *testing.T) {
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "lib_dep_on_bar",
|
||||
srcs: ["mylib.cpp"],
|
||||
shared_libs: ["libbar"],
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
apex_available: [
|
||||
"myapex_selfcontained",
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
srcs: ["mytest.cpp"],
|
||||
@@ -4177,9 +4186,22 @@ func TestDependenciesInApexManifest(t *testing.T) {
|
||||
stl: "none",
|
||||
apex_available: [
|
||||
"myapex_provider",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
srcs: ["mytest.cpp"],
|
||||
stubs: {
|
||||
versions: ["1"],
|
||||
},
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
apex_available: [
|
||||
"myapex_selfcontained",
|
||||
],
|
||||
}
|
||||
|
||||
`)
|
||||
|
||||
var apexManifestRule android.TestingBuildParams
|
||||
@@ -4206,7 +4228,7 @@ func TestDependenciesInApexManifest(t *testing.T) {
|
||||
apexManifestRule = ctx.ModuleForTests("myapex_selfcontained", "android_common_myapex_selfcontained_image").Rule("apexManifestRule")
|
||||
provideNativeLibs = names(apexManifestRule.Args["provideNativeLibs"])
|
||||
requireNativeLibs = names(apexManifestRule.Args["requireNativeLibs"])
|
||||
ensureListContains(t, provideNativeLibs, "libfoo.so")
|
||||
ensureListContains(t, provideNativeLibs, "libbar.so")
|
||||
ensureListEmpty(t, requireNativeLibs)
|
||||
}
|
||||
|
||||
@@ -8488,14 +8510,14 @@ func TestTestForForLibInOtherApex(t *testing.T) {
|
||||
apex {
|
||||
name: "com.android.art",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["mylib"],
|
||||
native_shared_libs: ["libnativebridge"],
|
||||
updatable: false,
|
||||
}
|
||||
|
||||
apex {
|
||||
name: "com.android.art.debug",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["mylib", "mytestlib"],
|
||||
native_shared_libs: ["libnativebridge", "libnativebrdige_test"],
|
||||
updatable: false,
|
||||
}
|
||||
|
||||
@@ -8506,8 +8528,8 @@ func TestTestForForLibInOtherApex(t *testing.T) {
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "mylib",
|
||||
srcs: ["mylib.cpp"],
|
||||
name: "libnativebridge",
|
||||
srcs: ["libnativebridge.cpp"],
|
||||
system_shared_libs: [],
|
||||
stl: "none",
|
||||
stubs: {
|
||||
@@ -8517,10 +8539,10 @@ func TestTestForForLibInOtherApex(t *testing.T) {
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "mytestlib",
|
||||
name: "libnativebrdige_test",
|
||||
srcs: ["mylib.cpp"],
|
||||
system_shared_libs: [],
|
||||
shared_libs: ["mylib"],
|
||||
shared_libs: ["libnativebridge"],
|
||||
stl: "none",
|
||||
apex_available: ["com.android.art.debug"],
|
||||
test_for: ["com.android.art"],
|
||||
@@ -10192,3 +10214,77 @@ func TestCannedFsConfig_HasCustomConfig(t *testing.T) {
|
||||
// Ensure that canned_fs_config has "cat my_config" at the end
|
||||
ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; cat my_config ) >`)
|
||||
}
|
||||
|
||||
func TestStubLibrariesMultipleApexViolation(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
hasStubs bool
|
||||
apexAvailable string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
desc: "non-stub library can have multiple apex_available",
|
||||
hasStubs: false,
|
||||
apexAvailable: `["myapex", "otherapex"]`,
|
||||
},
|
||||
{
|
||||
desc: "stub library should not be available to anyapex",
|
||||
hasStubs: true,
|
||||
apexAvailable: `["//apex_available:anyapex"]`,
|
||||
expectedError: "Stub libraries should have a single apex_available.*anyapex",
|
||||
},
|
||||
{
|
||||
desc: "stub library should not be available to multiple apexes",
|
||||
hasStubs: true,
|
||||
apexAvailable: `["myapex", "otherapex"]`,
|
||||
expectedError: "Stub libraries should have a single apex_available.*myapex.*otherapex",
|
||||
},
|
||||
{
|
||||
desc: "stub library can be available to a core apex and a test apex",
|
||||
hasStubs: true,
|
||||
apexAvailable: `["myapex", "test_myapex"]`,
|
||||
},
|
||||
}
|
||||
bpTemplate := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
%v
|
||||
apex_available: %v,
|
||||
}
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "apex.key",
|
||||
updatable: false,
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
apex {
|
||||
name: "otherapex",
|
||||
key: "apex.key",
|
||||
updatable: false,
|
||||
}
|
||||
apex_test {
|
||||
name: "test_myapex",
|
||||
key: "apex.key",
|
||||
updatable: false,
|
||||
native_shared_libs: ["libfoo"],
|
||||
}
|
||||
apex_key {
|
||||
name: "apex.key",
|
||||
}
|
||||
`
|
||||
for _, tc := range testCases {
|
||||
stubs := ""
|
||||
if tc.hasStubs {
|
||||
stubs = `stubs: {symbol_file: "libfoo.map.txt"},`
|
||||
}
|
||||
bp := fmt.Sprintf(bpTemplate, stubs, tc.apexAvailable)
|
||||
mockFsFixturePreparer := android.FixtureModifyMockFS(func(fs android.MockFS) {
|
||||
fs["system/sepolicy/apex/test_myapex-file_contexts"] = nil
|
||||
})
|
||||
if tc.expectedError == "" {
|
||||
testApex(t, bp, mockFsFixturePreparer)
|
||||
} else {
|
||||
testApexError(t, tc.expectedError, bp, mockFsFixturePreparer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
54
cc/cc.go
54
cc/cc.go
@@ -1987,6 +1987,56 @@ func moduleContextFromAndroidModuleContext(actx android.ModuleContext, c *Module
|
||||
return ctx
|
||||
}
|
||||
|
||||
// TODO (b/277651159): Remove this allowlist
|
||||
var (
|
||||
skipStubLibraryMultipleApexViolation = map[string]bool{
|
||||
"libclang_rt.asan": true,
|
||||
"libclang_rt.hwasan": true,
|
||||
// runtime apex
|
||||
"libc": true,
|
||||
"libc_hwasan": true,
|
||||
"libdl_android": true,
|
||||
"libm": true,
|
||||
"libdl": true,
|
||||
// art apex
|
||||
"libandroidio": true,
|
||||
"libdexfile": true,
|
||||
"libnativebridge": true,
|
||||
"libnativehelper": true,
|
||||
"libnativeloader": true,
|
||||
"libsigchain": true,
|
||||
}
|
||||
)
|
||||
|
||||
// Returns true if a stub library could be installed in multiple apexes
|
||||
func (c *Module) stubLibraryMultipleApexViolation(ctx android.ModuleContext) bool {
|
||||
// If this is not an apex variant, no check necessary
|
||||
if !c.InAnyApex() {
|
||||
return false
|
||||
}
|
||||
// If this is not a stub library, no check necessary
|
||||
if !c.HasStubsVariants() {
|
||||
return false
|
||||
}
|
||||
// Skip the allowlist
|
||||
// Use BaseModuleName so that this matches prebuilts.
|
||||
if _, exists := skipStubLibraryMultipleApexViolation[c.BaseModuleName()]; exists {
|
||||
return false
|
||||
}
|
||||
|
||||
_, aaWithoutTestApexes, _ := android.ListSetDifference(c.ApexAvailable(), c.TestApexes())
|
||||
// Stub libraries should not have more than one apex_available
|
||||
if len(aaWithoutTestApexes) > 1 {
|
||||
return true
|
||||
}
|
||||
// Stub libraries should not use the wildcard
|
||||
if aaWithoutTestApexes[0] == android.AvailableToAnyApex {
|
||||
return true
|
||||
}
|
||||
// Default: no violation
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
// Handle the case of a test module split by `test_per_src` mutator.
|
||||
//
|
||||
@@ -2013,6 +2063,10 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||
return
|
||||
}
|
||||
|
||||
if c.stubLibraryMultipleApexViolation(actx) {
|
||||
actx.PropertyErrorf("apex_available",
|
||||
"Stub libraries should have a single apex_available (test apexes excluded). Got %v", c.ApexAvailable())
|
||||
}
|
||||
if c.Properties.Clang != nil && *c.Properties.Clang == false {
|
||||
ctx.PropertyErrorf("clang", "false (GCC) is no longer supported")
|
||||
} else if c.Properties.Clang != nil && !ctx.DeviceConfig().BuildBrokenClangProperty() {
|
||||
|
Reference in New Issue
Block a user