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

Commit 492a8b1d authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "CcApiLibrary Variants for LLNDK"

parents 6a93fa42 ee58c930
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2540,6 +2540,8 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
			}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
		}
	}

	updateImportedLibraryDependency(ctx)
}

func BeginMutator(ctx android.BottomUpMutatorContext) {
+2 −1
Original line number Diff line number Diff line
@@ -2597,11 +2597,12 @@ func createVersionVariations(mctx android.BottomUpMutatorContext, versions []str
	m := mctx.Module().(*Module)
	isLLNDK := m.IsLlndk()
	isVendorPublicLibrary := m.IsVendorPublicLibrary()
	isImportedApiLibrary := m.isImportedApiLibrary()

	modules := mctx.CreateLocalVariations(variants...)
	for i, m := range modules {

		if variants[i] != "" || isLLNDK || isVendorPublicLibrary {
		if variants[i] != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary {
			// A stubs or LLNDK stubs variant.
			c := m.(*Module)
			c.sanitize = nil
+198 −19
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@
package cc

import (
	"strings"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/multitree"
)
@@ -26,6 +30,30 @@ func init() {
func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
	ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
	ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)
	ctx.RegisterModuleType("cc_api_variant", CcApiVariantFactory)
}

func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
	m, ok := ctx.Module().(*Module)
	if !ok {
		return
	}

	apiLibrary, ok := m.linker.(*apiLibraryDecorator)
	if !ok {
		return
	}

	if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
		// Add LLNDK dependencies
		for _, variant := range apiLibrary.properties.Variants {
			if variant == "llndk" {
				variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
				ctx.AddDependency(m, nil, variantName)
				break
			}
		}
	}
}

// 'cc_api_library' is a module type which is from the exported API surface
@@ -34,6 +62,7 @@ func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
// map file.
type apiLibraryProperties struct {
	Src      *string `android:"arch_variant"`
	Variants []string
}

type apiLibraryDecorator struct {
@@ -55,11 +84,9 @@ func CcApiLibraryFactory() android.Module {
	module.compiler = nil
	module.linker = apiLibraryDecorator
	module.installer = nil
	module.library = apiLibraryDecorator
	module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)

	// Mark module as stub, so APEX would not include this stub in the package.
	module.library.setBuildStubs(true)

	// Prevent default system libs (libc, libm, and libdl) from being linked
	if apiLibraryDecorator.baseLinker.Properties.System_shared_libs == nil {
		apiLibraryDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -91,13 +118,46 @@ func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
}

func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
	m, _ := ctx.Module().(*Module)

	var in android.Path

	if src := proptools.String(d.properties.Src); src != "" {
		in = android.PathForModuleSrc(ctx, src)
	}

	// LLNDK variant
	if m.UseVndk() && d.hasLLNDKStubs() {
		apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "llndk", "")

		var mod android.Module

		ctx.VisitDirectDeps(func(depMod android.Module) {
			if depMod.Name() == apiVariantModule {
				mod = depMod
			}
		})

		if mod != nil {
			variantMod, ok := mod.(*CcApiVariant)
			if ok {
				in = variantMod.Src()

				// Copy LLDNK properties to cc_api_library module
				d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
					d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
					variantMod.exportProperties.Export_headers...)

				// Export headers as system include dirs if specified. Mostly for libc
	if Bool(d.libraryDecorator.Properties.Llndk.Export_headers_as_system) {
				if proptools.Bool(variantMod.exportProperties.Export_headers_as_system) {
					d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs = append(
						d.libraryDecorator.flagExporter.Properties.Export_system_include_dirs,
						d.libraryDecorator.flagExporter.Properties.Export_include_dirs...)
					d.libraryDecorator.flagExporter.Properties.Export_include_dirs = nil
				}
			}
		}
	}

	// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
	d.exportIncludes(ctx)
@@ -107,13 +167,10 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
	d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
	d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)

	if d.properties.Src == nil {
		ctx.PropertyErrorf("src", "src is a required property")
	if in == nil {
		ctx.PropertyErrorf("src", "Unable to locate source property")
		return nil
	}
	// Skip the existence check of the stub prebuilt file.
	// The file is not guaranteed to exist during Soong analysis.
	// Build orchestrator will be responsible for creating a connected ninja graph.
	in := android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), *d.properties.Src)

	// Make the _compilation_ of rdeps have an order-only dep on cc_api_library.src (an .so file)
	// The .so file itself has an order-only dependency on the headers contributed by this library.
@@ -143,6 +200,43 @@ func (d *apiLibraryDecorator) availableFor(what string) bool {
	return true
}

func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []string {
	m, ok := ctx.Module().(*Module)

	if !ok {
		return nil
	}

	if d.hasLLNDKStubs() && m.UseVndk() {
		// LLNDK libraries only need a single stubs variant.
		return []string{android.FutureApiLevel.String()}
	}

	// TODO(b/244244438) Create more version information for NDK and APEX variations
	// NDK variants
	if m.MinSdkVersion() == "" {
		return nil
	}

	firstVersion, err := nativeApiLevelFromUser(ctx,
		m.MinSdkVersion())

	if err != nil {
		return nil
	}

	return ndkLibraryVersions(ctx, firstVersion)
}

func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
	for _, variant := range d.properties.Variants {
		if strings.Contains(variant, "llndk") {
			return true
		}
	}
	return false
}

