Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 127bb8b9 authored by Colin Cross's avatar Colin Cross
Browse files

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
parent adc81a07
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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{})
+2 −2
Original line number Diff line number Diff line
@@ -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"]
+4 −13
Original line number Diff line number Diff line
@@ -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) {
+56 −38
Original line number Diff line number Diff line
@@ -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() bool {
	return ctx.mod.IsLlndkPublic()
}

func (ctx *moduleContextImpl) isLlndkPublic(config android.Config) bool {
	return ctx.mod.isLlndkPublic(config)
func (ctx *moduleContextImpl) isImplementationForLLNDKPublic() bool {
	return ctx.mod.isImplementationForLLNDKPublic()
}

func (ctx *moduleContextImpl) isVndkPrivate(config android.Config) bool {
	return ctx.mod.IsVndkPrivate(config)
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
	}
+48 −4
Original line number Diff line number Diff line
@@ -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"])
}

Loading