diff --git a/android/makevars.go b/android/makevars.go index 5101436db..546abcfb0 100644 --- a/android/makevars.go +++ b/android/makevars.go @@ -90,6 +90,7 @@ type MakeVarsContext interface { ModuleDir(module blueprint.Module) string ModuleSubDir(module blueprint.Module) string ModuleType(module blueprint.Module) string + ModuleProvider(module blueprint.Module, key blueprint.ProviderKey) interface{} BlueprintFile(module blueprint.Module) string ModuleErrorf(module blueprint.Module, format string, args ...interface{}) diff --git a/apex/apex_test.go b/apex/apex_test.go index 4a6aecfdf..cb43e2429 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -1355,9 +1355,9 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) { ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libbar.so") mylibLdFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_shared_"+tc.apexVariant).Rule("ld").Args["libFlags"] - ensureContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so") + ensureContains(t, mylibLdFlags, "libbar/android_vendor.VER_arm64_armv8-a_shared_"+tc.shouldLink+"/libbar.so") for _, ver := range tc.shouldNotLink { - ensureNotContains(t, mylibLdFlags, "libbar.llndk/android_vendor.VER_arm64_armv8-a_shared_"+ver+"/libbar.so") + ensureNotContains(t, mylibLdFlags, "libbar/android_vendor.VER_arm64_armv8-a_shared_"+ver+"/libbar.so") } mylibCFlags := ctx.ModuleForTests("mylib", "android_vendor.VER_arm64_armv8-a_static_"+tc.apexVariant).Rule("cc").Args["cFlags"] diff --git a/cc/androidmk.go b/cc/androidmk.go index ddacb70f3..c4b9cd574 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -269,7 +269,7 @@ func (library *libraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries if library.shared() && !library.buildStubs() { ctx.subAndroidMk(entries, library.baseInstaller) } else { - if library.buildStubs() { + if library.buildStubs() && library.stubsVersion() != "" { entries.SubName = "." + library.stubsVersion() } entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { @@ -471,18 +471,9 @@ func (c *stubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android. } func (c *llndkStubDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { - entries.Class = "SHARED_LIBRARIES" - entries.OverrideName = c.implementationModuleName(ctx.BaseModuleName()) - - entries.ExtraEntries = append(entries.ExtraEntries, func(entries *android.AndroidMkEntries) { - c.libraryDecorator.androidMkWriteExportedFlags(entries) - _, _, ext := android.SplitFileExt(entries.OutputFile.Path().Base()) - - entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext) - entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true) - entries.SetBool("LOCAL_NO_NOTICE_FILE", true) - entries.SetString("LOCAL_SOONG_TOC", c.toc().String()) - }) + // Don't write anything for an llndk_library module, the vendor variant of the cc_library + // module will write the Android.mk entries. + entries.Disabled = true } func (c *vndkPrebuiltLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) { diff --git a/cc/cc.go b/cc/cc.go index 1cc2bd57c..a023f3f83 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -390,6 +390,13 @@ type VendorProperties struct { // explicitly marked as `double_loadable: true` by the owner, or the dependency // from the LLNDK lib should be cut if the lib is not designed to be double loaded. Double_loadable *bool + + // IsLLNDK is set to true for the vendor variant of a cc_library module that has LLNDK stubs. + IsLLNDK bool `blueprint:"mutated"` + + // IsLLNDKPrivate is set to true for the vendor variant of a cc_library module that has LLNDK + // stubs and also sets llndk.vendor_available: false. + IsLLNDKPrivate bool `blueprint:"mutated"` } // ModuleContextIntf is an interface (on a module context helper) consisting of functions related @@ -408,9 +415,10 @@ type ModuleContextIntf interface { sdkVersion() string useVndk() bool isNdk(config android.Config) bool - isLlndk(config android.Config) bool - isLlndkPublic(config android.Config) bool - isVndkPrivate(config android.Config) bool + IsLlndk() bool + IsLlndkPublic() bool + isImplementationForLLNDKPublic() bool + IsVndkPrivate() bool isVndk() bool isVndkSp() bool IsVndkExt() bool @@ -645,6 +653,7 @@ var ( runtimeDepTag = installDependencyTag{name: "runtime lib"} testPerSrcDepTag = dependencyTag{name: "test_per_src"} stubImplDepTag = dependencyTag{name: "stub_impl"} + llndkStubDepTag = dependencyTag{name: "llndk stub"} ) type copyDirectlyInAnyApexDependencyTag dependencyTag @@ -1028,20 +1037,34 @@ func (c *Module) IsNdk(config android.Config) bool { return inList(c.BaseModuleName(), *getNDKKnownLibs(config)) } -func (c *Module) isLlndk(config android.Config) bool { - // Returns true for both LLNDK (public) and LLNDK-private libs. - return isLlndkLibrary(c.BaseModuleName(), config) +// isLLndk returns true for both LLNDK (public) and LLNDK-private libs. +func (c *Module) IsLlndk() bool { + return c.VendorProperties.IsLLNDK } -func (c *Module) isLlndkPublic(config android.Config) bool { - // Returns true only for LLNDK (public) libs. - name := c.BaseModuleName() - return isLlndkLibrary(name, config) && !isVndkPrivateLibrary(name, config) +// IsLlndkPublic returns true only for LLNDK (public) libs. +func (c *Module) IsLlndkPublic() bool { + return c.VendorProperties.IsLLNDK && !c.VendorProperties.IsLLNDKPrivate } -func (c *Module) IsVndkPrivate(config android.Config) bool { +// isImplementationForLLNDKPublic returns true for any variant of a cc_library that has LLNDK stubs +// and does not set llndk.vendor_available: false. +func (c *Module) isImplementationForLLNDKPublic() bool { + library, _ := c.library.(*libraryDecorator) + return library != nil && library.hasLLNDKStubs() && + (Bool(library.Properties.Llndk.Vendor_available) || + // TODO(b/170784825): until the LLNDK properties are moved into the cc_library, + // the non-Vendor variants of the cc_library don't know if the corresponding + // llndk_library set vendor_available: false. Since libft2 is the only + // private LLNDK library, hardcode it during the transition. + c.BaseModuleName() != "libft2") +} + +func (c *Module) IsVndkPrivate() bool { // Returns true for LLNDK-private, VNDK-SP-private, and VNDK-core-private. - return isVndkPrivateLibrary(c.BaseModuleName(), config) + library, _ := c.library.(*libraryDecorator) + return library != nil && !Bool(library.Properties.Llndk.Vendor_available) && + !Bool(c.VendorProperties.Vendor_available) && !c.IsVndkExt() } func (c *Module) IsVndk() bool { @@ -1247,16 +1270,20 @@ func (ctx *moduleContextImpl) isNdk(config android.Config) bool { return ctx.mod.IsNdk(config) } -func (ctx *moduleContextImpl) isLlndk(config android.Config) bool { - return ctx.mod.isLlndk(config) +func (ctx *moduleContextImpl) IsLlndk() bool { + return ctx.mod.IsLlndk() } -func (ctx *moduleContextImpl) isLlndkPublic(config android.Config) bool { - return ctx.mod.isLlndkPublic(config) +func (ctx *moduleContextImpl) IsLlndkPublic() bool { + return ctx.mod.IsLlndkPublic() } -func (ctx *moduleContextImpl) isVndkPrivate(config android.Config) bool { - return ctx.mod.IsVndkPrivate(config) +func (ctx *moduleContextImpl) isImplementationForLLNDKPublic() bool { + return ctx.mod.isImplementationForLLNDKPublic() +} + +func (ctx *moduleContextImpl) IsVndkPrivate() bool { + return ctx.mod.IsVndkPrivate() } func (ctx *moduleContextImpl) isVndk() bool { @@ -1407,7 +1434,7 @@ func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string if vndkVersion == "current" { vndkVersion = ctx.DeviceConfig().PlatformVndkVersion() } - if c.Properties.VndkVersion != vndkVersion { + if c.Properties.VndkVersion != vndkVersion && c.Properties.VndkVersion != "" { // add version suffix only if the module is using different vndk version than the // version in product or vendor partition. nameSuffix += "." + c.Properties.VndkVersion @@ -1439,7 +1466,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { c.Properties.SubName += nativeBridgeSuffix } - _, llndk := c.linker.(*llndkStubDecorator) + llndk := c.IsLlndk() _, llndkHeader := c.linker.(*llndkHeadersDecorator) if llndk || llndkHeader || (c.UseVndk() && c.HasNonSystemVariants()) { // .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is @@ -1817,10 +1844,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) { vendorSnapshotSharedLibs := vendorSnapshotSharedLibs(actx.Config()) rewriteVendorLibs := func(lib string) string { - if isLlndkLibrary(lib, ctx.Config()) { - return lib + llndkLibrarySuffix - } - // only modules with BOARD_VNDK_VERSION uses snapshot. if c.VndkVersion() != actx.DeviceConfig().VndkVersion() { return lib @@ -2237,7 +2260,7 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { return true } - if to.isVndkSp() || to.isLlndk(ctx.Config()) || Bool(to.VendorProperties.Double_loadable) { + if to.isVndkSp() || to.IsLlndk() || Bool(to.VendorProperties.Double_loadable) { return false } @@ -2252,7 +2275,7 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) { } if module, ok := ctx.Module().(*Module); ok { if lib, ok := module.linker.(*libraryDecorator); ok && lib.shared() { - if module.isLlndk(ctx.Config()) || Bool(module.VendorProperties.Double_loadable) { + if lib.hasLLNDKStubs() || Bool(module.VendorProperties.Double_loadable) { ctx.WalkDeps(check) } } @@ -2372,9 +2395,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps { if depTag == android.ProtoPluginDepTag { return } - if depTag == llndkImplDep { - return - } if dep.Target().Os != ctx.Os() { ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName) @@ -2744,7 +2764,8 @@ func (c *Module) makeLibName(ctx android.ModuleContext, ccDep LinkableInterface, vendorPublicLibraries := vendorPublicLibraries(ctx.Config()) libName := baseLibName(depName) - isLLndk := isLlndkLibrary(libName, ctx.Config()) + ccDepModule, _ := ccDep.(*Module) + isLLndk := ccDepModule != nil && ccDepModule.IsLlndk() isVendorPublicLib := inList(libName, *vendorPublicLibraries) bothVendorAndCoreVariantsExist := ccDep.HasVendorVariant() || isLLndk @@ -2896,17 +2917,14 @@ func (c *Module) object() bool { func GetMakeLinkType(actx android.ModuleContext, c LinkableInterface) string { if c.UseVndk() { - if ccModule, ok := c.Module().(*Module); ok { - // Only CC modules provide stubs at the moment. - if lib, ok := ccModule.linker.(*llndkStubDecorator); ok { - if Bool(lib.Properties.Vendor_available) { - return "native:vndk" - } + if c.IsLlndk() { + if !c.IsLlndkPublic() { return "native:vndk_private" } + return "native:vndk" } if c.IsVndk() && !c.IsVndkExt() { - if c.IsVndkPrivate(actx.Config()) { + if c.IsVndkPrivate() { return "native:vndk_private" } return "native:vndk" @@ -3039,7 +3057,7 @@ func (c *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu return false } } - if depTag == stubImplDepTag || depTag == llndkImplDep { + if depTag == stubImplDepTag || depTag == llndkStubDepTag { // We don't track beyond LLNDK or from an implementation library to its stubs. return false } diff --git a/cc/cc_test.go b/cc/cc_test.go index c16cce83c..fe9db37a1 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -1049,6 +1049,16 @@ func TestVendorSnapshotCapture(t *testing.T) { name: "obj", vendor_available: true, } + + cc_library { + name: "libllndk", + llndk_stubs: "libllndk.llndk", + } + + llndk_library { + name: "libllndk.llndk", + symbol_file: "", + } ` config := TestConfig(buildDir, android.Android, nil, bp, nil) config.TestProductVariables.DeviceVndkVersion = StringPtr("current") @@ -1080,6 +1090,9 @@ func TestVendorSnapshotCapture(t *testing.T) { filepath.Join(sharedDir, "libvendor.so.json"), filepath.Join(sharedDir, "libvendor_available.so.json")) + // LLNDK modules are not captured + checkSnapshotExclude(t, ctx, snapshotSingleton, "libllndk", "libllndk.so", sharedDir, sharedVariant) + // For static libraries, all vendor:true and vendor_available modules (including VNDK) are captured. // Also cfi variants are captured, except for prebuilts like toolchain_library staticVariant := fmt.Sprintf("android_vendor.VER_%s_%s_static", archType, archVariant) @@ -2899,7 +2912,7 @@ func TestMakeLinkType(t *testing.T) { {vendorVariant, "libvndkprivate", "native:vndk_private"}, {vendorVariant, "libvendor", "native:vendor"}, {vendorVariant, "libvndkext", "native:vendor"}, - {vendorVariant, "libllndk.llndk", "native:vndk"}, + {vendorVariant, "libllndk", "native:vndk"}, {vendorVariant27, "prevndk.vndk.27.arm.binder32", "native:vndk"}, {coreVariant, "libvndk", "native:platform"}, {coreVariant, "libvndkprivate", "native:platform"}, @@ -3178,8 +3191,39 @@ func TestLlndkLibrary(t *testing.T) { llndk_library { name: "libllndk.llndk", } + + cc_prebuilt_library_shared { + name: "libllndkprebuilt", + stubs: { versions: ["1", "2"] }, + llndk_stubs: "libllndkprebuilt.llndk", + } + llndk_library { + name: "libllndkprebuilt.llndk", + } + + cc_library { + name: "libllndk_with_external_headers", + stubs: { versions: ["1", "2"] }, + llndk_stubs: "libllndk_with_external_headers.llndk", + header_libs: ["libexternal_headers"], + export_header_lib_headers: ["libexternal_headers"], + } + llndk_library { + name: "libllndk_with_external_headers.llndk", + } + cc_library_headers { + name: "libexternal_headers", + export_include_dirs: ["include"], + vendor_available: true, + } `) - actual := ctx.ModuleVariantsForTests("libllndk.llndk") + actual := ctx.ModuleVariantsForTests("libllndk") + for i := 0; i < len(actual); i++ { + if !strings.HasPrefix(actual[i], "android_vendor.VER_") { + actual = append(actual[:i], actual[i+1:]...) + i-- + } + } expected := []string{ "android_vendor.VER_arm64_armv8-a_shared_1", "android_vendor.VER_arm64_armv8-a_shared_2", @@ -3190,10 +3234,10 @@ func TestLlndkLibrary(t *testing.T) { } checkEquals(t, "variants for llndk stubs", expected, actual) - params := ctx.ModuleForTests("libllndk.llndk", "android_vendor.VER_arm_armv7-a-neon_shared").Description("generate stub") + params := ctx.ModuleForTests("libllndk", "android_vendor.VER_arm_armv7-a-neon_shared").Description("generate stub") checkEquals(t, "use VNDK version for default stubs", "current", params.Args["apiLevel"]) - params = ctx.ModuleForTests("libllndk.llndk", "android_vendor.VER_arm_armv7-a-neon_shared_1").Description("generate stub") + params = ctx.ModuleForTests("libllndk", "android_vendor.VER_arm_armv7-a-neon_shared_1").Description("generate stub") checkEquals(t, "override apiLevel for versioned stubs", "1", params.Args["apiLevel"]) } diff --git a/cc/image.go b/cc/image.go index cca454aa9..380c1dbe1 100644 --- a/cc/image.go +++ b/cc/image.go @@ -308,6 +308,18 @@ func (m *Module) ImageMutatorBegin(mctx android.BaseModuleContext) { } else { vendorVariants = append(vendorVariants, platformVndkVersion) } + } else if lib := moduleLibraryInterface(m); lib != nil && lib.hasLLNDKStubs() { + // This is an LLNDK library. The implementation of the library will be on /system, + // and vendor and product variants will be created with LLNDK stubs. + coreVariantNeeded = true + vendorVariants = append(vendorVariants, + platformVndkVersion, + boardVndkVersion, + ) + productVariants = append(productVariants, + platformVndkVersion, + productVndkVersion, + ) } else { // This is either in /system (or similar: /data), or is a // modules built with the NDK. Modules built with the NDK diff --git a/cc/library.go b/cc/library.go index 11ee7ddc4..1d0c018aa 100644 --- a/cc/library.go +++ b/cc/library.go @@ -22,6 +22,7 @@ import ( "strings" "sync" + "github.com/google/blueprint" "github.com/google/blueprint/pathtools" "android/soong/android" @@ -114,6 +115,10 @@ type LibraryProperties struct { // If this is an LLNDK library, the name of the equivalent llndk_library module. Llndk_stubs *string + + // If this is an LLNDK library, properties to describe the LLNDK stubs. Will be copied from + // the module pointed to by llndk_stubs if it is set. + Llndk llndkLibraryProperties } // StaticProperties is a properties stanza to affect only attributes of the "static" variants of a @@ -570,6 +575,12 @@ func (library *libraryDecorator) compilerFlags(ctx ModuleContext, flags Flags, d } flags = library.baseCompiler.compilerFlags(ctx, flags, deps) + if ctx.IsLlndk() { + // LLNDK libraries ignore most of the properties on the cc_library and use the + // LLNDK-specific properties instead. + // Wipe all the module-local properties, leaving only the global properties. + flags.Local = LocalOrGlobalFlags{} + } if library.buildStubs() { // Remove -include when compiling stubs. Otherwise, the force included // headers might cause conflicting types error with the symbols in the @@ -603,6 +614,22 @@ func (library *libraryDecorator) headerAbiCheckerExplicitlyDisabled() bool { } func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects { + if ctx.IsLlndk() { + // This is the vendor variant of an LLNDK library, build the LLNDK stubs. + vndkVer := ctx.Module().(*Module).VndkVersion() + if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" { + // For non-enforcing devices, vndkVer is empty. Use "current" in that case, too. + vndkVer = "current" + } + if library.stubsVersion() != "" { + vndkVer = library.stubsVersion() + } + objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Llndk.Symbol_file), vndkVer, "--llndk") + if !Bool(library.Properties.Llndk.Unversioned) { + library.versionScriptPath = android.OptionalPathForPath(versionScript) + } + return objs + } if library.buildStubs() { objs, versionScript := compileStubLibrary(ctx, flags, String(library.Properties.Stubs.Symbol_file), library.MutatedProperties.StubsVersion, "--apex") library.versionScriptPath = android.OptionalPathForPath(versionScript) @@ -693,6 +720,7 @@ type versionedInterface interface { allStubsVersions() []string implementationModuleName(name string) string + hasLLNDKStubs() bool } var _ libraryInterface = (*libraryDecorator)(nil) @@ -768,12 +796,27 @@ func (library *libraryDecorator) linkerInit(ctx BaseModuleContext) { } func (library *libraryDecorator) compilerDeps(ctx DepsContext, deps Deps) Deps { + if ctx.IsLlndk() { + // LLNDK libraries ignore most of the properties on the cc_library and use the + // LLNDK-specific properties instead. + return deps + } + deps = library.baseCompiler.compilerDeps(ctx, deps) return deps } func (library *libraryDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { + if ctx.IsLlndk() { + // LLNDK libraries ignore most of the properties on the cc_library and use the + // LLNDK-specific properties instead. + deps.HeaderLibs = append(deps.HeaderLibs, library.Properties.Llndk.Export_llndk_headers...) + deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, + library.Properties.Llndk.Export_llndk_headers...) + return deps + } + if library.static() { // Compare with nil because an empty list needs to be propagated. if library.StaticProperties.Static.System_shared_libs != nil { @@ -977,7 +1020,12 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, transformSharedObjectToToc(ctx, outputFile, tocFile, builderFlags) stripFlags := flagsToStripFlags(flags) - if library.stripper.NeedsStrip(ctx) { + needsStrip := library.stripper.NeedsStrip(ctx) + if library.buildStubs() { + // No need to strip stubs libraries + needsStrip = false + } + if needsStrip { if ctx.Darwin() { stripFlags.StripUseGnuStrip = true } @@ -1017,7 +1065,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, linkerDeps = append(linkerDeps, deps.LateSharedLibsDeps...) linkerDeps = append(linkerDeps, objs.tidyFiles...) - if Bool(library.Properties.Sort_bss_symbols_by_size) { + if Bool(library.Properties.Sort_bss_symbols_by_size) && !library.buildStubs() { unsortedOutputFile := android.PathForModuleOut(ctx, "unsorted", fileName) transformObjToDynamicBinary(ctx, objs.objFiles, sharedLibs, deps.StaticLibs, deps.LateStaticLibs, deps.WholeStaticLibs, @@ -1071,7 +1119,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext, ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{ SharedStubLibraries: stubsInfo, - IsLLNDK: ctx.isLlndk(ctx.Config()), + IsLLNDK: ctx.IsLlndk(), }) } @@ -1100,7 +1148,7 @@ func (library *libraryDecorator) coverageOutputFilePath() android.OptionalPath { func getRefAbiDumpFile(ctx ModuleContext, vndkVersion, fileName string) android.Path { // The logic must be consistent with classifySourceAbiDump. isNdk := ctx.isNdk(ctx.Config()) - isLlndkOrVndk := ctx.isLlndkPublic(ctx.Config()) || (ctx.useVndk() && ctx.isVndk()) + isLlndkOrVndk := ctx.IsLlndkPublic() || (ctx.useVndk() && ctx.isVndk()) refAbiDumpTextFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isLlndkOrVndk, false) refAbiDumpGzipFile := android.PathForVndkRefAbiDump(ctx, vndkVersion, fileName, isNdk, isLlndkOrVndk, true) @@ -1153,17 +1201,64 @@ func (library *libraryDecorator) linkSAbiDumpFiles(ctx ModuleContext, objs Objec library.sAbiDiff = sourceAbiDiff(ctx, library.sAbiOutputFile.Path(), refAbiDumpFile, fileName, exportedHeaderFlags, Bool(library.Properties.Header_abi_checker.Check_all_apis), - ctx.isLlndk(ctx.Config()), ctx.isNdk(ctx.Config()), ctx.IsVndkExt()) + ctx.IsLlndk(), ctx.isNdk(ctx.Config()), ctx.IsVndkExt()) } } } +func processLLNDKHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path { + srcDir := android.PathForModuleSrc(ctx, srcHeaderDir) + srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil) + + var installPaths []android.WritablePath + for _, header := range srcFiles { + headerDir := filepath.Dir(header.String()) + relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir) + if err != nil { + ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s", + srcDir.String(), headerDir, err) + continue + } + + installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base())) + } + + return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths) +} + // link registers actions to link this library, and sets various fields // on this library to reflect information that should be exported up the build // tree (for example, exported flags and include paths). func (library *libraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { + if ctx.IsLlndk() { + if len(library.Properties.Llndk.Export_preprocessed_headers) > 0 { + // This is the vendor variant of an LLNDK library with preprocessed headers. + genHeaderOutDir := android.PathForModuleGen(ctx, "include") + + var timestampFiles android.Paths + for _, dir := range library.Properties.Llndk.Export_preprocessed_headers { + timestampFiles = append(timestampFiles, processLLNDKHeaders(ctx, dir, genHeaderOutDir)) + } + + if Bool(library.Properties.Llndk.Export_headers_as_system) { + library.reexportSystemDirs(genHeaderOutDir) + } else { + library.reexportDirs(genHeaderOutDir) + } + + library.reexportDeps(timestampFiles...) + } + + if Bool(library.Properties.Llndk.Export_headers_as_system) { + library.flagExporter.Properties.Export_system_include_dirs = append( + library.flagExporter.Properties.Export_system_include_dirs, + library.flagExporter.Properties.Export_include_dirs...) + library.flagExporter.Properties.Export_include_dirs = nil + } + } + // Linking this library consists of linking `deps.Objs` (.o files in dependencies // of this library), together with `objs` (.o files created by compiling this // library). @@ -1246,7 +1341,7 @@ func (library *libraryDecorator) link(ctx ModuleContext, } func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) { - if library.buildStubs() && !library.skipAPIDefine { + if library.buildStubs() && library.stubsVersion() != "" && !library.skipAPIDefine { name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx)) ver := library.stubsVersion() library.reexportFlags("-D" + name + "=" + ver) @@ -1334,7 +1429,7 @@ func (library *libraryDecorator) install(ctx ModuleContext, file android.Path) { } library.baseInstaller.subDir = "bootstrap" } - } else if ctx.directlyInAnyApex() && ctx.isLlndk(ctx.Config()) && !isBionic(ctx.baseModuleName()) { + } else if ctx.directlyInAnyApex() && ctx.IsLlndk() && !isBionic(ctx.baseModuleName()) { // Skip installing LLNDK (non-bionic) libraries moved to APEX. ctx.Module().HideFromMake() } @@ -1411,6 +1506,11 @@ func (library *libraryDecorator) HeaderOnly() { library.MutatedProperties.BuildStatic = false } +// hasLLNDKStubs returns true if this cc_library module has a variant that will build LLNDK stubs. +func (library *libraryDecorator) hasLLNDKStubs() bool { + return String(library.Properties.Llndk_stubs) != "" +} + func (library *libraryDecorator) implementationModuleName(name string) string { return name } @@ -1423,6 +1523,9 @@ func (library *libraryDecorator) symbolFileForAbiCheck(ctx ModuleContext) *strin if library.Properties.Header_abi_checker.Symbol_file != nil { return library.Properties.Header_abi_checker.Symbol_file } + if ctx.Module().(*Module).IsLlndk() { + return library.Properties.Llndk.Symbol_file + } if library.hasStubsVariants() && library.Properties.Stubs.Symbol_file != nil { return library.Properties.Stubs.Symbol_file } @@ -1587,7 +1690,9 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { library := mctx.Module().(*Module).linker.(prebuiltLibraryInterface) // Differentiate between header only and building an actual static/shared library - if library.buildStatic() || library.buildShared() { + buildStatic := library.buildStatic() + buildShared := library.buildShared() + if buildStatic || buildShared { // Always create both the static and shared variants for prebuilt libraries, and then disable the one // that is not being used. This allows them to share the name of a cc_library module, which requires that // all the variants of the cc_library also exist on the prebuilt. @@ -1598,16 +1703,16 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { static.linker.(prebuiltLibraryInterface).setStatic() shared.linker.(prebuiltLibraryInterface).setShared() - if library.buildShared() { + if buildShared { mctx.AliasVariation("shared") - } else if library.buildStatic() { + } else if buildStatic { mctx.AliasVariation("static") } - if !library.buildStatic() { + if !buildStatic { static.linker.(prebuiltLibraryInterface).disablePrebuilt() } - if !library.buildShared() { + if !buildShared { shared.linker.(prebuiltLibraryInterface).disablePrebuilt() } } else { @@ -1622,7 +1727,18 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { variations = append(variations, "") } - if library.BuildStaticVariant() && library.BuildSharedVariant() { + isLLNDK := false + if m, ok := mctx.Module().(*Module); ok { + isLLNDK = m.IsLlndk() + // Don't count the vestigial llndk_library module as isLLNDK, it needs a static + // variant so that a cc_library_prebuilt can depend on it. + if _, ok := m.linker.(*llndkStubDecorator); ok { + isLLNDK = false + } + } + buildStatic := library.BuildStaticVariant() && !isLLNDK + buildShared := library.BuildSharedVariant() + if buildStatic && buildShared { variations := append([]string{"static", "shared"}, variations...) modules := mctx.CreateLocalVariations(variations...) @@ -1636,13 +1752,13 @@ func LinkageMutator(mctx android.BottomUpMutatorContext) { reuseStaticLibrary(mctx, static.(*Module), shared.(*Module)) } mctx.AliasVariation("shared") - } else if library.BuildStaticVariant() { + } else if buildStatic { variations := append([]string{"static"}, variations...) modules := mctx.CreateLocalVariations(variations...) modules[0].(LinkableInterface).SetStatic() mctx.AliasVariation("static") - } else if library.BuildSharedVariant() { + } else if buildShared { variations := append([]string{"shared"}, variations...) modules := mctx.CreateLocalVariations(variations...) @@ -1675,22 +1791,32 @@ func normalizeVersions(ctx android.BaseModuleContext, versions []string) { } func createVersionVariations(mctx android.BottomUpMutatorContext, versions []string) { - // "" is for the non-stubs (implementation) variant. + // "" is for the non-stubs (implementation) variant for system modules, or the LLNDK variant + // for LLNDK modules. variants := append(android.CopyOf(versions), "") + m := mctx.Module().(*Module) + isLLNDK := m.IsLlndk() + modules := mctx.CreateLocalVariations(variants...) for i, m := range modules { - if variants[i] != "" { + + if variants[i] != "" || isLLNDK { + // A stubs or LLNDK stubs variant. c := m.(*Module) - c.Properties.HideFromMake = true c.sanitize = nil c.stl = nil c.Properties.PreventInstall = true lib := moduleLibraryInterface(m) lib.setBuildStubs() - lib.setStubsVersion(variants[i]) - // The implementation depends on the stubs - mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i]) + + if variants[i] != "" { + // A non-LLNDK stubs module is hidden from make and has a dependency from the + // implementation module to the stubs module. + c.Properties.HideFromMake = true + lib.setStubsVersion(variants[i]) + mctx.AddInterVariantDependency(stubImplDepTag, modules[len(modules)-1], modules[i]) + } } } mctx.AliasVariation("") @@ -1737,7 +1863,7 @@ func CanBeVersionVariant(module interface { module.CcLibraryInterface() && module.Shared() } -func moduleLibraryInterface(module android.Module) libraryInterface { +func moduleLibraryInterface(module blueprint.Module) libraryInterface { if m, ok := module.(*Module); ok { return m.library } @@ -1758,7 +1884,15 @@ func versionSelectorMutator(mctx android.BottomUpMutatorContext) { // Set the versions on the pre-mutated module so they can be read by any llndk modules that // depend on the implementation library and haven't been mutated yet. library.setAllStubsVersions(versions) - return + } + + if mctx.Module().(*Module).UseVndk() && library.hasLLNDKStubs() { + // Propagate the version to the llndk stubs module. + mctx.VisitDirectDepsWithTag(llndkStubDepTag, func(stubs android.Module) { + if stubsLib := moduleLibraryInterface(stubs); stubsLib != nil { + stubsLib.setAllStubsVersions(library.allStubsVersions()) + } + }) } } } diff --git a/cc/linkable.go b/cc/linkable.go index d0109856a..489063f1f 100644 --- a/cc/linkable.go +++ b/cc/linkable.go @@ -43,9 +43,11 @@ type LinkableInterface interface { UseSdk() bool UseVndk() bool MustUseVendorVariant() bool + IsLlndk() bool + IsLlndkPublic() bool IsVndk() bool IsVndkExt() bool - IsVndkPrivate(config android.Config) bool + IsVndkPrivate() bool HasVendorVariant() bool InProduct() bool diff --git a/cc/llndk_library.go b/cc/llndk_library.go index 212720b55..d0fbc480e 100644 --- a/cc/llndk_library.go +++ b/cc/llndk_library.go @@ -15,21 +15,21 @@ package cc import ( - "fmt" - "path/filepath" "strings" "android/soong/android" ) -var llndkImplDep = dependencyTag{name: "llndk impl"} - var ( llndkLibrarySuffix = ".llndk" llndkHeadersSuffix = ".llndk" ) -// Creates a stub shared library based on the provided version file. +// Holds properties to describe a stub shared library based on the provided version file. +// The stub library will actually be built by the cc_library module that points to this +// module with the llndk_stubs property. +// TODO(ccross): move the properties from llndk_library modules directly into the cc_library +// modules and remove the llndk_library modules. // // Example: // @@ -64,43 +64,32 @@ type llndkLibraryProperties struct { // list of llndk headers to re-export include directories from. Export_llndk_headers []string `android:"arch_variant"` + + // whether this module can be directly depended upon by libs that are installed + // to /vendor and /product. + // When set to true, this module can only be depended on by VNDK libraries, not + // vendor nor product libraries. This effectively hides this module from + // non-system modules. Default value is false. + Private *bool } type llndkStubDecorator struct { *libraryDecorator Properties llndkLibraryProperties - - movedToApex bool } var _ versionedInterface = (*llndkStubDecorator)(nil) func (stub *llndkStubDecorator) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags { - flags = stub.baseCompiler.compilerFlags(ctx, flags, deps) - return addStubLibraryCompilerFlags(flags) + return flags } func (stub *llndkStubDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects { - vndkVer := ctx.Module().(*Module).VndkVersion() - if !inList(vndkVer, ctx.Config().PlatformVersionActiveCodenames()) || vndkVer == "" { - // For non-enforcing devices, vndkVer is empty. Use "current" in that case, too. - vndkVer = "current" - } - if stub.stubsVersion() != "" { - vndkVer = stub.stubsVersion() - } - objs, versionScript := compileStubLibrary(ctx, flags, String(stub.Properties.Symbol_file), vndkVer, "--llndk") - if !Bool(stub.Properties.Unversioned) { - stub.versionScriptPath = android.OptionalPathForPath(versionScript) - } - return objs + return Objects{} } func (stub *llndkStubDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { - headers := addSuffix(stub.Properties.Export_llndk_headers, llndkHeadersSuffix) - deps.HeaderLibs = append(deps.HeaderLibs, headers...) - deps.ReexportHeaderLibHeaders = append(deps.ReexportHeaderLibHeaders, headers...) return deps } @@ -116,57 +105,9 @@ func (stub *llndkStubDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flag return stub.libraryDecorator.linkerFlags(ctx, flags) } -func (stub *llndkStubDecorator) processHeaders(ctx ModuleContext, srcHeaderDir string, outDir android.ModuleGenPath) android.Path { - srcDir := android.PathForModuleSrc(ctx, srcHeaderDir) - srcFiles := ctx.GlobFiles(filepath.Join(srcDir.String(), "**/*.h"), nil) - - var installPaths []android.WritablePath - for _, header := range srcFiles { - headerDir := filepath.Dir(header.String()) - relHeaderDir, err := filepath.Rel(srcDir.String(), headerDir) - if err != nil { - ctx.ModuleErrorf("filepath.Rel(%q, %q) failed: %s", - srcDir.String(), headerDir, err) - continue - } - - installPaths = append(installPaths, outDir.Join(ctx, relHeaderDir, header.Base())) - } - - return processHeadersWithVersioner(ctx, srcDir, outDir, srcFiles, installPaths) -} - func (stub *llndkStubDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path { - - impl := ctx.GetDirectDepWithTag(stub.implementationModuleName(ctx.ModuleName()), llndkImplDep) - if implApexModule, ok := impl.(android.ApexModule); ok { - stub.movedToApex = implApexModule.DirectlyInAnyApex() - } - - if len(stub.Properties.Export_preprocessed_headers) > 0 { - genHeaderOutDir := android.PathForModuleGen(ctx, "include") - - var timestampFiles android.Paths - for _, dir := range stub.Properties.Export_preprocessed_headers { - timestampFiles = append(timestampFiles, stub.processHeaders(ctx, dir, genHeaderOutDir)) - } - - if Bool(stub.Properties.Export_headers_as_system) { - stub.reexportSystemDirs(genHeaderOutDir) - } else { - stub.reexportDirs(genHeaderOutDir) - } - - stub.reexportDeps(timestampFiles...) - } - - if Bool(stub.Properties.Export_headers_as_system) { - stub.exportIncludesAsSystem(ctx) - stub.libraryDecorator.flagExporter.Properties.Export_include_dirs = []string{} - } - - return stub.libraryDecorator.link(ctx, flags, deps, objs) + return nil } func (stub *llndkStubDecorator) nativeCoverage() bool { @@ -181,20 +122,8 @@ func (stub *llndkStubDecorator) buildStubs() bool { return true } -func (stub *llndkStubDecorator) stubsVersions(ctx android.BaseMutatorContext) []string { - // Get the versions from the implementation module. - impls := ctx.GetDirectDepsWithTag(llndkImplDep) - if len(impls) > 1 { - panic(fmt.Errorf("Expected single implmenetation library, got %d", len(impls))) - } else if len(impls) == 1 { - return moduleLibraryInterface(impls[0]).allStubsVersions() - } - return nil -} - func NewLLndkStubLibrary() *Module { module, library := NewLibrary(android.DeviceSupported) - library.BuildOnlyShared() module.stl = nil module.sanitize = nil library.disableStripping() @@ -235,10 +164,6 @@ type llndkHeadersDecorator struct { *libraryDecorator } -func (headers *llndkHeadersDecorator) Name(name string) string { - return name + llndkHeadersSuffix -} - // llndk_headers contains a set of c/c++ llndk headers files which are imported // by other soongs cc modules. func llndkHeadersFactory() android.Module { diff --git a/cc/sabi.go b/cc/sabi.go index c357f8dab..4a1ba3cda 100644 --- a/cc/sabi.go +++ b/cc/sabi.go @@ -80,10 +80,10 @@ func classifySourceAbiDump(ctx android.BaseModuleContext) string { if m.IsNdk(ctx.Config()) { return "NDK" } - if m.isLlndkPublic(ctx.Config()) { + if m.isImplementationForLLNDKPublic() { return "LLNDK" } - if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate(ctx.Config()) { + if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate() { if m.isVndkSp() { if m.IsVndkExt() { return "VNDK-SP-ext" @@ -156,7 +156,7 @@ func shouldCreateSourceAbiDumpForLibrary(ctx android.BaseModuleContext) bool { } // Don't create ABI dump for stubs. - if m.isNDKStubLibrary() || m.IsStubs() { + if m.isNDKStubLibrary() || m.IsLlndk() || m.IsStubs() { return false } diff --git a/cc/sanitize.go b/cc/sanitize.go index 22ee25fdf..d7df5dc00 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -1002,9 +1002,6 @@ func sanitizerRuntimeMutator(mctx android.BottomUpMutatorContext) { if runtimeLibrary != "" && (toolchain.Bionic() || c.sanitize.Properties.UbsanRuntimeDep) { // UBSan is supported on non-bionic linux host builds as well - if isLlndkLibrary(runtimeLibrary, mctx.Config()) && !c.static() && c.UseVndk() { - runtimeLibrary = runtimeLibrary + llndkLibrarySuffix - } // Adding dependency to the runtime library. We are using *FarVariation* // because the runtime libraries themselves are not mutated by sanitizer diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go index f5f812146..419b7cf5d 100644 --- a/cc/snapshot_prebuilt.go +++ b/cc/snapshot_prebuilt.go @@ -805,7 +805,7 @@ func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) { } // .. and also filter out llndk library - if module.isLlndk(ctx.Config()) { + if module.IsLlndk() { return } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index bca76dc19..d2c29d631 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -210,6 +210,9 @@ func isSnapshotAware(m *Module, inProprietaryPath bool, apexInfo android.ApexInf return false } // skip llndk_library and llndk_headers which are backward compatible + if m.IsLlndk() { + return false + } if _, ok := m.linker.(*llndkStubDecorator); ok { return false } diff --git a/cc/vndk.go b/cc/vndk.go index 1529ac5a2..c1bce160b 100644 --- a/cc/vndk.go +++ b/cc/vndk.go @@ -156,9 +156,15 @@ func (vndk *vndkdep) vndkCheckLinkType(ctx android.BaseModuleContext, to *Module } if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() { // Check only shared libraries. - // Other (static and LL-NDK) libraries are allowed to link. + // Other (static) libraries are allowed to link. return } + + if to.IsLlndk() { + // LL-NDK libraries are allowed to link + return + } + if !to.UseVndk() { ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library", vndk.typeName(), to.Name()) @@ -250,22 +256,12 @@ func vndkSpLibraries(config android.Config) map[string]string { }).(map[string]string) } -func isLlndkLibrary(baseModuleName string, config android.Config) bool { - _, ok := llndkLibraries(config)[strings.TrimSuffix(baseModuleName, llndkLibrarySuffix)] - return ok -} - func llndkLibraries(config android.Config) map[string]string { return config.Once(llndkLibrariesKey, func() interface{} { return make(map[string]string) }).(map[string]string) } -func isVndkPrivateLibrary(baseModuleName string, config android.Config) bool { - _, ok := vndkPrivateLibraries(config)[baseModuleName] - return ok -} - func vndkPrivateLibraries(config android.Config) map[string]string { return config.Once(vndkPrivateLibrariesKey, func() interface{} { return make(map[string]string) @@ -301,12 +297,10 @@ func processLlndkLibrary(mctx android.BottomUpMutatorContext, m *Module) { defer vndkLibrariesLock.Unlock() llndkLibraries(mctx.Config())[name] = filename + m.VendorProperties.IsLLNDK = true if !Bool(lib.Properties.Vendor_available) { vndkPrivateLibraries(mctx.Config())[name] = filename - } - - if mctx.OtherModuleExists(name) { - mctx.AddFarVariationDependencies(m.Target().Variations(), llndkImplDep, name) + m.VendorProperties.IsLLNDKPrivate = true } } @@ -410,9 +404,31 @@ func VndkMutator(mctx android.BottomUpMutatorContext) { return } + // This is a temporary measure to copy the properties from an llndk_library into the cc_library + // that will actually build the stubs. It will be removed once the properties are moved into + // the cc_library in the Android.bp files. + mergeLLNDKToLib := func(llndk *Module, llndkProperties *llndkLibraryProperties, flagExporter *flagExporter) { + if llndkLib := moduleLibraryInterface(llndk); llndkLib != nil { + *llndkProperties = llndkLib.(*llndkStubDecorator).Properties + flagExporter.Properties = llndkLib.(*llndkStubDecorator).flagExporter.Properties + + m.VendorProperties.IsLLNDK = llndk.VendorProperties.IsLLNDK + m.VendorProperties.IsLLNDKPrivate = llndk.VendorProperties.IsLLNDKPrivate + } + } + lib, is_lib := m.linker.(*libraryDecorator) prebuilt_lib, is_prebuilt_lib := m.linker.(*prebuiltLibraryLinker) + if m.UseVndk() && is_lib && lib.hasLLNDKStubs() { + llndk := mctx.AddVariationDependencies(nil, llndkStubDepTag, String(lib.Properties.Llndk_stubs)) + mergeLLNDKToLib(llndk[0].(*Module), &lib.Properties.Llndk, &lib.flagExporter) + } + if m.UseVndk() && is_prebuilt_lib && prebuilt_lib.hasLLNDKStubs() { + llndk := mctx.AddVariationDependencies(nil, llndkStubDepTag, String(prebuilt_lib.Properties.Llndk_stubs)) + mergeLLNDKToLib(llndk[0].(*Module), &prebuilt_lib.Properties.Llndk, &prebuilt_lib.flagExporter) + } + if (is_lib && lib.buildShared()) || (is_prebuilt_lib && prebuilt_lib.buildShared()) { if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() { processVndkLibrary(mctx, m) @@ -819,13 +835,11 @@ func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) { // they been moved to an apex. movedToApexLlndkLibraries := make(map[string]bool) ctx.VisitAllModules(func(module android.Module) { - if m, ok := module.(*Module); ok { - if llndk, ok := m.linker.(*llndkStubDecorator); ok { - // Skip bionic libs, they are handled in different manner - name := llndk.implementationModuleName(m.BaseModuleName()) - if llndk.movedToApex && !isBionic(name) { - movedToApexLlndkLibraries[name] = true - } + if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() { + // Skip bionic libs, they are handled in different manner + name := library.implementationModuleName(module.(*Module).BaseModuleName()) + if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) { + movedToApexLlndkLibraries[name] = true } } }) diff --git a/rust/rust.go b/rust/rust.go index 21da5ae6f..2e78a147a 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -189,7 +189,15 @@ func (mod *Module) IsVndkExt() bool { return false } -func (c *Module) IsVndkPrivate(config android.Config) bool { +func (c *Module) IsVndkPrivate() bool { + return false +} + +func (c *Module) IsLlndk() bool { + return false +} + +func (c *Module) IsLlndkPublic() bool { return false }