Delete multitree api imports code

The mutltiree workflow has not been in use for a while. This CL cleans
up the code that was added to support multitree.

Details
- Delete cc_api_library, cc_api_headers, cc_api_variant module types.
  These module types contain build rules for prebuilt stub .so and .h
files
- Update the DepsMutator of cc.Module to not create a dependency on a
  sibling cc_api_* module if it exists. e.g. do not create a dependency
on libfoo.apiimports if libfoo is listed in `shared_libs`.
- Remove cc_api_library from the stub/impl selection logic for cc
  modules

Test: m nothing --no-skip-soong-tests
Test: presbumits
Change-Id: Ie194157fb3bbc630f384cdd9b694b0fba6786ded
This commit is contained in:
Spandan Das
2024-09-11 18:48:44 +00:00
parent f2c204c655
commit ff66518da2
17 changed files with 6 additions and 1426 deletions

View File

@@ -15,7 +15,6 @@ bootstrap_go_package {
"soong-cc", "soong-cc",
"soong-filesystem", "soong-filesystem",
"soong-java", "soong-java",
"soong-multitree",
"soong-provenance", "soong-provenance",
"soong-python", "soong-python",
"soong-rust", "soong-rust",

View File

@@ -32,7 +32,6 @@ import (
prebuilt_etc "android/soong/etc" prebuilt_etc "android/soong/etc"
"android/soong/filesystem" "android/soong/filesystem"
"android/soong/java" "android/soong/java"
"android/soong/multitree"
"android/soong/rust" "android/soong/rust"
"android/soong/sh" "android/soong/sh"
) )
@@ -438,7 +437,6 @@ type apexBundle struct {
android.ModuleBase android.ModuleBase
android.DefaultableModuleBase android.DefaultableModuleBase
android.OverridableModuleBase android.OverridableModuleBase
multitree.ExportableModuleBase
// Properties // Properties
properties apexBundleProperties properties apexBundleProperties
@@ -1406,8 +1404,6 @@ func (a *apexBundle) DepIsInSameApex(_ android.BaseModuleContext, _ android.Modu
return true return true
} }
var _ multitree.Exportable = (*apexBundle)(nil)
func (a *apexBundle) Exportable() bool { func (a *apexBundle) Exportable() bool {
return true return true
} }
@@ -2540,7 +2536,6 @@ func newApexBundle() *apexBundle {
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon) android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module) android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableProperties.Overrides) android.InitOverridableModule(module, &module.overridableProperties.Overrides)
multitree.InitExportableModule(module)
return module return module
} }

View File

