Rename non-stubs variant of a lib if it is included in APEX
If a lib is directly included in an APEX (via native_shared_libs property) and the lib has stubs (via stubs.versions property), then the ordinary non-stubs variant of the library is renamed to <libname>.bootstrap in the makefile. At the same time, the stubs variant of the lib becomes visible and it's name is <libname>. This ensures that modules in Android.mk build against the stubs variant thus preventing them from using private APIs in the lib. The non-stubs variant, however, is used if the module explicitly has set the new 'bootstrap' property to true. This is useful for building some early binaries (such as init and vold) which need to run before APEXes are activated. Since they can't use the bionic libs from the runtime APEX, they should use the bionic libs left in the system partition which is called the boostrap bionic. Bug: 120266448 Test: m Test: m with https://android-review.googlesource.com/c/platform/bionic/+/849044 Change-Id: I882b8aeb5b29460f07b4424e4f8eb844d6c9a9b0
This commit is contained in:
parent
10ed054a6b
commit
b07885714c
13
apex/apex.go
13
apex/apex.go
|
@ -492,6 +492,19 @@ func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, di
|
||||||
if !cc.Arch().Native {
|
if !cc.Arch().Native {
|
||||||
dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
|
dirInApex = filepath.Join(dirInApex, cc.Arch().ArchType.String())
|
||||||
}
|
}
|
||||||
|
switch cc.Name() {
|
||||||
|
case "libc", "libm", "libdl":
|
||||||
|
// Special case for bionic libs. This is to prevent the bionic libs
|
||||||
|
// from being included in the search path /apex/com.android.apex/lib.
|
||||||
|
// This exclusion is required because bionic libs in the runtime APEX
|
||||||
|
// are available via the legacy paths /system/lib/libc.so, etc. By the
|
||||||
|
// init process, the bionic libs in the APEX are bind-mounted to the
|
||||||
|
// legacy paths and thus will be loaded into the default linker namespace.
|
||||||
|
// If the bionic libs are directly in /apex/com.android.apex/lib then
|
||||||
|
// the same libs will be again loaded to the runtime linker namespace,
|
||||||
|
// which will result double loading of bionic libs that isn't supported.
|
||||||
|
dirInApex = filepath.Join(dirInApex, "bionic")
|
||||||
|
}
|
||||||
|
|
||||||
fileToCopy = cc.OutputFile().Path()
|
fileToCopy = cc.OutputFile().Path()
|
||||||
return
|
return
|
||||||
|
|
|
@ -492,6 +492,13 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
|
||||||
versions: ["27", "28", "29"],
|
versions: ["27", "28", "29"],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc_library {
|
||||||
|
name: "libBootstrap",
|
||||||
|
srcs: ["mylib.cpp"],
|
||||||
|
stl: "none",
|
||||||
|
bootstrap: true,
|
||||||
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
|
apexRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexRule")
|
||||||
|
@ -499,11 +506,11 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
|
||||||
|
|
||||||
// Ensure that mylib, libm, libdl are included.
|
// Ensure that mylib, libm, libdl are included.
|
||||||
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
|
ensureContains(t, copyCmds, "image.apex/lib64/mylib.so")
|
||||||
ensureContains(t, copyCmds, "image.apex/lib64/libm.so")
|
ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.so")
|
||||||
ensureContains(t, copyCmds, "image.apex/lib64/libdl.so")
|
ensureContains(t, copyCmds, "image.apex/lib64/bionic/libdl.so")
|
||||||
|
|
||||||
// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
|
// Ensure that libc is not included (since it has stubs and not listed in native_shared_libs)
|
||||||
ensureNotContains(t, copyCmds, "image.apex/lib64/libc.so")
|
ensureNotContains(t, copyCmds, "image.apex/lib64/bionic/libc.so")
|
||||||
|
|
||||||
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"]
|
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_shared_myapex").Rule("ld").Args["libFlags"]
|
||||||
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
|
mylibCFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_core_static_myapex").Rule("cc").Args["cFlags"]
|
||||||
|
@ -538,6 +545,12 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
|
||||||
// ... Cflags from stub is correctly exported to mylib
|
// ... Cflags from stub is correctly exported to mylib
|
||||||
ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
|
ensureContains(t, mylibCFlags, "__LIBDL_API__=27")
|
||||||
ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
|
ensureContains(t, mylibSharedCFlags, "__LIBDL_API__=27")
|
||||||
|
|
||||||
|
// Ensure that libBootstrap is depending on the platform variant of bionic libs
|
||||||
|
libFlags := ctx.ModuleForTests("libBootstrap", "android_arm64_armv8-a_core_shared").Rule("ld").Args["libFlags"]
|
||||||
|
ensureContains(t, libFlags, "libc/android_arm64_armv8-a_core_shared/libc.so")
|
||||||
|
ensureContains(t, libFlags, "libm/android_arm64_armv8-a_core_shared/libm.so")
|
||||||
|
ensureContains(t, libFlags, "libdl/android_arm64_armv8-a_core_shared/libdl.so")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFilesInSubDir(t *testing.T) {
|
func TestFilesInSubDir(t *testing.T) {
|
||||||
|
|
|
@ -29,9 +29,12 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type AndroidMkContext interface {
|
type AndroidMkContext interface {
|
||||||
|
Name() string
|
||||||
Target() android.Target
|
Target() android.Target
|
||||||
subAndroidMk(*android.AndroidMkData, interface{})
|
subAndroidMk(*android.AndroidMkData, interface{})
|
||||||
useVndk() bool
|
useVndk() bool
|
||||||
|
static() bool
|
||||||
|
inRecovery() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type subAndroidMkProvider interface {
|
type subAndroidMkProvider interface {
|
||||||
|
@ -59,8 +62,12 @@ func (c *Module) AndroidMk() android.AndroidMkData {
|
||||||
|
|
||||||
ret := android.AndroidMkData{
|
ret := android.AndroidMkData{
|
||||||
OutputFile: c.outputFile,
|
OutputFile: c.outputFile,
|
||||||
Required: append(c.Properties.AndroidMkRuntimeLibs, c.Properties.ApexesProvidingSharedLibs...),
|
// TODO(jiyong): add the APEXes providing shared libs to the required modules
|
||||||
Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
|
// Currently, adding c.Properties.ApexesProvidingSharedLibs is causing multiple
|
||||||
|
// runtime APEXes (com.android.runtime.debug|release) to be installed. And this
|
||||||
|
// is breaking some older devices (like marlin) where system.img is small.
|
||||||
|
Required: c.Properties.AndroidMkRuntimeLibs,
|
||||||
|
Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk",
|
||||||
|
|
||||||
Extra: []android.AndroidMkExtraFunc{
|
Extra: []android.AndroidMkExtraFunc{
|
||||||
func(w io.Writer, outputFile android.Path) {
|
func(w io.Writer, outputFile android.Path) {
|
||||||
|
@ -172,13 +179,23 @@ func (library *libraryDecorator) AndroidMk(ctx AndroidMkContext, ret *android.An
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if library.shared() {
|
if library.shared() && !library.buildStubs() {
|
||||||
ctx.subAndroidMk(ret, library.baseInstaller)
|
ctx.subAndroidMk(ret, library.baseInstaller)
|
||||||
} else {
|
} else {
|
||||||
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
|
ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) {
|
||||||
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
|
fmt.Fprintln(w, "LOCAL_UNINSTALLABLE_MODULE := true")
|
||||||
|
if library.buildStubs() {
|
||||||
|
fmt.Fprintln(w, "LOCAL_NO_NOTICE_FILE := true")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(library.Properties.Stubs.Versions) > 0 && android.DirectlyInAnyApex(ctx.Name()) &&
|
||||||
|
!ctx.inRecovery() && !ctx.useVndk() && !ctx.static() {
|
||||||
|
if !library.buildStubs() {
|
||||||
|
ret.SubName = ".bootstrap"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (object *objectLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
|
func (object *objectLinker) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkData) {
|
||||||
|
|
30
cc/cc.go
30
cc/cc.go
|
@ -201,6 +201,10 @@ type BaseProperties struct {
|
||||||
Recovery_available *bool
|
Recovery_available *bool
|
||||||
|
|
||||||
InRecovery bool `blueprint:"mutated"`
|
InRecovery bool `blueprint:"mutated"`
|
||||||
|
|
||||||
|
// Allows this module to use non-APEX version of libraries. Useful
|
||||||
|
// for building binaries that are started before APEXes are activated.
|
||||||
|
Bootstrap *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type VendorProperties struct {
|
type VendorProperties struct {
|
||||||
|
@ -250,6 +254,8 @@ type ModuleContextIntf interface {
|
||||||
isPgoCompile() bool
|
isPgoCompile() bool
|
||||||
useClangLld(actx ModuleContext) bool
|
useClangLld(actx ModuleContext) bool
|
||||||
isApex() bool
|
isApex() bool
|
||||||
|
hasStubsVariants() bool
|
||||||
|
isStubs() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleContext interface {
|
type ModuleContext interface {
|
||||||
|
@ -676,6 +682,14 @@ func (ctx *moduleContextImpl) isApex() bool {
|
||||||
return ctx.mod.ApexName() != ""
|
return ctx.mod.ApexName() != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *moduleContextImpl) hasStubsVariants() bool {
|
||||||
|
return ctx.mod.HasStubsVariants()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx *moduleContextImpl) isStubs() bool {
|
||||||
|
return ctx.mod.IsStubs()
|
||||||
|
}
|
||||||
|
|
||||||
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
||||||
return &Module{
|
return &Module{
|
||||||
hod: hod,
|
hod: hod,
|
||||||
|
@ -855,6 +869,18 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.outputFile = android.OptionalPathForPath(outputFile)
|
c.outputFile = android.OptionalPathForPath(outputFile)
|
||||||
|
|
||||||
|
// If a lib is directly included in any of the APEXes, unhide the stubs
|
||||||
|
// variant having the latest version gets visible to make. In addition,
|
||||||
|
// the non-stubs variant is renamed to <libname>.bootstrap. This is to
|
||||||
|
// force anything in the make world to link against the stubs library.
|
||||||
|
// (unless it is explicitly referenced via .bootstrap suffix or the
|
||||||
|
// module is marked with 'bootstrap: true').
|
||||||
|
if c.HasStubsVariants() && android.DirectlyInAnyApex(ctx.baseModuleName()) &&
|
||||||
|
!c.inRecovery() && !c.useVndk() && !c.static() && c.IsStubs() {
|
||||||
|
c.Properties.HideFromMake = false // unhide
|
||||||
|
// Note: this is still non-installable
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() {
|
if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() {
|
||||||
|
@ -1446,8 +1472,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
||||||
// If not building for APEX, use stubs only when it is from
|
// If not building for APEX, use stubs only when it is from
|
||||||
// an APEX (and not from platform)
|
// an APEX (and not from platform)
|
||||||
useThisDep = (depInPlatform != depIsStubs)
|
useThisDep = (depInPlatform != depIsStubs)
|
||||||
if c.inRecovery() {
|
if c.inRecovery() || Bool(c.Properties.Bootstrap) {
|
||||||
// However, for recovery modules, since there is no APEX there,
|
// However, for recovery or bootstrap modules,
|
||||||
// always link to non-stub variant
|
// always link to non-stub variant
|
||||||
useThisDep = !depIsStubs
|
useThisDep = !depIsStubs
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue