Merge "Remove duplicate component from sdk snapshot"
This commit is contained in:
commit
a8de9fb2ae
5 changed files with 195 additions and 45 deletions
|
@ -38,6 +38,36 @@ type RequiredSdks interface {
|
|||
type sdkAwareWithoutModule interface {
|
||||
RequiredSdks
|
||||
|
||||
// SdkMemberComponentName will return the name to use for a component of this module based on the
|
||||
// base name of this module.
|
||||
//
|
||||
// The baseName is the name returned by ModuleBase.BaseModuleName(), i.e. the name specified in
|
||||
// the name property in the .bp file so will not include the prebuilt_ prefix.
|
||||
//
|
||||
// The componentNameCreator is a func for creating the name of a component from the base name of
|
||||
// the module, e.g. it could just append ".component" to the name passed in.
|
||||
//
|
||||
// This is intended to be called by prebuilt modules that create component models. It is because
|
||||
// prebuilt module base names come in a variety of different forms:
|
||||
// * unversioned - this is the same as the source module.
|
||||
// * internal to an sdk - this is the unversioned name prefixed by the base name of the sdk
|
||||
// module.
|
||||
// * versioned - this is the same as the internal with the addition of an "@<version>" suffix.
|
||||
//
|
||||
// While this can be called from a source module in that case it will behave the same way as the
|
||||
// unversioned name and return the result of calling the componentNameCreator func on the supplied
|
||||
// base name.
|
||||
//
|
||||
// e.g. Assuming the componentNameCreator func simply appends ".component" to the name passed in
|
||||
// then this will work as follows:
|
||||
// * An unversioned name of "foo" will return "foo.component".
|
||||
// * An internal to the sdk name of "sdk_foo" will return "sdk_foo.component".
|
||||
// * A versioned name of "sdk_foo@current" will return "sdk_foo.component@current".
|
||||
//
|
||||
// Note that in the latter case the ".component" suffix is added before the version. Adding it
|
||||
// after would change the version.
|
||||
SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string
|
||||
|
||||
sdkBase() *SdkBase
|
||||
MakeMemberOf(sdk SdkRef)
|
||||
IsInAnySdk() bool
|
||||
|
@ -135,6 +165,18 @@ func (s *SdkBase) sdkBase() *SdkBase {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *SdkBase) SdkMemberComponentName(baseName string, componentNameCreator func(string) string) string {
|
||||
if s.MemberName() == "" {
|
||||
return componentNameCreator(baseName)
|
||||
} else {
|
||||
index := strings.LastIndex(baseName, "@")
|
||||
unversionedName := baseName[:index]
|
||||
unversionedComponentName := componentNameCreator(unversionedName)
|
||||
versionSuffix := baseName[index:]
|
||||
return unversionedComponentName + versionSuffix
|
||||
}
|
||||
}
|
||||
|
||||
// MakeMemberOf sets this module to be a member of a specific SDK
|
||||
func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
|
||||
s.properties.ContainingSdk = &sdk
|
||||
|
@ -659,3 +701,30 @@ type SdkMemberContext interface {
|
|||
// into which to copy the prebuilt files.
|
||||
Name() string
|
||||
}
|
||||
|
||||
// ExportedComponentsInfo contains information about the components that this module exports to an
|
||||
// sdk snapshot.
|
||||
//
|
||||
// A component of a module is a child module that the module creates and which forms an integral
|
||||
// part of the functionality that the creating module provides. A component module is essentially
|
||||
// owned by its creator and is tightly coupled to the creator and other components.
|
||||
//
|
||||
// e.g. the child modules created by prebuilt_apis are not components because they are not tightly
|
||||
// coupled to the prebuilt_apis module. Once they are created the prebuilt_apis ignores them. The
|
||||
// child impl and stub library created by java_sdk_library (and corresponding import) are components
|
||||
// because the creating module depends upon them in order to provide some of its own functionality.
|
||||
//
|
||||
// A component is exported if it is part of an sdk snapshot. e.g. The xml and impl child modules are
|
||||
// components but they are not exported as they are not part of an sdk snapshot.
|
||||
//
|
||||
// This information is used by the sdk snapshot generation code to ensure that it does not create
|
||||
// an sdk snapshot that contains a declaration of the component module and the module that creates
|
||||
// it as that would result in duplicate modules when attempting to use the snapshot. e.g. a snapshot
|
||||
// that included the java_sdk_library_import "foo" and also a java_import "foo.stubs" would fail
|
||||
// as there would be two modules called "foo.stubs".
|
||||
type ExportedComponentsInfo struct {
|
||||
// The names of the exported components.
|
||||
Components []string
|
||||
}
|
||||
|
||||
var ExportedComponentsInfoProvider = blueprint.NewProvider(ExportedComponentsInfo{})
|
||||
|
|
|
@ -634,7 +634,7 @@ type commonToSdkLibraryAndImportProperties struct {
|
|||
// commonSdkLibraryAndImportModule defines the interface that must be provided by a module that
|
||||
// embeds the commonToSdkLibraryAndImport struct.
|
||||
type commonSdkLibraryAndImportModule interface {
|
||||
android.Module
|
||||
android.SdkAware
|
||||
|
||||
BaseModuleName() string
|
||||
}
|
||||
|
@ -700,13 +700,19 @@ func (c *commonToSdkLibraryAndImport) xmlPermissionsModuleName() string {
|
|||
|
||||
// Name of the java_library module that compiles the stubs source.
|
||||
func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope) string {
|
||||
return c.namingScheme.stubsLibraryModuleName(apiScope, c.module.BaseModuleName())
|
||||
baseName := c.module.BaseModuleName()
|
||||
return c.module.SdkMemberComponentName(baseName, func(name string) string {
|
||||
return c.namingScheme.stubsLibraryModuleName(apiScope, name)
|
||||
})
|
||||
}
|
||||
|
||||
// Name of the droidstubs module that generates the stubs source and may also
|
||||
// generate/check the API.
|
||||
func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
|
||||
return c.namingScheme.stubsSourceModuleName(apiScope, c.module.BaseModuleName())
|
||||
baseName := c.module.BaseModuleName()
|
||||
return c.module.SdkMemberComponentName(baseName, func(name string) string {
|
||||
return c.namingScheme.stubsSourceModuleName(apiScope, name)
|
||||
})
|
||||
}
|
||||
|
||||
// The component names for different outputs of the java_sdk_library.
|
||||
|
@ -1170,6 +1176,10 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
|
|||
module.Library.GenerateAndroidBuildActions(ctx)
|
||||
}
|
||||
|
||||
// Collate the components exported by this module. All scope specific modules are exported but
|
||||
// the impl and xml component modules are not.
|
||||
exportedComponents := map[string]struct{}{}
|
||||
|
||||
// Record the paths to the header jars of the library (stubs and impl).
|
||||
// When this java_sdk_library is depended upon from others via "libs" property,
|
||||
// the recorded paths will be returned depending on the link type of the caller.
|
||||
|
@ -1184,8 +1194,14 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
|
|||
// Extract information from the dependency. The exact information extracted
|
||||
// is determined by the nature of the dependency which is determined by the tag.
|
||||
scopeTag.extractDepInfo(ctx, to, scopePaths)
|
||||
|
||||
exportedComponents[ctx.OtherModuleName(to)] = struct{}{}
|
||||
}
|
||||
})
|
||||
|
||||
// Make the set of components exported by this module available for use elsewhere.
|
||||
exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedStringKeys(exportedComponents)}
|
||||
ctx.SetProvider(android.ExportedComponentsInfoProvider, exportedComponentInfo)
|
||||
}
|
||||
|
||||
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
|
||||
|
|
|
@ -110,7 +110,7 @@ func TestJavaSdkLibrary(t *testing.T) {
|
|||
`)
|
||||
|
||||
// check the existence of the internal modules
|
||||
result.ModuleForTests("foo", "android_common")
|
||||
foo := result.ModuleForTests("foo", "android_common")
|
||||
result.ModuleForTests(apiScopePublic.stubsLibraryModuleName("foo"), "android_common")
|
||||
result.ModuleForTests(apiScopeSystem.stubsLibraryModuleName("foo"), "android_common")
|
||||
result.ModuleForTests(apiScopeTest.stubsLibraryModuleName("foo"), "android_common")
|
||||
|
@ -122,6 +122,17 @@ func TestJavaSdkLibrary(t *testing.T) {
|
|||
result.ModuleForTests("foo.api.system.28", "")
|
||||
result.ModuleForTests("foo.api.test.28", "")
|
||||
|
||||
exportedComponentsInfo := result.ModuleProvider(foo.Module(), ExportedComponentsInfoProvider).(ExportedComponentsInfo)
|
||||
expectedFooExportedComponents := []string{
|
||||
"foo.stubs",
|
||||
"foo.stubs.source",
|
||||
"foo.stubs.source.system",
|
||||
"foo.stubs.source.test",
|
||||
"foo.stubs.system",
|
||||
"foo.stubs.test",
|
||||
}
|
||||
android.AssertArrayString(t, "foo exported components", expectedFooExportedComponents, exportedComponentsInfo.Components)
|
||||
|
||||
bazJavac := result.ModuleForTests("baz", "android_common").Rule("javac")
|
||||
// tests if baz is actually linked to the stubs lib
|
||||
android.AssertStringDoesContain(t, "baz javac classpath", bazJavac.Args["classpath"], "foo.stubs.system.jar")
|
||||
|
|
|
@ -722,14 +722,6 @@ java_import {
|
|||
jars: ["java/system-module.jar"],
|
||||
}
|
||||
|
||||
java_import {
|
||||
name: "mysdk_myjavalib.stubs",
|
||||
prefer: false,
|
||||
visibility: ["//visibility:private"],
|
||||
apex_available: ["//apex_available:platform"],
|
||||
jars: ["java/myjavalib.stubs.jar"],
|
||||
}
|
||||
|
||||
java_sdk_library_import {
|
||||
name: "myjavalib",
|
||||
prefer: false,
|
||||
|
@ -752,7 +744,7 @@ java_system_modules_import {
|
|||
libs: [
|
||||
"mysdk_system-module",
|
||||
"exported-system-module",
|
||||
"mysdk_myjavalib.stubs",
|
||||
"myjavalib.stubs",
|
||||
],
|
||||
}
|
||||
`),
|
||||
|
@ -775,14 +767,6 @@ java_import {
|
|||
jars: ["java/system-module.jar"],
|
||||
}
|
||||
|
||||
java_import {
|
||||
name: "mysdk_myjavalib.stubs@current",
|
||||
sdk_member_name: "myjavalib.stubs",
|
||||
visibility: ["//visibility:private"],
|
||||
apex_available: ["//apex_available:platform"],
|
||||
jars: ["java/myjavalib.stubs.jar"],
|
||||
}
|
||||
|
||||
java_sdk_library_import {
|
||||
name: "mysdk_myjavalib@current",
|
||||
sdk_member_name: "myjavalib",
|
||||
|
@ -820,7 +804,6 @@ sdk_snapshot {
|
|||
checkAllCopyRules(`
|
||||
.intermediates/exported-system-module/android_common/turbine-combined/exported-system-module.jar -> java/exported-system-module.jar
|
||||
.intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar
|
||||
.intermediates/myjavalib.stubs/android_common/turbine-combined/myjavalib.stubs.jar -> java/myjavalib.stubs.jar
|
||||
.intermediates/myjavalib.stubs/android_common/javac/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
|
||||
.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
|
||||
.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
|
||||
|
@ -1153,10 +1136,10 @@ sdk_snapshot {
|
|||
".intermediates/mysdk/common_os/tmp/sdk_library/test/myjavalib_stub_sources.zip",
|
||||
),
|
||||
snapshotTestChecker(checkSnapshotWithoutSource, func(t *testing.T, result *android.TestResult) {
|
||||
// Show that the existing behavior is incorrect as the suffix for the child modules is added
|
||||
// to the version not before it.
|
||||
result.Module("mysdk_myjavalib@current.stubs", "android_common")
|
||||
result.Module("mysdk_myjavalib@current.stubs.source", "android_common")
|
||||
// Make sure that the name of the child modules created by a versioned java_sdk_library_import
|
||||
// module is correct, i.e. the suffix is added before the version and not after.
|
||||
result.Module("mysdk_myjavalib.stubs@current", "android_common")
|
||||
result.Module("mysdk_myjavalib.stubs.source@current", "android_common")
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
|
109
sdk/update.go
109
sdk/update.go
|
@ -22,7 +22,6 @@ import (
|
|||
|
||||
"android/soong/apex"
|
||||
"android/soong/cc"
|
||||
|
||||
"github.com/google/blueprint"
|
||||
"github.com/google/blueprint/proptools"
|
||||
|
||||
|
@ -148,8 +147,8 @@ func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderC
|
|||
|
||||
// Collect all the members.
|
||||
//
|
||||
// Updates the sdk module with a list of sdkMemberVariantDeps and details as to which multilibs
|
||||
// (32/64/both) are used by this sdk variant.
|
||||
// Updates the sdk module with a list of sdkMemberVariantDep instances and details as to which
|
||||
// multilibs (32/64/both) are used by this sdk variant.
|
||||
func (s *sdk) collectMembers(ctx android.ModuleContext) {
|
||||
s.multilibUsages = multilibNone
|
||||
ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
|
||||
|
@ -165,8 +164,15 @@ func (s *sdk) collectMembers(ctx android.ModuleContext) {
|
|||
// Keep track of which multilib variants are used by the sdk.
|
||||
s.multilibUsages = s.multilibUsages.addArchType(child.Target().Arch.ArchType)
|
||||
|
||||
var exportedComponentsInfo android.ExportedComponentsInfo
|
||||
if ctx.OtherModuleHasProvider(child, android.ExportedComponentsInfoProvider) {
|
||||
exportedComponentsInfo = ctx.OtherModuleProvider(child, android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo)
|
||||
}
|
||||
|
||||
export := memberTag.ExportMember()
|
||||
s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{s, memberType, child.(android.SdkAware), export})
|
||||
s.memberVariantDeps = append(s.memberVariantDeps, sdkMemberVariantDep{
|
||||
s, memberType, child.(android.SdkAware), export, exportedComponentsInfo,
|
||||
})
|
||||
|
||||
// Recurse down into the member's dependencies as it may have dependencies that need to be
|
||||
// automatically added to the sdk.
|
||||
|
@ -253,26 +259,41 @@ func versionedSdkMemberName(ctx android.ModuleContext, memberName string, versio
|
|||
// the contents (header files, stub libraries, etc) into the zip file.
|
||||
func (s *sdk) buildSnapshot(ctx android.ModuleContext, sdkVariants []*sdk) android.OutputPath {
|
||||
|
||||
allMembersByName := make(map[string]struct{})
|
||||
exportedMembersByName := make(map[string]struct{})
|
||||
// Aggregate all the sdkMemberVariantDep instances from all the sdk variants.
|
||||
hasLicenses := false
|
||||
var memberVariantDeps []sdkMemberVariantDep
|
||||
for _, sdkVariant := range sdkVariants {
|
||||
memberVariantDeps = append(memberVariantDeps, sdkVariant.memberVariantDeps...)
|
||||
}
|
||||
|
||||
// Record the names of all the members, both explicitly specified and implicitly
|
||||
// included.
|
||||
for _, memberVariantDep := range sdkVariant.memberVariantDeps {
|
||||
name := memberVariantDep.variant.Name()
|
||||
allMembersByName[name] = struct{}{}
|
||||
// Filter out any sdkMemberVariantDep that is a component of another.
|
||||
memberVariantDeps = filterOutComponents(ctx, memberVariantDeps)
|
||||
|
||||
if memberVariantDep.export {
|
||||
exportedMembersByName[name] = struct{}{}
|
||||
}
|
||||
// Record the names of all the members, both explicitly specified and implicitly
|
||||
// included.
|
||||
allMembersByName := make(map[string]struct{})
|
||||
exportedMembersByName := make(map[string]struct{})
|
||||
|
||||
if memberVariantDep.memberType == android.LicenseModuleSdkMemberType {
|
||||
hasLicenses = true
|
||||
}
|
||||
addMember := func(name string, export bool) {
|
||||
allMembersByName[name] = struct{}{}
|
||||
if export {
|
||||
exportedMembersByName[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
for _, memberVariantDep := range memberVariantDeps {
|
||||
name := memberVariantDep.variant.Name()
|
||||
export := memberVariantDep.export
|
||||
|
||||
addMember(name, export)
|
||||
|
||||
// Add any components provided by the module.
|
||||
for _, component := range memberVariantDep.exportedComponentsInfo.Components {
|
||||
addMember(component, export)
|
||||
}
|
||||
|
||||
if memberVariantDep.memberType == android.LicenseModuleSdkMemberType {
|
||||
hasLicenses = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,6 +452,47 @@ be unnecessary as every module in the sdk already has its own licenses property.
|
|||
return outputZipFile
|
||||
}
|
||||
|
||||
// filterOutComponents removes any item from the deps list that is a component of another item in
|
||||
// the deps list, e.g. if the deps list contains "foo" and "foo.stubs" which is component of "foo"
|
||||
// then it will remove "foo.stubs" from the deps.
|
||||
func filterOutComponents(ctx android.ModuleContext, deps []sdkMemberVariantDep) []sdkMemberVariantDep {
|
||||
// Collate the set of components that all the modules added to the sdk provide.
|
||||
components := map[string]*sdkMemberVariantDep{}
|
||||
for i, _ := range deps {
|
||||
dep := &deps[i]
|
||||
for _, c := range dep.exportedComponentsInfo.Components {
|
||||
components[c] = dep
|
||||
}
|
||||
}
|
||||
|
||||
// If no module provides components then return the input deps unfiltered.
|
||||
if len(components) == 0 {
|
||||
return deps
|
||||
}
|
||||
|
||||
filtered := make([]sdkMemberVariantDep, 0, len(deps))
|
||||
for _, dep := range deps {
|
||||
name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(dep.variant))
|
||||
if owner, ok := components[name]; ok {
|
||||
// This is a component of another module that is a member of the sdk.
|
||||
|
||||
// If the component is exported but the owning module is not then the configuration is not
|
||||
// supported.
|
||||
if dep.export && !owner.export {
|
||||
ctx.ModuleErrorf("Module %s is internal to the SDK but provides component %s which is used outside the SDK")
|
||||
continue
|
||||
}
|
||||
|
||||
// This module must not be added to the list of members of the sdk as that would result in a
|
||||
// duplicate module in the sdk snapshot.
|
||||
continue
|
||||
}
|
||||
|
||||
filtered = append(filtered, dep)
|
||||
}
|
||||
return filtered
|
||||
}
|
||||
|
||||
// addSnapshotModule adds the sdk_snapshot/module_exports_snapshot module to the builder.
|
||||
func (s *sdk) addSnapshotModule(ctx android.ModuleContext, builder *snapshotBuilder, sdkVariants []*sdk, memberVariantDeps []sdkMemberVariantDep) {
|
||||
bpFile := builder.bpFile
|
||||
|
@ -1152,9 +1214,18 @@ func addSdkMemberPropertiesToSet(ctx *memberContext, memberProperties android.Sd
|
|||
type sdkMemberVariantDep struct {
|
||||
// The sdk variant that depends (possibly indirectly) on the member variant.
|
||||
sdkVariant *sdk
|
||||
|
||||
// The type of sdk member the variant is to be treated as.
|
||||
memberType android.SdkMemberType
|
||||
variant android.SdkAware
|
||||
export bool
|
||||
|
||||
// The variant that is added to the sdk.
|
||||
variant android.SdkAware
|
||||
|
||||
// True if the member should be exported, i.e. accessible, from outside the sdk.
|
||||
export bool
|
||||
|
||||
// The names of additional component modules provided by the variant.
|
||||
exportedComponentsInfo android.ExportedComponentsInfo
|
||||
}
|
||||
|
||||
var _ android.SdkMember = (*sdkMember)(nil)
|
||||
|
|
Loading…
Reference in a new issue