@@ -10274,208 +10274,6 @@ func TestUpdatableApexEnforcesAppUpdatability(t *testing.T) {
} }
} }
func TestApexBuildsAgainstApiSurfaceStubLibraries(t *testing.T) {
bp := `
apex {
name: "myapex",
key: "myapex.key",
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: "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: "libbar",
src: "libbar_stub.so",
min_sdk_version: "29",
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",
apex_shared_libs: [
"libbar",
"libbaz",
"libqux",
],
}
`
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_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(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").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) { func TestTrimmedApex(t *testing.T) {
bp := ` bp := `
apex { apex {
@@ -10514,21 +10312,6 @@ func TestTrimmedApex(t *testing.T) {
apex_available: ["myapex","mydcla"], apex_available: ["myapex","mydcla"],
min_sdk_version: "29", min_sdk_version: "29",
} }
cc_api_library {
name: "libc",
src: "libc.so",
min_sdk_version: "29",
recovery_available: true,
vendor_available: true,
product_available: true,
}
api_imports {
name: "api_imports",
shared_libs: [
"libc",
],
header_libs: [],
}
` `
ctx := testApex(t, bp) ctx := testApex(t, bp)
module := ctx.ModuleForTests("myapex", "android_common_myapex") module := ctx.ModuleForTests("myapex", "android_common_myapex")

View File

@@ -16,7 +16,6 @@ bootstrap_go_package {
"soong-etc", "soong-etc",
"soong-fuzz", "soong-fuzz",
"soong-genrule", "soong-genrule",
"soong-multitree",
"soong-testing", "soong-testing",
"soong-tradefed", "soong-tradefed",
], ],
@@ -65,7 +64,6 @@ bootstrap_go_package {
"library.go", "library.go",
"library_headers.go", "library_headers.go",
"library_sdk_member.go", "library_sdk_member.go",
"library_stub.go",
"native_bridge_sdk_trait.go", "native_bridge_sdk_trait.go",
"object.go", "object.go",
"test.go", "test.go",

View File

@@ -21,7 +21,6 @@ import (
"strings" "strings"
"android/soong/android" "android/soong/android"
"android/soong/multitree"
) )
var ( var (
@@ -479,34 +478,6 @@ func (p *prebuiltBinaryLinker) AndroidMkEntries(ctx AndroidMkContext, entries *a
androidMkWritePrebuiltOptions(p.baseLinker, entries) androidMkWritePrebuiltOptions(p.baseLinker, entries)
} }
func (a *apiLibraryDecorator) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
entries.Class = "SHARED_LIBRARIES"
entries.SubName += multitree.GetApiImportSuffix()
entries.ExtraEntries = append(entries.ExtraEntries, func(_ android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
a.libraryDecorator.androidMkWriteExportedFlags(entries)
src := *a.properties.Src
path, file := filepath.Split(src)
stem, suffix, ext := android.SplitFileExt(file)
entries.SetString("LOCAL_BUILT_MODULE_STEM", "$(LOCAL_MODULE)"+ext)
entries.SetString("LOCAL_MODULE_SUFFIX", suffix)
entries.SetString("LOCAL_MODULE_STEM", stem)
entries.SetString("LOCAL_MODULE_PATH", path)
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", true)
entries.SetString("LOCAL_SOONG_TOC", a.toc().String())
})
}
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 androidMkWritePrebuiltOptions(linker *baseLinker, entries *android.AndroidMkEntries) { func androidMkWritePrebuiltOptions(linker *baseLinker, entries *android.AndroidMkEntries) {
allow := linker.Properties.Allow_undefined_symbols allow := linker.Properties.Allow_undefined_symbols
if allow != nil { if allow != nil {

119
cc/cc.go
View File

@@ -34,7 +34,6 @@ import (
"android/soong/cc/config" "android/soong/cc/config"
"android/soong/fuzz" "android/soong/fuzz"
"android/soong/genrule" "android/soong/genrule"
"android/soong/multitree"
) )
func init() { func init() {
@@ -2361,24 +2360,6 @@ 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, _ := android.OtherModuleProvider(actx, apiImportModule[0], multitree.ApiImportsProvider)
apiImportInfo = apiInfo
android.SetProvider(actx, multitree.ApiImportsProvider, apiInfo)
}
}
}
return apiImportInfo
}
func GetReplaceModuleName(lib string, replaceMap map[string]string) string { func GetReplaceModuleName(lib string, replaceMap map[string]string) string {
if snapshot, ok := replaceMap[lib]; ok { if snapshot, ok := replaceMap[lib]; ok {
return snapshot return snapshot
@@ -2448,11 +2429,6 @@ func (c *Module) shouldUseApiSurface() bool {
// NDK Variant // NDK Variant
return true return true
} }
if c.isImportedApiLibrary() {
// API Library should depend on API headers
return true
}
} }
return false return false
@@ -2472,19 +2448,10 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
ctx.ctx = ctx ctx.ctx = ctx
deps := c.deps(ctx) deps := c.deps(ctx)
apiImportInfo := GetApiImports(c, actx)
apiNdkLibs := []string{} apiNdkLibs := []string{}
apiLateNdkLibs := []string{} apiLateNdkLibs := []string{}
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())
deps.ReexportHeaderLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportHeaderLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
deps.ReexportSharedLibHeaders, _ = rewriteLibsForApiImports(c, deps.ReexportSharedLibHeaders, apiImportInfo.SharedLibs, ctx.Config())
}
c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs c.Properties.AndroidMkSystemSharedLibs = deps.SystemSharedLibs
variantNdkLibs := []string{} variantNdkLibs := []string{}
@@ -2501,11 +2468,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
depTag.reexportFlags = true depTag.reexportFlags = true
} }
// Check header lib replacement from API surface first, and then check again with VSDK
if c.shouldUseApiSurface() {
lib = GetReplaceModuleName(lib, apiImportInfo.HeaderLibs)
}
if c.isNDKStubLibrary() { if c.isNDKStubLibrary() {
variationExists := actx.OtherModuleDependencyVariantExists(nil, lib) variationExists := actx.OtherModuleDependencyVariantExists(nil, lib)
if variationExists { if variationExists {
@@ -2515,7 +2477,7 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
// any variants. // any variants.
actx.AddFarVariationDependencies([]blueprint.Variation{}, depTag, lib) actx.AddFarVariationDependencies([]blueprint.Variation{}, depTag, lib)
} }
} else if c.IsStubs() && !c.isImportedApiLibrary() { } else if c.IsStubs() {
actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()), actx.AddFarVariationDependencies(append(ctx.Target().Variations(), c.ImageVariation()),
depTag, lib) depTag, lib)
} else { } else {
@@ -2591,24 +2553,14 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
} }
name, version := StubsLibNameAndVersion(lib) name, version := StubsLibNameAndVersion(lib)
if apiLibraryName, ok := apiImportInfo.SharedLibs[name]; ok && !ctx.OtherModuleExists(name) {
name = apiLibraryName
}
sharedLibNames = append(sharedLibNames, name) sharedLibNames = append(sharedLibNames, name)
variations := []blueprint.Variation{ variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"}, {Mutator: "link", Variation: "shared"},
} }
if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
AddSharedLibDependenciesWithVersions(ctx, c, variations, depTag, name, version, false) 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 { for _, lib := range deps.LateStaticLibs {
depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency} depTag := libraryDependencyTag{Kind: staticLibraryDependency, Order: lateLibraryDependency}
actx.AddVariationDependencies([]blueprint.Variation{ actx.AddVariationDependencies([]blueprint.Variation{
@@ -2701,7 +2653,6 @@ func (c *Module) DepsMutator(actx android.BottomUpMutatorContext) {
) )
} }
updateImportedLibraryDependency(ctx)
} }
func BeginMutator(ctx android.BottomUpMutatorContext) { func BeginMutator(ctx android.BottomUpMutatorContext) {
@@ -2730,10 +2681,6 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin
return return
} }
// TODO(b/244244438) : Remove this once all variants are implemented
if ccFrom, ok := from.(*Module); ok && ccFrom.isImportedApiLibrary() {
return
}
if from.SdkVersion() == "" { if from.SdkVersion() == "" {
// Platform code can link to anything // Platform code can link to anything
return return
@@ -2756,10 +2703,6 @@ func checkLinkType(ctx android.BaseModuleContext, from LinkableInterface, to Lin
// the NDK. // the NDK.
return return
} }
if c.isImportedApiLibrary() {
// Imported library from the API surface is a stub library built against interface definition.
return
}
} }
if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" { if strings.HasPrefix(ctx.ModuleName(), "libclang_rt.") && to.Module().Name() == "libc++" {
@@ -2935,47 +2878,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
skipModuleList := map[string]bool{} skipModuleList := map[string]bool{}
var apiImportInfo multitree.ApiImportInfo
hasApiImportInfo := false
ctx.VisitDirectDeps(func(dep android.Module) {
if dep.Name() == "api_imports" {
apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
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) { ctx.VisitDirectDeps(func(dep android.Module) {
depName := ctx.OtherModuleName(dep) depName := ctx.OtherModuleName(dep)
depTag := ctx.OtherModuleDependencyTag(dep) depTag := ctx.OtherModuleDependencyTag(dep)
@@ -3404,17 +3306,7 @@ func ShouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
// bootstrap modules, always link to non-stub variant // bootstrap modules, always link to non-stub variant
isNotInPlatform := dep.(android.ApexModule).NotInPlatform() isNotInPlatform := dep.(android.ApexModule).NotInPlatform()
isApexImportedApiLibrary := false useStubs = isNotInPlatform && !bootstrap
if cc, ok := dep.(*Module); ok {
if apiLibrary, ok := cc.linker.(*apiLibraryDecorator); ok {
if apiLibrary.hasApexStubs() {
isApexImportedApiLibrary = true
}
}
}
useStubs = (isNotInPlatform || isApexImportedApiLibrary) && !bootstrap
if useStubs { if useStubs {
// Another exception: if this module is a test for an APEX, then // Another exception: if this module is a test for an APEX, then
@@ -3439,7 +3331,7 @@ func ShouldUseStubForApex(ctx android.ModuleContext, dep android.Module) bool {
// only partially overlapping apex_available. For that test_for // only partially overlapping apex_available. For that test_for
// modules would need to be split into APEX variants and resolved // modules would need to be split into APEX variants and resolved
// separately for each APEX they have access to. // separately for each APEX they have access to.
if !isApexImportedApiLibrary && android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) { if android.AvailableToSameApexes(thisModule, dep.(android.ApexModule)) {
useStubs = false useStubs = false
} }
} }
@@ -4023,11 +3915,6 @@ func (c *Module) IsSdkVariant() bool {
return c.Properties.IsSdkVariant return c.Properties.IsSdkVariant
} }
func (c *Module) isImportedApiLibrary() bool {
_, ok := c.linker.(*apiLibraryDecorator)
return ok
}
func kytheExtractAllFactory() android.Singleton { func kytheExtractAllFactory() android.Singleton {
return &kytheExtractAllSingleton{} return &kytheExtractAllSingleton{}
} }

View File

@@ -2350,9 +2350,8 @@ func (versionTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, varia
if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) { if library := moduleLibraryInterface(ctx.Module()); library != nil && canBeVersionVariant(m) {
isLLNDK := m.IsLlndk() isLLNDK := m.IsLlndk()
isVendorPublicLibrary := m.IsVendorPublicLibrary() isVendorPublicLibrary := m.IsVendorPublicLibrary()
isImportedApiLibrary := m.isImportedApiLibrary()
if variation != "" || isLLNDK || isVendorPublicLibrary || isImportedApiLibrary { if variation != "" || isLLNDK || isVendorPublicLibrary {
// A stubs or LLNDK stubs variant. // A stubs or LLNDK stubs variant.
if m.sanitize != nil { if m.sanitize != nil {
m.sanitize.Properties.ForceDisable = true m.sanitize.Properties.ForceDisable = true

View File

@@ -1,512 +0,0 @@
// Copyright 2021 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 cc
import (
"regexp"
"strings"
"android/soong/android"
"android/soong/multitree"
"github.com/google/blueprint/proptools"
)
var (
ndkVariantRegex = regexp.MustCompile("ndk\\.([a-zA-Z0-9]+)")
stubVariantRegex = regexp.MustCompile("apex\\.([a-zA-Z0-9]+)")
)
func init() {
RegisterLibraryStubBuildComponents(android.InitRegistrationContext)
}
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.InVendorOrProduct() && apiLibrary.hasLLNDKStubs() {
// Add LLNDK variant dependency
if inList("llndk", apiLibrary.properties.Variants) {
variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
ctx.AddDependency(m, nil, variantName)
}
} else if m.IsSdkVariant() {
// Add NDK variant dependencies
targetVariant := "ndk." + m.StubsVersion()
if inList(targetVariant, apiLibrary.properties.Variants) {
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)
}
}
}
// '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"`
Variants []string
}
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.library = apiLibraryDecorator
module.AddProperties(&module.Properties, &apiLibraryDecorator.properties)
// 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{}
}
apiLibraryDecorator.baseLinker.Properties.No_libcrt = BoolPtr(true)
apiLibraryDecorator.baseLinker.Properties.Nocrt = BoolPtr(true)
module.Init()
return module
}
func (d *apiLibraryDecorator) Name(basename string) string {
return basename + multitree.GetApiImportSuffix()
}
// Export include dirs without checking for existence.
// The directories are not guaranteed to exist during Soong analysis.
func (d *apiLibraryDecorator) exportIncludes(ctx ModuleContext) {
exporterProps := d.flagExporter.Properties
for _, dir := range exporterProps.Export_include_dirs.GetOrDefault(ctx, nil) {
d.dirs = append(d.dirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
}
// system headers
for _, dir := range exporterProps.Export_system_include_dirs {
d.systemDirs = append(d.systemDirs, android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), dir))
}
}
func (d *apiLibraryDecorator) linkerInit(ctx BaseModuleContext) {
d.baseLinker.linkerInit(ctx)
if d.hasNDKStubs() {
// Set SDK version of module as current
ctx.Module().(*Module).Properties.Sdk_version = StringPtr("current")
// Add NDK stub as NDK known libs
name := ctx.ModuleName()
ndkKnownLibsLock.Lock()
ndkKnownLibs := getNDKKnownLibs(ctx.Config())
if !inList(name, *ndkKnownLibs) {
*ndkKnownLibs = append(*ndkKnownLibs, name)
}
ndkKnownLibsLock.Unlock()
}
}
func (d *apiLibraryDecorator) link(ctx ModuleContext, flags Flags, deps PathDeps, objects Objects) android.Path {
m, _ := ctx.Module().(*Module)
var in android.Path
// src might not exist during the beginning of soong analysis in Multi-tree
if src := String(d.properties.Src); src != "" {
in = android.MaybeExistentPathForSource(ctx, ctx.ModuleDir(), src)
}
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
}
})
if mod != nil {
variantMod, ok := mod.(*CcApiVariant)
if ok {
in = variantMod.Src()
// Copy LLDNK properties to cc_api_library module
exportIncludeDirs := append(d.libraryDecorator.flagExporter.Properties.Export_include_dirs.GetOrDefault(ctx, nil),
variantMod.exportProperties.Export_include_dirs...)
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](
nil,
[]proptools.ConfigurableCase[[]string]{
proptools.NewConfigurableCase[[]string](nil, &exportIncludeDirs),
},
)
// 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.GetOrDefault(ctx, nil)...)
d.libraryDecorator.flagExporter.Properties.Export_include_dirs = proptools.NewConfigurable[[]string](nil, nil)
}
}
}
}
if m.InVendorOrProduct() && 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)
d.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...)
if in == nil {
ctx.PropertyErrorf("src", "Unable to locate source property")
return nil
}
// 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.
// Creating this dependency ensures that the headers are assembled before compilation of rdeps begins.
d.libraryDecorator.reexportDeps(in)
d.libraryDecorator.flagExporter.setProvider(ctx)
d.unstrippedOutputFile = in
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",
},
})
android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: outputFile,
Target: ctx.Target(),
TableOfContents: d.tocFile,
})
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, _ := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
stubsInfo = append(stubsInfo, SharedStubLibrary{
Version: moduleLibraryInterface(stub).stubsVersion(),
SharedLibraryInfo: stubInfo,
FlagExporterInfo: flagInfo,
})
}
android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
IsLLNDK: ctx.IsLlndk(),
})
}
}
func (d *apiLibraryDecorator) availableFor(what string) bool {
// Stub from API surface should be available for any APEX.
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.BaseModuleContext) []string {
m, ok := ctx.Module().(*Module)
if !ok {
return nil
}
// 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() {
return d.getNdkVersions()
}
}
if d.hasLLNDKStubs() && m.InVendorOrProduct() {
// 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
}
firstVersion, err := nativeApiLevelFromUser(ctx,
m.MinSdkVersion())
if err != nil {
return nil
}
return ndkLibraryVersions(ctx, firstVersion)
}
func (d *apiLibraryDecorator) hasLLNDKStubs() bool {
return inList("llndk", d.properties.Variants)
}
func (d *apiLibraryDecorator) hasNDKStubs() bool {
for _, variant := range d.properties.Variants {
if ndkVariantRegex.MatchString(variant) {
return true
}
}
return false
}
func (d *apiLibraryDecorator) getNdkVersions() []string {
ndkVersions := []string{}
for _, variant := range d.properties.Variants {
if match := ndkVariantRegex.FindStringSubmatch(variant); len(match) == 2 {
ndkVersions = append(ndkVersions, match[1])
}
}
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.
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
// 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
}
type ccApiexportProperties struct {
Src *string `android:"arch_variant"`
Variant *string
Version *string
}
type variantExporterProperties struct {
// Header directory to export
Export_include_dirs []string `android:"arch_variant"`
// 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 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(), String(v.properties.Src))
}
func (v *CcApiVariant) Name() string {
version := 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) VendorVariantNeeded(ctx android.BaseModuleContext) bool {
return String(v.properties.Variant) == "llndk"
}
func (v *CcApiVariant) ProductVariantNeeded(ctx android.BaseModuleContext) bool {
return String(v.properties.Variant) == "llndk"
}
func (v *CcApiVariant) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
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 }
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 { return nil }
func (v *CcApiVariant) SetImageVariation(ctx android.BaseModuleContext, variation string) {
}

View File

@@ -51,13 +51,6 @@ func (sdkTransitionMutator) Split(ctx android.BaseModuleContext) []string {
return []string{""} return []string{""}
} }
} }
case *CcApiVariant:
ccApiVariant, _ := ctx.Module().(*CcApiVariant)
if String(ccApiVariant.properties.Variant) == "ndk" {
return []string{"sdk"}
} else {
return []string{""}
}
} }
return []string{""} return []string{""}
@@ -84,11 +77,6 @@ func (sdkTransitionMutator) IncomingTransition(ctx android.IncomingTransitionCon
return incomingVariation return incomingVariation
} }
} }
case *CcApiVariant:
ccApiVariant, _ := ctx.Module().(*CcApiVariant)
if String(ccApiVariant.properties.Variant) == "ndk" {
return "sdk"
}
} }
if ctx.IsAddingDependency() { if ctx.IsAddingDependency() {

View File

@@ -20,7 +20,6 @@ import (
"android/soong/android" "android/soong/android"
"android/soong/genrule" "android/soong/genrule"
"android/soong/multitree"
) )
func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
@@ -29,9 +28,6 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
RegisterBinaryBuildComponents(ctx) RegisterBinaryBuildComponents(ctx)
RegisterLibraryBuildComponents(ctx) RegisterLibraryBuildComponents(ctx)
RegisterLibraryHeadersBuildComponents(ctx) RegisterLibraryHeadersBuildComponents(ctx)
RegisterLibraryStubBuildComponents(ctx)
multitree.RegisterApiImportsModule(ctx)
ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool) ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory) ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)

View File

@@ -1,20 +0,0 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
}
bootstrap_go_package {
name: "soong-multitree",
pkgPath: "android/soong/multitree",
deps: [
"blueprint",
"soong-android",
],
srcs: [
"api_imports.go",
"api_surface.go",
"export.go",
"metadata.go",
"import.go",
],
pluginFor: ["soong_build"],
}

View File

@@ -1,102 +0,0 @@
// 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"
"strings"
"github.com/google/blueprint"
)
var (
apiImportNameSuffix = ".apiimport"
)
func init() {
RegisterApiImportsModule(android.InitRegistrationContext)
android.RegisterMakeVarsProvider(pctx, makeVarsProvider)
}
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
Apex_shared_libs []string // List of C shared libraries with APEX stubs
}
// '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, ApexSharedLibs 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)
apexSharedLibs := generateNameMapWithSuffix(imports.properties.Apex_shared_libs)
android.SetProvider(ctx, ApiImportsProvider, ApiImportInfo{
SharedLibs: sharedLibs,
HeaderLibs: headerLibs,
ApexSharedLibs: apexSharedLibs,
})
}
func GetApiImportSuffix() string {
return apiImportNameSuffix
}
func makeVarsProvider(ctx android.MakeVarsContext) {
ctx.VisitAllModules(func(m android.Module) {
if i, ok := m.(*ApiImports); ok {
ctx.Strict("API_IMPORTED_SHARED_LIBRARIES", strings.Join(i.properties.Shared_libs, " "))
ctx.Strict("API_IMPORTED_HEADER_LIBRARIES", strings.Join(i.properties.Header_libs, " "))
}
})
}

