diff --git a/apex/apex.go b/apex/apex.go index 1d50cee3b..b324644a1 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -492,6 +492,19 @@ func getCopyManifestForNativeLibrary(cc *cc.Module) (fileToCopy android.Path, di if !cc.Arch().Native { 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() return diff --git a/apex/apex_test.go b/apex/apex_test.go index f8f9b33b4..d4f0f7e3f 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -492,6 +492,13 @@ func TestApexWithSystemLibsStubs(t *testing.T) { versions: ["27", "28", "29"], }, } + + cc_library { + name: "libBootstrap", + srcs: ["mylib.cpp"], + stl: "none", + bootstrap: true, + } `) 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. ensureContains(t, copyCmds, "image.apex/lib64/mylib.so") - ensureContains(t, copyCmds, "image.apex/lib64/libm.so") - ensureContains(t, copyCmds, "image.apex/lib64/libdl.so") + ensureContains(t, copyCmds, "image.apex/lib64/bionic/libm.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) - 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"] 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 ensureContains(t, mylibCFlags, "__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) { diff --git a/cc/androidmk.go b/cc/androidmk.go index 82feec833..784475612 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -29,9 +29,12 @@ var ( ) type AndroidMkContext interface { + Name() string Target() android.Target subAndroidMk(*android.AndroidMkData, interface{}) useVndk() bool + static() bool + inRecovery() bool } type subAndroidMkProvider interface { @@ -59,8 +62,12 @@ func (c *Module) AndroidMk() android.AndroidMkData { ret := android.AndroidMkData{ OutputFile: c.outputFile, - Required: append(c.Properties.AndroidMkRuntimeLibs, c.Properties.ApexesProvidingSharedLibs...), - Include: "$(BUILD_SYSTEM)/soong_cc_prebuilt.mk", + // TODO(jiyong): add the APEXes providing shared libs to the required modules + // 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{ 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) } else { ret.Extra = append(ret.Extra, func(w io.Writer, outputFile android.Path) { 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) { diff --git a/cc/cc.go b/cc/cc.go index ce28a3bf4..85e3a6718 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -201,6 +201,10 @@ type BaseProperties struct { Recovery_available *bool 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 { @@ -250,6 +254,8 @@ type ModuleContextIntf interface { isPgoCompile() bool useClangLld(actx ModuleContext) bool isApex() bool + hasStubsVariants() bool + isStubs() bool } type ModuleContext interface { @@ -676,6 +682,14 @@ func (ctx *moduleContextImpl) isApex() bool { 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 { return &Module{ hod: hod, @@ -855,6 +869,18 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { return } 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 .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() { @@ -1446,8 +1472,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { // If not building for APEX, use stubs only when it is from // an APEX (and not from platform) useThisDep = (depInPlatform != depIsStubs) - if c.inRecovery() { - // However, for recovery modules, since there is no APEX there, + if c.inRecovery() || Bool(c.Properties.Bootstrap) { + // However, for recovery or bootstrap modules, // always link to non-stub variant useThisDep = !depIsStubs }