Introduce cc_api_library
Introduce cc_api_library, which reflects imported API from other inner-tree. This cc_api_library module type will later refer from the other ninja module which generates stub library from the interface description. Tested environment : * original libc definition has been removed temporarily, to ensure that imported api stub library is being used from build * Added new definition of libc as below cc_api_library { name: "libc", arch: { x86: { src: "libs/x86/libc.so", }, x86_64: { src: "libs/x86_64/libc.so", }, }, header_libs: [ "libc_headers", ], export_header_lib_headers: ["libc_headers"], min_sdk_version: "9", vendor_available: true, } Bug: 236087698 Test: `ALLOW_MISSING_DEPENDENCIES=true m vendorimage` succeeded Change-Id: I67070b0f3561aa2afd73b6c1c0fdf4255218baac
This commit is contained in:
parent
b7873a8b0f
commit
487689eaee
8 changed files with 447 additions and 32 deletions
|
@ -26,6 +26,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
"android/soong/android"
|
||||
|
@ -9546,6 +9547,63 @@ func TestUpdatableApexEnforcesAppUpdatability(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
|
||||
bp := `
|
||||
apex {
|
||||
name: "myapex",
|
||||
key: "myapex.key",
|
||||
native_shared_libs: ["libfoo"],
|
||||
min_sdk_version: "29",
|
||||
}
|
||||
apex_key {
|
||||
name: "myapex.key",
|
||||
}
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libc"],
|
||||
apex_available: ["myapex"],
|
||||
min_sdk_version: "29",
|
||||
}
|
||||
cc_api_library {
|
||||
name: "libc",
|
||||
src: "libc.so",
|
||||
min_sdk_version: "29",
|
||||
recovery_available: true,
|
||||
}
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libc",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
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
|
||||
}
|
||||
|
||||
libfooApexVariant := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex29").Module()
|
||||
libcApexVariant := result.ModuleForTests("libc.apiimport", "android_arm64_armv8-a_shared_apex29").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "apex variant should link against API surface stub libraries", true, hasDep(libfooApexVariant, libcApexVariant))
|
||||
|
||||
// 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))
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
|
113
cc/cc.go
113
cc/cc.go
|
@ -31,6 +31,7 @@ import (
|
|||
"android/soong/cc/config"
|
||||
"android/soong/fuzz"
|
||||
"android/soong/genrule"
|
||||
"android/soong/multitree"
|
||||
"android/soong/snapshot"
|
||||
)
|
||||
|
||||
|
@ -2184,6 +2185,24 @@ func AddSharedLibDependenciesWithVersions(ctx android.BottomUpMutatorContext, mo
|
|||
}
|
||||
}
|
||||
|
||||
func GetApiImports(c LinkableInterface, actx android.BottomUpMutatorContext) multitree.ApiImportInfo {
|
||||
apiImportInfo := multitree.ApiImportInfo{}
|
||||
|
||||
if c.Device() {
|
||||
var apiImportModule []blueprint.Module
|
||||
if actx.OtherModuleExists("api_imports") {
|
||||
apiImportModule = actx.AddDependency(c, nil, "api_imports")
|
||||
if len(apiImportModule) > 0 && apiImportModule[0] != nil {
|
||||
apiInfo := actx.OtherModuleProvider(apiImportModule[0], multitree.ApiImportsProvider).(multitree.ApiImportInfo)
|
||||
apiImportInfo = apiInfo
|
||||
actx.SetProvider(multitree.ApiImportsProvider, apiInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return apiImportInfo
|
||||
}
|
||||
|
||||
func GetSnapshot(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.BottomUpMutatorContext) SnapshotInfo {
|
||||
// Only device modules with BOARD_VNDK_VERSION uses snapshot. Others use the zero value of
|
||||
// SnapshotInfo, which provides no mappings.
|
||||
|
@ -2209,8 +2228,8 @@ func GetSnapshot(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.
|
|||
return **snapshotInfo
|
||||
}
|
||||
|
||||
func RewriteSnapshotLib(lib string, snapshotMap map[string]string) string {
|
||||
if snapshot, ok := snapshotMap[lib]; ok {
|
||||
func GetReplaceModuleName(lib string, replaceMap map[string]string) string {
|
||||
if snapshot, ok := replaceMap[lib]; ok {
|
||||
return snapshot
|
||||
}
|
||||
|
||||
|
@ -2221,13 +2240,18 @@ func RewriteSnapshotLib(lib string, snapshotMap map[string]string) string {
|
|||
// of names:
|
||||
//
|
||||
// 1. Name of an NDK library that refers to a prebuilt module.
|
||||
// For each of these, it adds the name of the prebuilt module (which will be in
|
||||
// prebuilts/ndk) to the list of nonvariant libs.
|
||||
//
|
||||
// For each of these, it adds the name of the prebuilt module (which will be in
|
||||
// prebuilts/ndk) to the list of nonvariant libs.
|
||||
//
|
||||
// 2. Name of an NDK library that refers to an ndk_library module.
|
||||
// For each of these, it adds the name of the ndk_library module to the list of
|
||||
// variant libs.
|
||||
//
|
||||
// For each of these, it adds the name of the ndk_library module to the list of
|
||||
// variant libs.
|
||||
//
|
||||
// 3. Anything else (so anything that isn't an NDK library).
|
||||
// It adds these to the nonvariantLibs list.
|
||||
//
|
||||
// It adds these to the nonvariantLibs list.
|
||||
//
|
||||
// The caller can then know to add the variantLibs dependencies differently from the
|
||||
// nonvariantLibs
|
||||
|
@ -2239,11 +2263,11 @@ func RewriteLibs(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.
|
|||
// strip #version suffix out
|
||||
name, _ := StubsLibNameAndVersion(entry)
|
||||
if c.InRecovery() {
|
||||
nonvariantLibs = append(nonvariantLibs, RewriteSnapshotLib(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
|
||||
nonvariantLibs = append(nonvariantLibs, GetReplaceModuleName(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
|
||||
} else if c.UseSdk() && inList(name, *getNDKKnownLibs(config)) {
|
||||
variantLibs = append(variantLibs, name+ndkLibrarySuffix)
|
||||
} else if c.UseVndk() {
|
||||
nonvariantLibs = append(nonvariantLibs, RewriteSnapshotLib(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
|
||||
nonvariantLibs = append(nonvariantLibs, GetReplaceModuleName(entry, GetSnapshot(c, snapshotInfo, actx).SharedLibs))
|
||||
} else {
|
||||
// put name#version back
|
||||
nonvariantLibs = append(nonvariantLibs, entry)
|
||||
|
@ -2252,6 +2276,25 @@ func RewriteLibs(c LinkableInterface, snapshotInfo **SnapshotInfo, actx android.
|
|||
return nonvariantLibs, variantLibs
|
||||
}
|
||||
|
||||
func updateDepsWithApiImports(deps Deps, apiImports multitree.ApiImportInfo) Deps {
|
||||
for idx, lib := range deps.SharedLibs {
|
||||
deps.SharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
|
||||
}
|
||||
|
||||
for idx, lib := range deps.LateSharedLibs {
|
||||
deps.LateSharedLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
|
||||
}
|
||||
|
||||
for idx, lib := range deps.RuntimeLibs {
|
||||
deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, apiImports.SharedLibs)
|
||||
}
|
||||
|
||||
for idx, lib := range deps.HeaderLibs {
|
||||
deps.HeaderLibs[idx] = GetReplaceModuleName(lib, apiImports.HeaderLibs)
|
||||
}
|
||||
return deps
|
||||
}
|
||||
|
||||
func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
||||
if !c.Enabled() {
|
||||
return
|
||||
|
@ -2267,6 +2310,9 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
|
||||
deps := c.deps(ctx)
|
||||
|
||||
apiImportInfo := GetApiImports(c, actx)
|
||||
deps = updateDepsWithApiImports(deps, apiImportInfo)
|
||||
|
||||
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
|
||||
|
||||
var snapshotInfo *SnapshotInfo
|
||||
|
@ -2279,7 +2325,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
deps.ReexportSharedLibHeaders, _ = RewriteLibs(c, &snapshotInfo, actx, ctx.Config(), deps.ReexportSharedLibHeaders)
|
||||
|
||||
for idx, lib := range deps.RuntimeLibs {
|
||||
deps.RuntimeLibs[idx] = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).SharedLibs)
|
||||
deps.RuntimeLibs[idx] = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).SharedLibs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2289,7 +2335,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
depTag.reexportFlags = true
|
||||
}
|
||||
|
||||
lib = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
|
||||
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).HeaderLibs)
|
||||
|
||||
if c.IsStubs() {
|
||||
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
|
||||
|
@ -2302,10 +2348,20 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
if c.isNDKStubLibrary() {
|
||||
// NDK stubs depend on their implementation because the ABI dumps are
|
||||
// generated from the implementation library.
|
||||
actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
|
||||
c.ImageVariation(),
|
||||
blueprint.Variation{Mutator: "link", Variation: "shared"},
|
||||
), stubImplementation, c.BaseModuleName())
|
||||
apiImportName := c.BaseModuleName() + multitree.GetApiImportSuffix()
|
||||
|
||||
// If original library exists as imported API, set dependency on the imported library
|
||||
if actx.OtherModuleExists(apiImportName) {
|
||||
actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
|
||||
c.ImageVariation(),
|
||||
blueprint.Variation{Mutator: "link", Variation: "shared"},
|
||||
), stubImplementation, apiImportName)
|
||||
} else {
|
||||
actx.AddFarVariationDependencies(append(ctx.Target().Variations(),
|
||||
c.ImageVariation(),
|
||||
blueprint.Variation{Mutator: "link", Variation: "shared"},
|
||||
), stubImplementation, c.BaseModuleName())
|
||||
}
|
||||
}
|
||||
|
||||
// sysprop_library has to support both C++ and Java. So sysprop_library internally creates one
|
||||
|
@ -2321,7 +2377,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
lib = impl
|
||||
}
|
||||
|
||||
lib = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
|
||||
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
|
||||
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
|
@ -2341,7 +2397,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
lib = impl
|
||||
}
|
||||
|
||||
lib = RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
|
||||
lib = GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs)
|
||||
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
|
@ -2355,7 +2411,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
depTag := libraryDependencyTag{Kind: staticLibraryDependency, staticUnwinder: true}
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
}, depTag, RewriteSnapshotLib(staticUnwinder(actx), GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
|
||||
}, depTag, GetReplaceModuleName(staticUnwinder(actx), GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
|
||||
}
|
||||
|
||||
// shared lib names without the #version suffix
|
||||
|
@ -2387,14 +2443,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
}, depTag, RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
|
||||
}, depTag, GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
|
||||
}
|
||||
|
||||
for _, lib := range deps.UnexportedStaticLibs {
|
||||
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency, unexportedSymbols: true}
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
}, depTag, RewriteSnapshotLib(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
|
||||
}, depTag, GetReplaceModuleName(lib, GetSnapshot(c, &snapshotInfo, actx).StaticLibs))
|
||||
}
|
||||
|
||||
for _, lib := range deps.LateSharedLibs {
|
||||
|
@ -2435,11 +2491,11 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
actx.AddVariationDependencies(crtVariations, objDepTag, deps.ObjFiles...)
|
||||
for _, crt := range deps.CrtBegin {
|
||||
actx.AddVariationDependencies(crtVariations, CrtBeginDepTag,
|
||||
RewriteSnapshotLib(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
|
||||
GetReplaceModuleName(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
|
||||
}
|
||||
for _, crt := range deps.CrtEnd {
|
||||
actx.AddVariationDependencies(crtVariations, CrtEndDepTag,
|
||||
RewriteSnapshotLib(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
|
||||
GetReplaceModuleName(crt, GetSnapshot(c, &snapshotInfo, actx).Objects))
|
||||
}
|
||||
if deps.DynamicLinker != "" {
|
||||
actx.AddDependency(c, dynamicLinkerDepTag, deps.DynamicLinker)
|
||||
|
@ -2464,7 +2520,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
c.ImageVariation(),
|
||||
{Mutator: "link", Variation: "shared"},
|
||||
}, vndkExtDepTag, RewriteSnapshotLib(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
|
||||
}, vndkExtDepTag, GetReplaceModuleName(vndkdep.getVndkExtendsModuleName(), GetSnapshot(c, &snapshotInfo, actx).SharedLibs))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3186,6 +3242,11 @@ 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() &&
|
||||
|
@ -3521,6 +3582,10 @@ 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" {
|
||||
return nil
|
||||
|
@ -3638,9 +3703,7 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Defaults
|
||||
//
|
||||
type Defaults struct {
|
||||
android.ModuleBase
|
||||
android.DefaultsModuleBase
|
||||
|
|
|
@ -17,6 +17,7 @@ package cc
|
|||
import (
|
||||
"android/soong/android"
|
||||
"android/soong/multitree"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -25,10 +26,96 @@ 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_stub_library", CcApiStubLibraryFactory)
|
||||
ctx.RegisterModuleType("cc_api_contribution", CcApiContributionFactory)
|
||||
}
|
||||
|
||||
// 'cc_api_library' is a module type which is from the exported API surface
|
||||
// with C shared library type. The module will replace original module, and
|
||||
// offer a link to the module that generates shared library object from the
|
||||
// map file.
|
||||
type apiLibraryProperties struct {
|
||||
Src *string `android:"arch_variant"`
|
||||
}
|
||||
|
||||
type apiLibraryDecorator struct {
|
||||
*libraryDecorator
|
||||
properties apiLibraryProperties
|
||||
}
|
||||
|
||||
func CcApiLibraryFactory() android.Module {
|
||||
module, decorator := NewLibrary(android.DeviceSupported)
|
||||
apiLibraryDecorator := &apiLibraryDecorator{
|
||||
libraryDecorator: decorator,
|
||||
}
|
||||
apiLibraryDecorator.BuildOnlyShared()
|
||||
|
||||
module.stl = nil
|
||||
module.sanitize = nil
|
||||
decorator.disableStripping()
|
||||
|
||||
module.compiler = nil
|
||||
module.linker = apiLibraryDecorator
|
||||
module.installer = nil
|
||||
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{}
|
||||
}
|
||||
|
||||
module.Init()
|
||||
|
||||
return module
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) Name(basename string) string {
|
||||
return basename + multitree.GetApiImportSuffix()
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
|
||||
// Flags reexported from dependencies. (e.g. vndk_prebuilt_shared)
|
||||
d.libraryDecorator.flagExporter.exportIncludes(ctx)
|
||||
d.libraryDecorator.reexportDirs(deps.ReexportedDirs...)
|
||||
d.libraryDecorator.reexportSystemDirs(deps.ReexportedSystemDirs...)
|
||||
d.libraryDecorator.reexportFlags(deps.ReexportedFlags...)
|
||||
d.libraryDecorator.reexportDeps(deps.ReexportedDeps...)
|
||||
d.libraryDecorator.addExportedGeneratedHeaders(deps.ReexportedGeneratedHeaders...)
|
||||
d.libraryDecorator.flagExporter.setProvider(ctx)
|
||||
|
||||
in := android.PathForModuleSrc(ctx, *d.properties.Src)
|
||||
|
||||
d.unstrippedOutputFile = in
|
||||
libName := d.libraryDecorator.getLibName(ctx) + flags.Toolchain.ShlibSuffix()
|
||||
|
||||
tocFile := android.PathForModuleOut(ctx, libName+".toc")
|
||||
d.tocFile = android.OptionalPathForPath(tocFile)
|
||||
TransformSharedObjectToToc(ctx, in, tocFile)
|
||||
|
||||
ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
|
||||
SharedLibrary: in,
|
||||
Target: ctx.Target(),
|
||||
|
||||
TableOfContents: d.tocFile,
|
||||
})
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
func (d *apiLibraryDecorator) availableFor(what string) bool {
|
||||
// Stub from API surface should be available for any APEX.
|
||||
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)
|
||||
}
|
||||
|
||||
func CcApiStubLibraryFactory() android.Module {
|
||||
module, decorator := NewLibrary(android.DeviceSupported)
|
||||
apiStubDecorator := &apiStubDecorator{
|
||||
|
|
|
@ -22,6 +22,8 @@ import (
|
|||
|
||||
"android/soong/android"
|
||||
"android/soong/multitree"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
func TestCcApiStubLibraryOutputFiles(t *testing.T) {
|
||||
|
@ -106,3 +108,111 @@ func TestApiSurfaceOutputs(t *testing.T) {
|
|||
android.AssertStringEquals(t, "name", "foo.mysdk", api_surface_gen_rule_args["name"])
|
||||
android.AssertStringEquals(t, "symbol_file", "foo.map.txt", api_surface_gen_rule_args["symbol_file"])*/
|
||||
}
|
||||
|
||||
func hasDirectDependency(t *testing.T, ctx *android.TestResult, from android.Module, to android.Module) bool {
|
||||
t.Helper()
|
||||
var found bool
|
||||
ctx.VisitDirectDeps(from, func(dep blueprint.Module) {
|
||||
if dep == to {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
func TestApiLibraryReplacesExistingModule(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
src: "libbar.so",
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "original library should not be linked", false, hasDirectDependency(t, ctx, libfoo, libbar))
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
|
||||
}
|
||||
|
||||
func TestApiLibraryDoNotRequireOriginalModule(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
src: "libbar.so",
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [
|
||||
"libbar",
|
||||
],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
|
||||
android.AssertBoolEquals(t, "Stub library from API surface should be linked", true, hasDirectDependency(t, ctx, libfoo, libbarApiImport))
|
||||
}
|
||||
|
||||
func TestApiLibraryShouldNotReplaceWithoutApiImport(t *testing.T) {
|
||||
bp := `
|
||||
cc_library {
|
||||
name: "libfoo",
|
||||
shared_libs: ["libbar"],
|
||||
}
|
||||
|
||||
cc_library {
|
||||
name: "libbar",
|
||||
}
|
||||
|
||||
cc_api_library {
|
||||
name: "libbar",
|
||||
src: "libbar.so",
|
||||
}
|
||||
|
||||
api_imports {
|
||||
name: "api_imports",
|
||||
shared_libs: [],
|
||||
header_libs: [],
|
||||
}
|
||||
`
|
||||
|
||||
ctx := prepareForCcTest.RunTestWithBp(t, bp)
|
||||
|
||||
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
|
||||
libbar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
|
||||
libbarApiImport := ctx.ModuleForTests("libbar.apiimport", "android_arm64_armv8-a_shared").Module()
|
||||
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
"android/soong/android"
|
||||
"android/soong/genrule"
|
||||
"android/soong/multitree"
|
||||
"android/soong/snapshot"
|
||||
)
|
||||
|
||||
|
@ -31,6 +32,8 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
|
|||
RegisterLibraryHeadersBuildComponents(ctx)
|
||||
RegisterLibraryStubBuildComponents(ctx)
|
||||
|
||||
multitree.RegisterApiImportsModule(ctx)
|
||||
|
||||
ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
|
||||
ctx.RegisterModuleType("cc_object", ObjectFactory)
|
||||
ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
|
||||
|
|
|
@ -10,6 +10,7 @@ bootstrap_go_package {
|
|||
"soong-android",
|
||||
],
|
||||
srcs: [
|
||||
"api_imports.go",
|
||||
"api_surface.go",
|
||||
"export.go",
|
||||
"metadata.go",
|
||||
|
|
88
multitree/api_imports.go
Normal file
88
multitree/api_imports.go
Normal file
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2022 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package multitree
|
||||
|
||||
import (
|
||||
"android/soong/android"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
)
|
||||
|
||||
var (
|
||||
apiImportNameSuffix = ".apiimport"
|
||||
)
|
||||
|
||||
func init() {
|
||||
RegisterApiImportsModule(android.InitRegistrationContext)
|
||||
}
|
||||
|
||||
func RegisterApiImportsModule(ctx android.RegistrationContext) {
|
||||
ctx.RegisterModuleType("api_imports", apiImportsFactory)
|
||||
}
|
||||
|
||||
type ApiImports struct {
|
||||
android.ModuleBase
|
||||
properties apiImportsProperties
|
||||
}
|
||||
|
||||
type apiImportsProperties struct {
|
||||
Shared_libs []string // List of C shared libraries from API surfaces
|
||||
Header_libs []string // List of C header libraries from API surfaces
|
||||
}
|
||||
|
||||
// 'api_imports' is a module which describes modules available from API surfaces.
|
||||
// This module is required to get the list of all imported API modules, because
|
||||
// it is discouraged to loop and fetch all modules from its type information. The
|
||||
// only module with name 'api_imports' will be used from the build.
|
||||
func apiImportsFactory() android.Module {
|
||||
module := &ApiImports{}
|
||||
module.AddProperties(&module.properties)
|
||||
android.InitAndroidModule(module)
|
||||
return module
|
||||
}
|
||||
|
||||
func (imports *ApiImports) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||
// ApiImport module does not generate any build actions
|
||||
}
|
||||
|
||||
type ApiImportInfo struct {
|
||||
SharedLibs, HeaderLibs map[string]string
|
||||
}
|
||||
|
||||
var ApiImportsProvider = blueprint.NewMutatorProvider(ApiImportInfo{}, "deps")
|
||||
|
||||
// Store module lists into ApiImportInfo and share it over mutator provider.
|
||||
func (imports *ApiImports) DepsMutator(ctx android.BottomUpMutatorContext) {
|
||||
generateNameMapWithSuffix := func(names []string) map[string]string {
|
||||
moduleNameMap := make(map[string]string)
|
||||
for _, name := range names {
|
||||
moduleNameMap[name] = name + apiImportNameSuffix
|
||||
}
|
||||
|
||||
return moduleNameMap
|
||||
}
|
||||
|
||||
sharedLibs := generateNameMapWithSuffix(imports.properties.Shared_libs)
|
||||
headerLibs := generateNameMapWithSuffix(imports.properties.Header_libs)
|
||||
|
||||
ctx.SetProvider(ApiImportsProvider, ApiImportInfo{
|
||||
SharedLibs: sharedLibs,
|
||||
HeaderLibs: headerLibs,
|
||||
})
|
||||
}
|
||||
|
||||
func GetApiImportSuffix() string {
|
||||
return apiImportNameSuffix
|
||||
}
|
19
rust/rust.go
19
rust/rust.go
|
@ -1380,6 +1380,11 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
var commonDepVariations []blueprint.Variation
|
||||
var snapshotInfo *cc.SnapshotInfo
|
||||
|
||||
apiImportInfo := cc.GetApiImports(mod, actx)
|
||||
for idx, lib := range deps.SharedLibs {
|
||||
deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs)
|
||||
}
|
||||
|
||||
if ctx.Os() == android.Android {
|
||||
deps.SharedLibs, _ = cc.RewriteLibs(mod, &snapshotInfo, actx, ctx.Config(), deps.SharedLibs)
|
||||
}
|
||||
|
@ -1400,7 +1405,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
rlibDepVariations = append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: rlibVariation})
|
||||
for _, lib := range deps.Rlibs {
|
||||
depTag := rlibDepTag
|
||||
lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
|
||||
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
|
||||
|
||||
actx.AddVariationDependencies(rlibDepVariations, depTag, lib)
|
||||
}
|
||||
|
@ -1438,7 +1443,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
|
||||
for _, lib := range deps.Stdlibs {
|
||||
depTag := rlibDepTag
|
||||
lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
|
||||
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
|
||||
|
||||
actx.AddVariationDependencies(append(commonDepVariations, []blueprint.Variation{{Mutator: "rust_libraries", Variation: "rlib"}}...),
|
||||
depTag, lib)
|
||||
|
@ -1462,7 +1467,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
|
||||
for _, lib := range deps.WholeStaticLibs {
|
||||
depTag := cc.StaticDepTag(true)
|
||||
lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
|
||||
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
|
||||
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
|
@ -1471,7 +1476,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
|
||||
for _, lib := range deps.StaticLibs {
|
||||
depTag := cc.StaticDepTag(false)
|
||||
lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
|
||||
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).StaticLibs)
|
||||
|
||||
actx.AddVariationDependencies([]blueprint.Variation{
|
||||
{Mutator: "link", Variation: "static"},
|
||||
|
@ -1483,11 +1488,11 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
crtVariations := cc.GetCrtVariations(ctx, mod)
|
||||
for _, crt := range deps.CrtBegin {
|
||||
actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag,
|
||||
cc.RewriteSnapshotLib(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
|
||||
cc.GetReplaceModuleName(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
|
||||
}
|
||||
for _, crt := range deps.CrtEnd {
|
||||
actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag,
|
||||
cc.RewriteSnapshotLib(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
|
||||
cc.GetReplaceModuleName(crt, cc.GetSnapshot(mod, &snapshotInfo, actx).Objects))
|
||||
}
|
||||
|
||||
if mod.sourceProvider != nil {
|
||||
|
@ -1510,7 +1515,7 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|||
|
||||
// addRlibDependency will add an rlib dependency, rewriting to the snapshot library if available.
|
||||
func addRlibDependency(actx android.BottomUpMutatorContext, lib string, mod *Module, snapshotInfo *cc.SnapshotInfo, variations []blueprint.Variation) {
|
||||
lib = cc.RewriteSnapshotLib(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
|
||||
lib = cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Rlibs)
|
||||
actx.AddVariationDependencies(variations, rlibDepTag, lib)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue