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

Commit 8972e4d6 authored by Kiyoung Kim's avatar Kiyoung Kim Committed by Gerrit Code Review
Browse files

Merge "Implement API surface import with APEX stub"

parents b547b65e 76b06f39
Loading
Loading
Loading
Loading
+163 −18
Original line number Diff line number Diff line
@@ -9788,30 +9788,85 @@ func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
		apex {
			name: "myapex",
			key: "myapex.key",
			native_shared_libs: ["libfoo"],
			native_shared_libs: ["libbaz"],
			binaries: ["binfoo"],
			min_sdk_version: "29",
		}
		apex_key {
			name: "myapex.key",
		}
		cc_binary {
			name: "binfoo",
			shared_libs: ["libbar", "libbaz", "libqux",],
			apex_available: ["myapex"],
			min_sdk_version: "29",
			recovery_available: false,
		}
		cc_library {
			name: "libfoo",
			shared_libs: ["libc"],
			name: "libbar",
			srcs: ["libbar.cc"],
			stubs: {
				symbol_file: "libbar.map.txt",
				versions: [
					"29",
				],
			},
		}
		cc_library {
			name: "libbaz",
			srcs: ["libbaz.cc"],
			apex_available: ["myapex"],
			min_sdk_version: "29",
			stubs: {
				symbol_file: "libbaz.map.txt",
				versions: [
					"29",
				],
			},
		}
		cc_api_library {
			name: "libc",
			src: "libc.so",
			name: "libbar",
			src: "libbar_stub.so",
			min_sdk_version: "29",
			recovery_available: true,
			variants: ["apex.29"],
		}
		cc_api_variant {
			name: "libbar",
			variant: "apex",
			version: "29",
			src: "libbar_apex_29.so",
		}
		cc_api_library {
			name: "libbaz",
			src: "libbaz_stub.so",
			min_sdk_version: "29",
			variants: ["apex.29"],
		}
		cc_api_variant {
			name: "libbaz",
			variant: "apex",
			version: "29",
			src: "libbaz_apex_29.so",
		}
		cc_api_library {
			name: "libqux",
			src: "libqux_stub.so",
			min_sdk_version: "29",
			variants: ["apex.29"],
		}
		cc_api_variant {
			name: "libqux",
			variant: "apex",
			version: "29",
			src: "libqux_apex_29.so",
		}
		api_imports {
			name: "api_imports",
			shared_libs: [
				"libc",
			apex_shared_libs: [
				"libbar",
				"libbaz",
				"libqux",
			],
			header_libs: [],
		}
		`
	result := testApex(t, bp)
@@ -9827,17 +9882,107 @@ func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
		return found
	}

	libfooApexVariant := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex29").Module()
	libcApexVariant := result.ModuleForTests("libc.apiimport", "android_arm64_armv8-a_shared_apex29").Module()
	// Library defines stubs and cc_api_library should be used with cc_api_library
	binfooApexVariant := result.ModuleForTests("binfoo", "android_arm64_armv8-a_apex29").Module()
	libbarCoreVariant := result.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
	libbarApiImportCoreVariant := result.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()

	android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(binfooApexVariant, libbarApiImportCoreVariant))
	android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbarCoreVariant))

	binFooCFlags := result.ModuleForTests("binfoo", "android_arm64_armv8-a_apex29").Rule("ld").Args["libFlags"]
	android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbar.apex.29.apiimport.so")
	android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbar.apiimport.so")
	android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbar.so")

	// Library defined in the same APEX should be linked with original definition instead of cc_api_library
	libbazApexVariant := result.ModuleForTests("libbaz", "android_arm64_armv8-a_shared_apex29").Module()
	libbazApiImportCoreVariant := result.ModuleForTests("libbaz.apiimport", "android_arm64_armv8-a_shared").Module()
	android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries even from same APEX", true, hasDep(binfooApexVariant, libbazApiImportCoreVariant))
	android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbazApexVariant))

	android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbaz.so")
	android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbaz.apiimport.so")
	android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbaz.apex.29.apiimport.so")

	// cc_api_library defined without original library should be linked with cc_api_library
	libquxApiImportApexVariant := result.ModuleForTests("libqux.apiimport", "android_arm64_armv8-a_shared").Module()
	android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries even original library definition does not exist", true, hasDep(binfooApexVariant, libquxApiImportApexVariant))
	android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libqux.apex.29.apiimport.so")
}

func TestPlatformBinaryBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
	bp := `
		apex {
			name: "myapex",
			key: "myapex.key",
			native_shared_libs: ["libbar"],
			min_sdk_version: "29",
		}
		apex_key {
			name: "myapex.key",
		}
		cc_binary {
			name: "binfoo",
			shared_libs: ["libbar"],
			recovery_available: false,
		}
		cc_library {
			name: "libbar",
			srcs: ["libbar.cc"],
			apex_available: ["myapex"],
			min_sdk_version: "29",
			stubs: {
				symbol_file: "libbar.map.txt",
				versions: [
					"29",
				],
			},
		}
		cc_api_library {
			name: "libbar",
			src: "libbar_stub.so",
			variants: ["apex.29"],
		}
		cc_api_variant {
			name: "libbar",
			variant: "apex",
			version: "29",
			src: "libbar_apex_29.so",
		}
		api_imports {
			name: "api_imports",
			apex_shared_libs: [
				"libbar",
			],
		}
		`

	result := testApex(t, bp)

	hasDep := func(m android.Module, wantDep android.Module) bool {
		t.Helper()
		var found bool
		result.VisitDirectDeps(m, func(dep blueprint.Module) {
			if dep == wantDep {
				found = true
			}
		})
		return found
	}

	// Library defines stubs and cc_api_library should be used with cc_api_library
	binfooApexVariant := result.ModuleForTests("binfoo", "android_arm64_armv8-a").Module()
	libbarCoreVariant := result.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
	libbarApiImportCoreVariant := result.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()

	android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(libfooApexVariant, libcApexVariant))
	android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(binfooApexVariant, libbarApiImportCoreVariant))
	android.AssertBoolEquals(t, "apex variant should link against original library if exists", true, hasDep(binfooApexVariant, libbarCoreVariant))

	// libfoo core variant should be buildable in the same inner tree since
	// certain mcombo files might build system and apexes in the same inner tree
	// libfoo core variant should link against source libc
	libfooCoreVariant := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
	libcCoreVariant := result.ModuleForTests("libc.apiimport", "android_arm64_armv8-a_shared").Module()
	android.AssertBoolEquals(t, "core variant should link against source libc", true, hasDep(libfooCoreVariant, libcCoreVariant))
	binFooCFlags := result.ModuleForTests("binfoo", "android_arm64_armv8-a").Rule("ld").Args["libFlags"]
	android.AssertStringDoesContain(t, "binfoo should link against APEX variant", binFooCFlags, "libbar.apex.29.apiimport.so")
	android.AssertStringDoesNotContain(t, "binfoo should not link against cc_api_library itself", binFooCFlags, "libbar.apiimport.so")
	android.AssertStringDoesNotContain(t, "binfoo should not link against original definition", binFooCFlags, "libbar.so")
}

func TestTrimmedApex(t *testing.T) {
+160 −63
Original line number Diff line number Diff line
@@ -2416,6 +2416,27 @@ func rewriteLibsForApiImports(c LinkableInterface, libs []string, replaceList ma
	return nonVariantLibs, variantLibs
}

func (c *Module) shouldUseApiSurface() bool {
	if c.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
		if GetImageVariantType(c) == vendorImageVariant || GetImageVariantType(c) == productImageVariant {
			// LLNDK Variant
			return true
		}

		if c.Properties.IsSdkVariant {
			// NDK Variant
			return true
		}

		if c.isImportedApiLibrary() {
			// API Library should depend on API headers
			return true
		}
	}

	return false
}

func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
	if !c.Enabled() {
		return
@@ -2435,7 +2456,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
	apiNdkLibs := []string{}
	apiLateNdkLibs := []string{}

	if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
	if c.shouldUseApiSurface() {
		deps.SharedLibs, apiNdkLibs = rewriteLibsForApiImports(c, deps.SharedLibs, apiImportInfo.SharedLibs, ctx.Config())
		deps.LateSharedLibs, apiLateNdkLibs = rewriteLibsForApiImports(c, deps.LateSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
		deps.SystemSharedLibs, _ = rewriteLibsForApiImports(c, deps.SystemSharedLibs, apiImportInfo.SharedLibs, ctx.Config())
@@ -2466,7 +2487,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
		}

		// Check header lib replacement from API surface first, and then check again with VSDK
		if ctx.Os() == android.Android && c.Target().NativeBridge != android.NativeBridgeEnabled {
		if c.shouldUseApiSurface() {
			lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
		}
		lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
@@ -2550,14 +2571,24 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
		}

		name, version := StubsLibNameAndVersion(lib)
		if apiLibraryName, ok := apiImportInfo.SharedLibs[name]; ok && !ctx.OtherModuleExists(name) {
			name = apiLibraryName
		}
		sharedLibNames = append(sharedLibNames, name)

		variations := []blueprint.Variation{
			{Mutator: "link", Variation: "shared"},
		}

		if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
			AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false)
		}

		if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
			AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, apiLibraryName, version, false)
		}
	}

	for _, lib := range deps.LateStaticLibs {
		depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
		actx.AddVariationDependencies([]blueprint.Variation{
@@ -2898,10 +2929,58 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
	c.apexSdkVersion = findApexSdkVersion(ctx, apexInfo)

	skipModuleList := map[string]bool{}

	var apiImportInfo multitree.ApiImportInfo
	hasApiImportInfo := false

	ctx.VisitDirectDeps(func(dep android.Module) {
		if dep.Name() == "api_imports" {
			apiImportInfo = ctx.OtherModuleProvider(dep, multitree.ApiImportsProvider).(multitree.ApiImportInfo)
			hasApiImportInfo = true
		}
	})

	if hasApiImportInfo {
		targetStubModuleList := map[string]string{}
		targetOrigModuleList := map[string]string{}

		// Search for dependency which both original module and API imported library with APEX stub exists
		ctx.VisitDirectDeps(func(dep android.Module) {
			depName := ctx.OtherModuleName(dep)
			if apiLibrary, ok := apiImportInfo.ApexSharedLibs[depName]; ok {
				targetStubModuleList[apiLibrary] = depName
			}
		})
		ctx.VisitDirectDeps(func(dep android.Module) {
			depName := ctx.OtherModuleName(dep)
			if origLibrary, ok := targetStubModuleList[depName]; ok {
				targetOrigModuleList[origLibrary] = depName
			}
		})

		// Decide which library should be used between original and API imported library
		ctx.VisitDirectDeps(func(dep android.Module) {
			depName := ctx.OtherModuleName(dep)
			if apiLibrary, ok := targetOrigModuleList[depName]; ok {
				if shouldUseStubForApex(ctx, dep) {
					skipModuleList[depName] = true
				} else {
					skipModuleList[apiLibrary] = true
				}
			}
		})
	}

	ctx.VisitDirectDeps(func(dep android.Module) {
		depName := ctx.OtherModuleName(dep)
		depTag := ctx.OtherModuleDependencyTag(dep)

		if _, ok := skipModuleList[depName]; ok {
			// skip this module because original module or API imported module matching with this should be used instead.
			return
		}

		if depTag == android.DarwinUniversalVariantTag {
			depPaths.DarwinSecondArchOutput = dep.(*Module).OutputFile()
			return
@@ -3237,21 +3316,8 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
	return depPaths
}

// ChooseStubOrImpl determines whether a given dependency should be redirected to the stub variant
// of the dependency or not, and returns the SharedLibraryInfo and FlagExporterInfo for the right
// dependency. The stub variant is selected when the dependency crosses a boundary where each side
// has different level of updatability. For example, if a library foo in an APEX depends on a
// library bar which provides stable interface and exists in the platform, foo uses the stub variant
// of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
// same APEX as foo, the non-stub variant of bar is used.
func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
func shouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
	depName := ctx.OtherModuleName(dep)
	depTag := ctx.OtherModuleDependencyTag(dep)
	libDepTag, ok := depTag.(libraryDependencyTag)
	if !ok || !libDepTag.shared() {
		panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
	}

	thisModule, ok := ctx.Module().(android.ApexModule)
	if !ok {
		panic(fmt.Errorf("Not an APEX module: %q", ctx.ModuleName()))
@@ -3266,12 +3332,8 @@ func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibr
		bootstrap = linkable.Bootstrap()
	}

	sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
	depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
	sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryStubsProvider).(SharedLibraryStubsInfo)
	apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)

	if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
	useStubs := false

	if lib := moduleLibraryInterface(dep); lib.buildStubs() && useVndk { // LLNDK
@@ -3286,7 +3348,20 @@ func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibr
		// platform APIs, use stubs only when it is from an APEX (and not from
		// platform) However, for host, ramdisk, vendor_ramdisk, recovery or
		// bootstrap modules, always link to non-stub variant
			useStubs = dep.(android.ApexModule).NotInPlatform() && !bootstrap
		isNotInPlatform := dep.(android.ApexModule).NotInPlatform()

		isApexImportedApiLibrary := false

		if cc, ok := dep.(*Module); ok {
			if apiLibrary, ok := cc.linker.(*apiLibraryDecorator); ok {
				if apiLibrary.hasApexStubs() {
					isApexImportedApiLibrary = true
				}
			}
		}

		useStubs = (isNotInPlatform || isApexImportedApiLibrary) && !bootstrap

		if useStubs {
			// Another exception: if this module is a test for an APEX, then
			// it is linked with the non-stub variant of a module in the APEX
@@ -3310,7 +3385,7 @@ func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibr
			// only partially overlapping apex_available. For that test_for
			// modules would need to be split into APEX variants and resolved
			// separately for each APEX they have access to.
				if android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
			if !isApexImportedApiLibrary && android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
				useStubs = false
			}
		}
@@ -3320,8 +3395,30 @@ func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibr
		useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
	}

	return useStubs
}

// ChooseStubOrImpl determines whether a given dependency should be redirected to the stub variant
// of the dependency or not, and returns the SharedLibraryInfo and FlagExporterInfo for the right
// dependency. The stub variant is selected when the dependency crosses a boundary where each side
// has different level of updatability. For example, if a library foo in an APEX depends on a
// library bar which provides stable interface and exists in the platform, foo uses the stub variant
// of bar. If bar doesn't provide a stable interface (i.e. buildStubs() == false) or is in the
// same APEX as foo, the non-stub variant of bar is used.
func ChooseStubOrImpl(ctx android.ModuleContext, dep android.Module) (SharedLibraryInfo, FlagExporterInfo) {
	depTag := ctx.OtherModuleDependencyTag(dep)
	libDepTag, ok := depTag.(libraryDependencyTag)
	if !ok || !libDepTag.shared() {
		panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
	}

	sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
	depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
	sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryStubsProvider).(SharedLibraryStubsInfo)

	if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
		// when to use (unspecified) stubs, use the latest one.
		if useStubs {
		if shouldUseStubForApex(ctx, dep) {
			stubs := sharedLibraryStubsInfo.SharedStubLibraries
			toUse := stubs[len(stubs)-1]
			sharedLibraryInfo = toUse.SharedLibraryInfo
+98 −43
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import (

var (
	ndkVariantRegex  = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
	stubVariantRegex = regexp.MustCompile("apex\\.([a-zA-Z0-9]+)")
)

func init() {
@@ -60,6 +61,12 @@ func updateImportedLibraryDependency(ctx android.BottomUpMutatorContext) {
			variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
			ctx.AddDependency(m, nil, variantName)
		}
	} else if m.IsStubs() {
		targetVariant := "apex." + m.StubsVersion()
		if inList(targetVariant, apiLibrary.properties.Variants) {
			variantName := BuildApiVariantName(m.BaseModuleName(), targetVariant, "")
			ctx.AddDependency(m, nil, variantName)
		}
	}
}

@@ -153,15 +160,15 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
		in = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), src)
	}

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

	load_cc_variant := func(apiVariantModule string) {
		var mod android.Module

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

@@ -184,37 +191,17 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
				}
			}
		}
	} else if m.IsSdkVariant() {
		// NDK Variant
		apiVariantModule := BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion())

		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 NDK properties to cc_api_library module
				d.libraryDecorator.flagExporter.Properties.Export_include_dirs = append(
					d.libraryDecorator.flagExporter.Properties.Export_include_dirs,
					variantMod.exportProperties.Export_include_dirs...)

				// Export headers as system include dirs if specified. Mostly for libc
				if 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
				}
			}
		}
	if m.UseVndk() && d.hasLLNDKStubs() {
		// LLNDK variant
		load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "llndk", ""))
	} else if m.IsSdkVariant() {
		// NDK Variant
		load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "ndk", m.StubsVersion()))
	} else if m.IsStubs() {
		// APEX Variant
		load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "apex", m.StubsVersion()))
	}

	// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
@@ -237,20 +224,58 @@ func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps
	d.libraryDecorator.flagExporter.setProvider(ctx)

	d.unstrippedOutputFile = in
	libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
	libName += flags.Toolchain.ShlibSuffix()

	tocFile := android.PathForModuleOut(ctx, libName+".toc")
	d.tocFile = android.OptionalPathForPath(tocFile)
	TransformSharedObjectToToc(ctx, in, tocFile)

	outputFile := android.PathForModuleOut(ctx, libName)

	// TODO(b/270485584) This copies with a new name, just to avoid conflict with prebuilts.
	// We can just use original input if there is any way to avoid name conflict without copy.
	ctx.Build(pctx, android.BuildParams{
		Rule:        android.Cp,
		Description: "API surface imported library",
		Input:       in,
		Output:      outputFile,
		Args: map[string]string{
			"cpFlags": "-L",
		},
	})

	ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
		SharedLibrary: in,
		SharedLibrary: outputFile,
		Target:        ctx.Target(),

		TableOfContents: d.tocFile,
	})

	return in
	d.shareStubs(ctx)

	return outputFile
}

// Share additional information about stub libraries with provider
func (d *apiLibraryDecorator) shareStubs(ctx ModuleContext) {
	stubs := ctx.GetDirectDepsWithTag(stubImplDepTag)
	if len(stubs) > 0 {
		var stubsInfo []SharedStubLibrary
		for _, stub := range stubs {
			stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
			flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
			stubsInfo = append(stubsInfo, SharedStubLibrary{
				Version:           moduleLibraryInterface(stub).stubsVersion(),
				SharedLibraryInfo: stubInfo,
				FlagExporterInfo:  flagInfo,
			})
		}
		ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
			SharedStubLibraries: stubsInfo,

			IsLLNDK: ctx.IsLlndk(),
		})
	}
}

func (d *apiLibraryDecorator) availableFor(what string) bool {
@@ -258,6 +283,19 @@ func (d *apiLibraryDecorator) availableFor(what string) bool {
	return true
}

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

func (d *apiLibraryDecorator) hasStubsVariants() bool {
	return d.hasApexStubs()
}

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

@@ -265,14 +303,8 @@ func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []st
		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.IsSdkVariant() {
		// TODO(b/249193999) Do not check if module has NDK stubs once all NDK cc_api_library contains ndk variant of cc_api_variant.
		if d.hasNDKStubs() {
@@ -280,6 +312,17 @@ func (d *apiLibraryDecorator) stubsVersions(ctx android.BaseMutatorContext) []st
		}
	}

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

	stubsVersions := d.getStubVersions()

	if len(stubsVersions) != 0 {
		return stubsVersions
	}

	if m.MinSdkVersion() == "" {
		return nil
	}
@@ -319,6 +362,18 @@ func (d *apiLibraryDecorator) getNdkVersions() []string {
	return ndkVersions
}

func (d *apiLibraryDecorator) getStubVersions() []string {
	stubVersions := []string{}

	for _, variant := range d.properties.Variants {
		if match := stubVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
			stubVersions = append(stubVersions, match[1])
		}
	}

	return stubVersions
}

// '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.
@@ -433,7 +488,7 @@ func BuildApiVariantName(baseName string, variant string, version string) string
// Implement ImageInterface to generate image variants
func (v *CcApiVariant) ImageMutatorBegin(ctx android.BaseModuleContext) {}
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
	return String(v.properties.Variant) == "ndk"
	return inList(String(v.properties.Variant), []string{"ndk", "apex"})
}
func (v *CcApiVariant) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool       { return false }
func (v *CcApiVariant) VendorRamdiskVariantNeeded(ctx android.BaseModuleContext) bool { return false }
+72 −122

File changed.

Preview size limit exceeded, changes collapsed.

+14 −9
Original line number Diff line number Diff line
@@ -62,21 +62,26 @@ func sdkMutator(ctx android.BottomUpMutatorContext) {
		} else if isCcModule && ccModule.isImportedApiLibrary() {
			apiLibrary, _ := ccModule.linker.(*apiLibraryDecorator)
			if apiLibrary.hasNDKStubs() && ccModule.canUseSdk() {
				variations := []string{"sdk"}
				if apiLibrary.hasApexStubs() {
					variations = append(variations, "")
				}
				// Handle cc_api_library module with NDK stubs and variants only which can use SDK
				modules := ctx.CreateVariations("", "sdk")

				modules := ctx.CreateVariations(variations...)
				// Mark the SDK variant.
				modules[1].(*Module).Properties.IsSdkVariant = true
				// SDK variant is not supposed to be installed
				modules[1].(*Module).Properties.PreventInstall = true

				modules[0].(*Module).Properties.IsSdkVariant = true
				if ctx.Config().UnbundledBuildApps() {
					if apiLibrary.hasApexStubs() {
						// For an unbundled apps build, hide the platform variant from Make.
					modules[0].(*Module).Properties.HideFromMake = true
						modules[1].(*Module).Properties.HideFromMake = true
						modules[1].(*Module).Properties.PreventInstall = true
					}
				} else {
					// For a platform build, mark the SDK variant so that it gets a ".sdk" suffix when
					// exposed to Make.
					modules[1].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
					modules[0].(*Module).Properties.SdkAndPlatformVariantVisibleToMake = true
					// SDK variant is not supposed to be installed
					modules[0].(*Module).Properties.PreventInstall = true
				}
			} else {
				ccModule.Properties.Sdk_version = nil
Loading