View File

@@ -1,109 +0,0 @@
// Copyright 2021 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 (
pctx = android.NewPackageContext("android/soong/multitree")
)
func init() {
RegisterApiSurfaceBuildComponents(android.InitRegistrationContext)
}
var PrepareForTestWithApiSurface = android.FixtureRegisterWithContext(RegisterApiSurfaceBuildComponents)
func RegisterApiSurfaceBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("api_surface", ApiSurfaceFactory)
}
type ApiSurface struct {
android.ModuleBase
ExportableModuleBase
properties apiSurfaceProperties
taggedOutputs map[string]android.Paths
}
type apiSurfaceProperties struct {
Contributions []string
}
func ApiSurfaceFactory() android.Module {
module := &ApiSurface{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
InitExportableModule(module)
return module
}
func (surface *ApiSurface) DepsMutator(ctx android.BottomUpMutatorContext) {
if surface.properties.Contributions != nil {
ctx.AddVariationDependencies(nil, nil, surface.properties.Contributions...)
}
}
func (surface *ApiSurface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
contributionFiles := make(map[string]android.Paths)
var allOutputs android.Paths
ctx.WalkDeps(func(child, parent android.Module) bool {
if contribution, ok := child.(ApiContribution); ok {
copied := contribution.CopyFilesWithTag(ctx)
for tag, files := range copied {
contributionFiles[child.Name()+"#"+tag] = files
}
for _, paths := range copied {
allOutputs = append(allOutputs, paths...)
}
return false // no transitive dependencies
}
return false
})
// phony target
ctx.Build(pctx, android.BuildParams{
Rule: blueprint.Phony,
Output: android.PathForPhony(ctx, ctx.ModuleName()),
Inputs: allOutputs,
})
surface.taggedOutputs = contributionFiles
ctx.SetOutputFiles(allOutputs, "")
}
func (surface *ApiSurface) TaggedOutputs() map[string]android.Paths {
return surface.taggedOutputs
}
func (surface *ApiSurface) Exportable() bool {
return true
}
var _ Exportable = (*ApiSurface)(nil)
type ApiContribution interface {
// copy files necessaryt to construct an API surface
// For C, it will be map.txt and .h files
// For Java, it will be api.txt
CopyFilesWithTag(ctx android.ModuleContext) map[string]android.Paths // output paths
// Generate Android.bp in out/ to use the exported .txt files
// GenerateBuildFiles(ctx ModuleContext) Paths //output paths
}

View File

@@ -1,66 +0,0 @@
// 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/proptools"
)
type moduleExportProperty struct {
// True if the module is exported to the other components in a multi-tree.
// Any components in the multi-tree can import this module to use.
Export *bool
}
type ExportableModuleBase struct {
properties moduleExportProperty
}
type Exportable interface {
// Properties for the exporable module.
exportableModuleProps() *moduleExportProperty
// Check if this module can be exported.
// If this returns false, the module will not be exported regardless of the 'export' value.
Exportable() bool
// Returns 'true' if this module has 'export: true'
// This module will not be exported if it returns 'false' to 'Exportable()' interface even if
// it has 'export: true'.
IsExported() bool
// Map from tags to outputs.
// Each module can tag their outputs for convenience.
TaggedOutputs() map[string]android.Paths
}
type ExportableModule interface {
android.Module
Exportable
}
func InitExportableModule(module ExportableModule) {
module.AddProperties(module.exportableModuleProps())
}
func (m *ExportableModuleBase) exportableModuleProps() *moduleExportProperty {
return &m.properties
}
func (m *ExportableModuleBase) IsExported() bool {
return proptools.Bool(m.properties.Export)
}

View File

@@ -1,96 +0,0 @@
// 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"
)
var (
nameSuffix = ".imported"
)
type MultitreeImportedModuleInterface interface {
GetMultitreeImportedModuleName() string
}
func init() {
android.RegisterModuleType("imported_filegroup", importedFileGroupFactory)
android.PreArchMutators(RegisterMultitreePreArchMutators)
}
type importedFileGroupProperties struct {
// Imported modules from the other components in a multi-tree
Imported []string
}
type importedFileGroup struct {
android.ModuleBase
properties importedFileGroupProperties
srcs android.Paths
}
func (ifg *importedFileGroup) Name() string {
return ifg.BaseModuleName() + nameSuffix
}
func importedFileGroupFactory() android.Module {
module := &importedFileGroup{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
return module
}
var _ MultitreeImportedModuleInterface = (*importedFileGroup)(nil)
func (ifg *importedFileGroup) GetMultitreeImportedModuleName() string {
// The base module name of the imported filegroup is used as the imported module name
return ifg.BaseModuleName()
}
var _ android.SourceFileProducer = (*importedFileGroup)(nil)
func (ifg *importedFileGroup) Srcs() android.Paths {
return ifg.srcs
}
func (ifg *importedFileGroup) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// srcs from this module must not be used. Adding a dot path to avoid the empty
// source failure. Still soong returns error when a module wants to build against
// this source, which is intended.
ifg.srcs = android.PathsForModuleSrc(ctx, []string{"."})
}
func RegisterMultitreePreArchMutators(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("multitree_imported_rename", MultitreeImportedRenameMutator).Parallel()
}
func MultitreeImportedRenameMutator(ctx android.BottomUpMutatorContext) {
if m, ok := ctx.Module().(MultitreeImportedModuleInterface); ok {
name := m.GetMultitreeImportedModuleName()
if !ctx.OtherModuleExists(name) {
// Provide an empty filegroup not to break the build while updating the metadata.
// In other cases, soong will report an error to guide users to run 'm update-meta'
// first.
if !ctx.Config().TargetMultitreeUpdateMeta() {
ctx.ModuleErrorf("\"%s\" filegroup must be imported.\nRun 'm update-meta' first to import the filegroup.", name)
}
ctx.Rename(name)
}
}
}

View File

@@ -1,74 +0,0 @@
// 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"
"encoding/json"
)
func init() {
android.RegisterParallelSingletonType("update-meta", UpdateMetaSingleton)
}
func UpdateMetaSingleton() android.Singleton {
return &updateMetaSingleton{}
}
type jsonImported struct {
FileGroups map[string][]string `json:",omitempty"`
}
type metadataJsonFlags struct {
Imported jsonImported `json:",omitempty"`
Exported map[string][]string `json:",omitempty"`
}
type updateMetaSingleton struct {
importedModules []string
generatedMetadataFile android.OutputPath
}
func (s *updateMetaSingleton) GenerateBuildActions(ctx android.SingletonContext) {
metadata := metadataJsonFlags{
Imported: jsonImported{
FileGroups: make(map[string][]string),
},
Exported: make(map[string][]string),
}
ctx.VisitAllModules(func(module android.Module) {
if ifg, ok := module.(*importedFileGroup); ok {
metadata.Imported.FileGroups[ifg.BaseModuleName()] = ifg.properties.Imported
}
if e, ok := module.(ExportableModule); ok {
if e.IsExported() && e.Exportable() {
for tag, files := range e.TaggedOutputs() {
// TODO(b/219846705): refactor this to a dictionary
metadata.Exported[e.Name()+":"+tag] = append(metadata.Exported[e.Name()+":"+tag], files.Strings()...)
}
}
}
})
jsonStr, err := json.Marshal(metadata)
if err != nil {
ctx.Errorf(err.Error())
}
s.generatedMetadataFile = android.PathForOutput(ctx, "multitree", "metadata.json")
android.WriteFileRule(ctx, s.generatedMetadataFile, string(jsonStr))
}
func (s *updateMetaSingleton) MakeVars(ctx android.MakeVarsContext) {
ctx.Strict("MULTITREE_METADATA", s.generatedMetadataFile.String())
}