// 'cc_api_headers' is similar with 'cc_api_library', but which replaces
// header libraries. The module will replace any dependencies to existing
// original header libraries.
@@ -165,9 +259,6 @@ func CcApiHeadersFactory() android.Module {
	module.linker = apiHeadersDecorator
	module.installer = nil

	// Mark module as stub, so APEX would not include this stub in the package.
	module.library.setBuildStubs(true)

	// Prevent default system libs (libc, libm, and libdl) from being linked
	if apiHeadersDecorator.baseLinker.Properties.System_shared_libs == nil {
		apiHeadersDecorator.baseLinker.Properties.System_shared_libs = []string{}
@@ -189,3 +280,91 @@ func (d *apiHeadersDecorator) availableFor(what string) bool {
	// Stub from API surface should be available for any APEX.
	return true
}

type ccApiexportProperties struct {
	Src     *string `android:"arch_variant"`
	Variant *string
	Version *string
}

type variantExporterProperties struct {
	// Header directory or library to export
	Export_headers []string

	// Export all headers as system include
	Export_headers_as_system *bool
}

type CcApiVariant struct {
	android.ModuleBase

	properties       ccApiexportProperties
	exportProperties variantExporterProperties

	src android.Path
}

var _ android.Module = (*CcApiVariant)(nil)
var _ android.ImageInterface = (*CcApiVariant)(nil)

func CcApiVariantFactory() android.Module {
	module := &CcApiVariant{}

	module.AddProperties(&module.properties)
	module.AddProperties(&module.exportProperties)

	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
	return module
}

func (v *CcApiVariant) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	// No need to build

	if proptools.String(v.properties.Src) == "" {
		ctx.PropertyErrorf("src", "src is a required property")
	}

	// Skip the existence check of the stub prebuilt file.
	// The file is not guaranteed to exist during Soong analysis.
	// Build orchestrator will be responsible for creating a connected ninja graph.
	v.src = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), proptools.String(v.properties.Src))
}

func (v *CcApiVariant) Name() string {
	version := proptools.String(v.properties.Version)
	return BuildApiVariantName(v.BaseModuleName(), *v.properties.Variant, version)
}

func (v *CcApiVariant) Src() android.Path {
	return v.src
}

func BuildApiVariantName(baseName string, variant string, version string) string {
	names := []string{baseName, variant}
	if version != "" {
		names = append(names, version)
	}

	return strings.Join(names[:], ".") + multitree.GetApiImportSuffix()
}

// Implement ImageInterface to generate image variants
func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext)               {}
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool          { return false }
func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool       { return false }
func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
func (v *CcApiVariant) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool  { return false }
func (v *CcApiVariant) RecoveryVariantNeeded(ctx android.BaseModuleContext) bool      { return false }
func (v *CcApiVariant) ExtraImageVariations(ctx android.BaseModuleContext) []string {
	var variations []string
	platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()

	if proptools.String(v.properties.Variant) == "llndk" {
		variations = append(variations, VendorVariationPrefix+platformVndkVersion)
		variations = append(variations, ProductVariationPrefix+platformVndkVersion)
	}

	return variations
}
func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string, module android.Module) {
}
+51 −0
Original line number Diff line number Diff line
@@ -284,3 +284,54 @@ func TestExportDirFromStubLibrary(t *testing.T) {
	// These header files are required for compiling the other API domain (vendor in this case)
	android.AssertStringListContains(t, "Vendor binary compilation should have an implicit dep on the stub .so file", vendorImplicits, "libfoo.so")
}

func TestApiLibraryWithLlndkVariant(t *testing.T) {
	bp := `
		cc_binary {
			name: "binfoo",
			vendor: true,
			srcs: ["binfoo.cc"],
			shared_libs: ["libbar"],
		}

		cc_api_library {
			name: "libbar",
			// TODO(b/244244438) Remove src property once all variants are implemented.
			src: "libbar.so",
			vendor_available: true,
			variants: [
				"llndk",
			],
		}

		cc_api_variant {
			name: "libbar",
			variant: "llndk",
			src: "libbar_llndk.so",
			export_headers: ["libbar_llndk_include"]
		}

		api_imports {
			name: "api_imports",
			shared_libs: [
				"libbar",
			],
			header_libs: [],
		}
	`

	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	libfoo := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Module()
	libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_vendor.29_arm64_armv8-a_shared").Module()
	libbarApiVariant := ctx.ModuleForTests("libbar.llndk.apiimport", "android_vendor.29_arm64_armv8-a").Module()

	android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
	android.AssertBoolEquals(t, "Stub library variant from API surface should be linked", true, hasDirectDependency(t, ctx, libbarApiImport, libbarApiVariant))

	libFooLibFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("ld").Args["libFlags"]
	android.AssertStringDoesContain(t, "Vendor binary should be linked with LLNDK variant source", libFooLibFlags, "libbar_llndk.so")

	libFooCFlags := ctx.ModuleForTests("binfoo", "android_vendor.29_arm64_armv8-a").Rule("cc").Args["cFlags"]
	android.AssertStringDoesContain(t, "Vendor binary should include headers from the LLNDK variant source", libFooCFlags, "-Ilibbar_llndk_include")
}
+2 −0
Original line number Diff line number Diff line
@@ -78,5 +78,7 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
		}
	case *snapshotModule:
		ctx.CreateVariations("")
	case *CcApiVariant:
		ctx.CreateVariations("")
	}
}