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

Commit 51279d3a authored by Kiyoung Kim's avatar Kiyoung Kim
Browse files

Define cc_api_headers module

Define cc_api_headers module to import from API surfaces and replace
existing header definition if needed.

Tested with :
cc_api_headers {
  name: "libc_headers",
  export_system_include_dirs: [
    "include",
  ],
  min_sdk_version: "1",
  sdk_version: "1",
  vendor_available: true,
  native_bridge_supported: true,
  ...
}

Bug: 236087698
Test: ALLOW_MISSING_DEPENDENCIES=true m -j vendorimage succeeded
Change-Id: I2c3294fe19a272453a168d8c7beeee9859bd4583
parent e66fe044
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -644,6 +644,16 @@ func (a *apiLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *an
	})
}

func (a *apiHeadersDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
	entries.Class = "HEADER_LIBRARIES"
	entries.SubName += multitree.GetApiImportSuffix()

	entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
		a.libraryDecorator.androidMkWriteExportedFlags(entries)
		entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
	})
}

func androidMkWriteAllowUndefinedSymbols(linker *baseLinker, entries *android.AndroidMkEntries) {
	allow := linker.Properties.Allow_undefined_symbols
	if allow != nil {
+15 −11
Original line number Diff line number Diff line
@@ -2302,9 +2302,14 @@ func updateDepsWithApiImports(deps Deps, apiImports multitree.ApiImportInfo) Dep
		deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	for idx, lib := range deps.HeaderLibs {
		deps.HeaderLibs[idx] = GetReplaceModuleName(lib, apiImports.HeaderLibs)
	for idx, lib := range deps.SystemSharedLibs {
		deps.SystemSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	for idx, lib := range deps.ReexportSharedLibHeaders {
		deps.ReexportSharedLibHeaders[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
	}

	return deps
}

@@ -2348,12 +2353,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
			depTag.reexportFlags = true
		}

		// Check header lib replacement from API surface first, and then check again with VSDK
		lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
		lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)

		if c.isNDKStubLibrary() {
			// ndk_headers do not have any variations
			actx.AddFarVariationDependencies([]blueprint.Variation{}, depTag, lib)
		} else if c.IsStubs() {
		} else if c.IsStubs() && !c.isImportedApiLibrary() {
			actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
				depTag, lib)
		} else {
@@ -3258,11 +3265,6 @@ func MakeLibName(ctx android.ModuleContext, c LinkableInterface, ccDep LinkableI

			return baseName + snapshotPrebuilt.SnapshotAndroidMkSuffix()
		}

		// Remove API import suffix if exists
		if _, ok := ccDepModule.linker.(*apiLibraryDecorator); ok {
			libName = strings.TrimSuffix(libName, multitree.GetApiImportSuffix())
		}
	}

	if ctx.DeviceConfig().VndkUseCoreVariant() && ccDep.IsVndk() && !ccDep.MustUseVendorVariant() &&
@@ -3598,9 +3600,6 @@ func (c *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
	if _, ok := c.linker.(prebuiltLinkerInterface); ok {
		return nil
	}
	if _, ok := c.linker.(*apiLibraryDecorator); ok {
		return nil
	}

	minSdkVersion := c.MinSdkVersion()
	if minSdkVersion == "apex_inherit" {
@@ -3781,6 +3780,11 @@ func (c *Module) IsSdkVariant() bool {
	return c.Properties.IsSdkVariant
}

func (c *Module) isImportedApiLibrary() bool {
	_, ok := c.linker.(*apiLibraryDecorator)
	return ok
}

func kytheExtractAllFactory() android.Singleton {
	return &kytheExtractAllSingleton{}
}
+56 −5
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package cc
import (
	"android/soong/android"
	"android/soong/multitree"
	"strings"
)

func init() {
@@ -25,8 +24,10 @@ func init() {
}

func RegisterLibraryStubBuildComponents(ctx android.RegistrationContext) {
	// cc_api_stub_library shares a lot of ndk_library, and this will be refactored later
	ctx.RegisterModuleType("cc_api_library", CcApiLibraryFactory)
	ctx.RegisterModuleType("cc_api_headers", CcApiHeadersFactory)

	// cc_api_stub_library shares a lot of ndk_library, and this will be refactored later
	ctx.RegisterModuleType("cc_api_stub_library", CcApiStubLibraryFactory)
	ctx.RegisterModuleType("cc_api_contribution", CcApiContributionFactory)
}
@@ -81,6 +82,14 @@ func (d *apiLibraryDecorator) Name(basename string) string {
}

func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
	// Export headers as system include dirs if specified. Mostly for libc
	if Bool(d.libraryDecorator.Properties.Llndk.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.libraryDecorator.flagExporter.exportIncludes(ctx)
	d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
@@ -114,9 +123,51 @@ func (d *apiLibraryDecorator) availableFor(what string) bool {
	return true
}

func (d *apiLibraryDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
	d.libraryDecorator.libName = strings.TrimSuffix(ctx.ModuleName(), multitree.GetApiImportSuffix())
	return d.libraryDecorator.linkerFlags(ctx, flags)
// '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.
type apiHeadersDecorator struct {
	*libraryDecorator
}

func CcApiHeadersFactory() android.Module {
	module, decorator := NewLibrary(android.DeviceSupported)
	apiHeadersDecorator := &apiHeadersDecorator{
		libraryDecorator: decorator,
	}
	apiHeadersDecorator.HeaderOnly()

	module.stl = nil
	module.sanitize = nil
	decorator.disableStripping()

	module.compiler = nil
	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{}
	}

	apiHeadersDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
	apiHeadersDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)

	module.Init()

	return module
}

func (d *apiHeadersDecorator) Name(basename string) string {
	return basename + multitree.GetApiImportSuffix()
}

func (d *apiHeadersDecorator) availableFor(what string) bool {
	// Stub from API surface should be available for any APEX.
	return true
}

func CcApiStubLibraryFactory() android.Module {
+109 −0
Original line number Diff line number Diff line
@@ -216,3 +216,112 @@ func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
	android.AssertBoolEquals(t, "original library should be linked", true, hasDirectDependency(t, ctx, libfoo, libbar))
	android.AssertBoolEquals(t, "Stub library from API surface should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
}

func TestApiHeaderReplacesExistingModule(t *testing.T) {
	bp := `
		cc_library {
			name: "libfoo",
			header_libs: ["libfoo_headers"],
		}

		cc_api_library {
			name: "libfoo",
			header_libs: ["libfoo_headers"],
			src: "libfoo.so",
		}

		cc_library_headers {
			name: "libfoo_headers",
		}

		cc_api_headers {
			name: "libfoo_headers",
		}

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

	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
	libfooApiImport := ctx.ModuleForTests("libfoo.apiimport", "android_arm64_armv8-a_shared").Module()
	libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
	libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()

	android.AssertBoolEquals(t, "original header should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeader))
	android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
	android.AssertBoolEquals(t, "original header should not be used for library imported from API surface", false, hasDirectDependency(t, ctx, libfooApiImport, libfooHeader))
	android.AssertBoolEquals(t, "Header from API surface should be used for library imported from API surface", true, hasDirectDependency(t, ctx, libfooApiImport, libfooHeaderApiImport))
}

func TestApiHeadersDoNotRequireOriginalModule(t *testing.T) {
	bp := `
	cc_library {
		name: "libfoo",
		header_libs: ["libfoo_headers"],
	}

	cc_api_headers {
		name: "libfoo_headers",
	}

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

	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
	libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()

	android.AssertBoolEquals(t, "Header from API surface should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
}

func TestApiHeadersShouldNotReplaceWithoutApiImport(t *testing.T) {
	bp := `
		cc_library {
			name: "libfoo",
			header_libs: ["libfoo_headers"],
		}

		cc_library_headers {
			name: "libfoo_headers",
		}

		cc_api_headers {
			name: "libfoo_headers",
		}

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

	ctx := prepareForCcTest.RunTestWithBp(t, bp)

	libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
	libfooHeader := ctx.ModuleForTests("libfoo_headers", "android_arm64_armv8-a").Module()
	libfooHeaderApiImport := ctx.ModuleForTests("libfoo_headers.apiimport", "android_arm64_armv8-a").Module()

	android.AssertBoolEquals(t, "original header should be used for original library", true, hasDirectDependency(t, ctx, libfoo, libfooHeader))
	android.AssertBoolEquals(t, "Header from API surface should not be used for original library", false, hasDirectDependency(t, ctx, libfoo, libfooHeaderApiImport))
}