View File

@@ -29,7 +29,6 @@ import (
"android/soong/cc" "android/soong/cc"
cc_config "android/soong/cc/config" cc_config "android/soong/cc/config"
"android/soong/fuzz" "android/soong/fuzz"
"android/soong/multitree"
"android/soong/rust/config" "android/soong/rust/config"
) )
@@ -1218,47 +1217,6 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
skipModuleList := map[string]bool{} skipModuleList := map[string]bool{}
var apiImportInfo multitree.ApiImportInfo
hasApiImportInfo := false
ctx.VisitDirectDeps(func(dep android.Module) {
if dep.Name() == "api_imports" {
apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
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 cc.ShouldUseStubForApex(ctx, dep) {
skipModuleList[depName] = true
} else {
skipModuleList[apiLibrary] = true
}
}
})
}
var transitiveAndroidMkSharedLibs []*android.DepSet[string] var transitiveAndroidMkSharedLibs []*android.DepSet[string]
var directAndroidMkSharedLibs []string var directAndroidMkSharedLibs []string
@@ -1609,13 +1567,6 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
deps := mod.deps(ctx) deps := mod.deps(ctx)
var commonDepVariations []blueprint.Variation var commonDepVariations []blueprint.Variation
apiImportInfo := cc.GetApiImports(mod, actx)
if mod.usePublicApi() || mod.useVendorApi() {
for idx, lib := range deps.SharedLibs {
deps.SharedLibs[idx] = cc.GetReplaceModuleName(lib, apiImportInfo.SharedLibs)
}
}
if ctx.Os() == android.Android { if ctx.Os() == android.Android {
deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs) deps.SharedLibs, _ = cc.FilterNdkLibs(mod, ctx.Config(), deps.SharedLibs)
} }
@@ -1708,17 +1659,9 @@ func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
variations := []blueprint.Variation{ variations := []blueprint.Variation{
{Mutator: "link", Variation: "shared"}, {Mutator: "link", Variation: "shared"},
} }
// For core variant, add a dep on the implementation (if it exists) and its .apiimport (if it exists)
// GenerateAndroidBuildActions will pick the correct impl/stub based on the api_domain boundary
if _, ok := apiImportInfo.ApexSharedLibs[name]; !ok || ctx.OtherModuleExists(name) {
cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false) cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, name, version, false)
} }
if apiLibraryName, ok := apiImportInfo.ApexSharedLibs[name]; ok {
cc.AddSharedLibDependenciesWithVersions(ctx, mod, variations, depTag, apiLibraryName, version, false)
}
}
for _, lib := range deps.WholeStaticLibs { for _, lib := range deps.WholeStaticLibs {
depTag := cc.StaticDepTag(true) depTag := cc.StaticDepTag(true)