Don't rewrite LLNDK dependencies with .llndk suffix

Rewriting LLNDK dependencies with .llndk suffix requries referencing
a global data structure to determine if a given library is an LLNDK
library and therefore needs the .llndk suffix.  References to
global data structures from mutators must be removed to support
incremental Soong analysis.  Instead, move the LLNDK stubs rules
into the vendor variant of the implementing cc_library so that
the original name can be used.

As an incremental step, the llndk_library modules are left in
place, and the properties are copied into the cc_library via
the dependency specified by the llndk_stub property.  A followup
will move the LLNDK properties directly into the cc_library and
delete the llndk_library modules.

The global list of LLNDK libraries is kept for now as it is used
to generate the vndk.libraries.txt file.

Bug: 170784825
Test: m checkbuild
Test: compare Soong outputs
Test: all Soong tests
Change-Id: I2a942b21c162541a49e27b2e5833c9aebccff1d0
This commit is contained in:
Colin Cross 2020-12-16 16:46:01 -08:00
parent adc81a0783
commit 127bb8b9f6
15 changed files with 344 additions and 200 deletions

View File

@ -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{})

View File

@ -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"]

View File

@ -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) {

View File

@ -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
}

View File

@ -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"])
}

View File

@ -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

View File

@ -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 <file> 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 {
@ -1022,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,
@ -1076,7 +1119,7 @@ func (library *libraryDecorator) linkShared(ctx ModuleContext,
ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
IsLLNDK: ctx.isLlndk(ctx.Config()),
IsLLNDK: ctx.IsLlndk(),
})
}
@ -1105,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)
@ -1158,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).
@ -1251,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)
@ -1339,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()
}
@ -1416,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
}
@ -1428,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
}
@ -1592,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.
@ -1603,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 {
@ -1627,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...)
@ -1641,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...)
@ -1680,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("")
@ -1742,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
}
@ -1763,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())
}
})
}
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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
}

View File

@ -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

View File

@ -805,7 +805,7 @@ func VendorSnapshotSourceMutator(ctx android.BottomUpMutatorContext) {
}
// .. and also filter out llndk library
if module.isLlndk(ctx.Config()) {
if module.IsLlndk() {
return
}

View File

@ -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
}

View File

@ -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
}
}
})

View File

@ -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
}