java_sdk_library: Path extraction from deps depend on tag

Previously, the information that the java_sdk_library extracted from
its child dependencies was determined purely by the type of the
dependency and whether it had a tag of the appropriate type. The actual
tag itself was ignored. That worked but was a little fragile as it
relied on there being no overlap between the types of the dependencies
or if there was overlap on the order in which the dependencies were
processed and the dependency types were checked to ensure that the
correct information was collected.

This change makes the information that is extracted dependent on the
tag that is used. That makes the behavior much more robust and also
simplifes the follow up change which may get the stubs source and API
files from separate droidstubs invocations.

Changes:
* A func field is added to the scopeDependencyTag that is supplied with
  a dependency from which to extract the information and scopePaths
  into which the information will be stored.
* Each scopeDependencyTag instance supplies its own function.
* Various items are renamed to more closely reflect what they actually
  do. e.g. the apiFileTag is renamed to stubsSourceAndApiTag field
  because if provides access to both api file and stubs source.

Test: m checkapi
Bug: 155164730
Merged-In: I4e1861ea67f441f2948a0d7d7053ab0b1169955f
Change-Id: I4e1861ea67f441f2948a0d7d7053ab0b1169955f
(cherry picked from commit c878250d3f)
This commit is contained in:
Paul Duffin
2020-04-29 20:45:27 +01:00
parent 991f262697
commit 5fb8213db6

View File

@@ -60,6 +60,17 @@ type scopeDependencyTag struct {
blueprint.BaseDependencyTag blueprint.BaseDependencyTag
name string name string
apiScope *apiScope apiScope *apiScope
// Function for extracting appropriate path information from the dependency.
depInfoExtractor func(paths *scopePaths, dep android.Module) error
}
// Extract tag specific information from the dependency.
func (tag scopeDependencyTag) extractDepInfo(ctx android.ModuleContext, dep android.Module, paths *scopePaths) {
err := tag.depInfoExtractor(paths, dep)
if err != nil {
ctx.ModuleErrorf("has an invalid {scopeDependencyTag: %s} dependency on module %s: %s", tag.name, ctx.OtherModuleName(dep), err.Error())
}
} }
// Provides information about an api scope, e.g. public, system, test. // Provides information about an api scope, e.g. public, system, test.
@@ -88,8 +99,8 @@ type apiScope struct {
// The tag to use to depend on the stubs library module. // The tag to use to depend on the stubs library module.
stubsTag scopeDependencyTag stubsTag scopeDependencyTag
// The tag to use to depend on the stubs // The tag to use to depend on the stubs source and API module.
apiFileTag scopeDependencyTag stubsSourceAndApiTag scopeDependencyTag
// The scope specific prefix to add to the api file base of "current.txt" or "removed.txt". // The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
apiFilePrefix string apiFilePrefix string
@@ -112,14 +123,17 @@ type apiScope struct {
// Initialize a scope, creating and adding appropriate dependency tags // Initialize a scope, creating and adding appropriate dependency tags
func initApiScope(scope *apiScope) *apiScope { func initApiScope(scope *apiScope) *apiScope {
scope.fieldName = proptools.FieldNameForProperty(scope.name) name := scope.name
scope.fieldName = proptools.FieldNameForProperty(name)
scope.stubsTag = scopeDependencyTag{ scope.stubsTag = scopeDependencyTag{
name: scope.name + "-stubs", name: name + "-stubs",
apiScope: scope, apiScope: scope,
depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency,
} }
scope.apiFileTag = scopeDependencyTag{ scope.stubsSourceAndApiTag = scopeDependencyTag{
name: scope.name + "-api", name: name + "-stubs-source-and-api",
apiScope: scope, apiScope: scope,
depInfoExtractor: (*scopePaths).extractStubsSourceAndApiInfoFromApiStubsProvider,
} }
return scope return scope
} }
@@ -128,7 +142,7 @@ func (scope *apiScope) stubsModuleName(baseName string) string {
return baseName + sdkStubsLibrarySuffix + scope.moduleSuffix return baseName + sdkStubsLibrarySuffix + scope.moduleSuffix
} }
func (scope *apiScope) docsModuleName(baseName string) string { func (scope *apiScope) stubsSourceModuleName(baseName string) string {
return baseName + sdkStubsSourceSuffix + scope.moduleSuffix return baseName + sdkStubsSourceSuffix + scope.moduleSuffix
} }
@@ -349,6 +363,27 @@ type scopePaths struct {
stubsSrcJar android.Path stubsSrcJar android.Path
} }
func (paths *scopePaths) extractStubsLibraryInfoFromDependency(dep android.Module) error {
if lib, ok := dep.(Dependency); ok {
paths.stubsHeaderPath = lib.HeaderJars()
paths.stubsImplPath = lib.ImplementationJars()
return nil
} else {
return fmt.Errorf("expected module that implements Dependency, e.g. java_library")
}
}
func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(dep android.Module) error {
if provider, ok := dep.(ApiStubsProvider); ok {
paths.currentApiFilePath = provider.ApiFilePath()
paths.removedApiFilePath = provider.RemovedApiFilePath()
paths.stubsSrcJar = provider.StubsSrcJar()
return nil
} else {
return fmt.Errorf("expected module that implements ApiStubsProvider, e.g. droidstubs")
}
}
// Common code between sdk library and sdk library import // Common code between sdk library and sdk library import
type commonToSdkLibraryAndImport struct { type commonToSdkLibraryAndImport struct {
scopePaths map[*apiScope]*scopePaths scopePaths map[*apiScope]*scopePaths
@@ -447,8 +482,8 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies to the stubs library // Add dependencies to the stubs library
ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope)) ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
// And the api file // And the stubs source and api files
ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.docsName(apiScope)) ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceName(apiScope))
} }
if !proptools.Bool(module.sdkLibraryProperties.Api_only) { if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
@@ -469,27 +504,16 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext)
// When this java_sdk_library is depended upon from others via "libs" property, // 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. // the recorded paths will be returned depending on the link type of the caller.
ctx.VisitDirectDeps(func(to android.Module) { ctx.VisitDirectDeps(func(to android.Module) {
otherName := ctx.OtherModuleName(to)
tag := ctx.OtherModuleDependencyTag(to) tag := ctx.OtherModuleDependencyTag(to)
if lib, ok := to.(Dependency); ok { // Extract information from any of the scope specific dependencies.
if scopeTag, ok := tag.(scopeDependencyTag); ok { if scopeTag, ok := tag.(scopeDependencyTag); ok {
apiScope := scopeTag.apiScope apiScope := scopeTag.apiScope
scopePaths := module.getScopePaths(apiScope) scopePaths := module.getScopePaths(apiScope)
scopePaths.stubsHeaderPath = lib.HeaderJars()
scopePaths.stubsImplPath = lib.ImplementationJars() // 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)
if doc, ok := to.(ApiStubsProvider); ok {
if scopeTag, ok := tag.(scopeDependencyTag); ok {
apiScope := scopeTag.apiScope
scopePaths := module.getScopePaths(apiScope)
scopePaths.currentApiFilePath = doc.ApiFilePath()
scopePaths.removedApiFilePath = doc.RemovedApiFilePath()
scopePaths.stubsSrcJar = doc.StubsSrcJar()
} else {
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
}
} }
}) })
} }
@@ -504,14 +528,15 @@ func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
return entriesList return entriesList
} }
// Module name of the stubs library // Name of the java_library module that compiles the stubs source.
func (module *SdkLibrary) stubsName(apiScope *apiScope) string { func (module *SdkLibrary) stubsName(apiScope *apiScope) string {
return apiScope.stubsModuleName(module.BaseModuleName()) return apiScope.stubsModuleName(module.BaseModuleName())
} }
// Module name of the docs // // Name of the droidstubs module that generates the stubs source and
func (module *SdkLibrary) docsName(apiScope *apiScope) string { // generates/checks the API.
return apiScope.docsModuleName(module.BaseModuleName()) func (module *SdkLibrary) stubsSourceName(apiScope *apiScope) string {
return apiScope.stubsSourceModuleName(module.BaseModuleName())
} }
// Module name of the runtime implementation library // Module name of the runtime implementation library
@@ -597,7 +622,7 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
props.Visibility = visibility props.Visibility = visibility
// sources are generated from the droiddoc // sources are generated from the droiddoc
props.Srcs = []string{":" + module.docsName(apiScope)} props.Srcs = []string{":" + module.stubsSourceName(apiScope)}
sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope) sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion) props.Sdk_version = proptools.StringPtr(sdkVersion)
props.System_modules = module.Library.Module.deviceProperties.System_modules props.System_modules = module.Library.Module.deviceProperties.System_modules
@@ -633,8 +658,8 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
} }
// Creates a droidstubs module that creates stubs source files from the given full source // Creates a droidstubs module that creates stubs source files from the given full source
// files // files and also updates and checks the API specification files.
func (module *SdkLibrary) createStubsSources(mctx android.DefaultableHookContext, apiScope *apiScope) { func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookContext, apiScope *apiScope) {
props := struct { props := struct {
Name *string Name *string
Visibility []string Visibility []string
@@ -670,7 +695,7 @@ func (module *SdkLibrary) createStubsSources(mctx android.DefaultableHookContext
// * system_modules // * system_modules
// * libs (static_libs/libs) // * libs (static_libs/libs)
props.Name = proptools.StringPtr(module.docsName(apiScope)) props.Name = proptools.StringPtr(module.stubsSourceName(apiScope))
// If stubs_source_visibility is not set then the created module will use the // If stubs_source_visibility is not set then the created module will use the
// visibility of this module. // visibility of this module.
@@ -934,7 +959,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
for _, scope := range generatedScopes { for _, scope := range generatedScopes {
module.createStubsLibrary(mctx, scope) module.createStubsLibrary(mctx, scope)
module.createStubsSources(mctx, scope) module.createStubsSourcesAndApi(mctx, scope)
} }
if !proptools.Bool(module.sdkLibraryProperties.Api_only) { if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
@@ -1001,7 +1026,7 @@ type sdkLibraryScopeProperties struct {
// List of shared java libs that this module has dependencies to // List of shared java libs that this module has dependencies to
Libs []string Libs []string
// The stub sources. // The stubs source.
Stub_srcs []string `android:"path"` Stub_srcs []string `android:"path"`
// The current.txt // The current.txt
@@ -1161,7 +1186,7 @@ func (module *sdkLibraryImport) createPrebuiltStubsSources(mctx android.Defaulta
Name *string Name *string
Srcs []string Srcs []string
}{} }{}
props.Name = proptools.StringPtr(apiScope.docsModuleName(module.BaseModuleName())) props.Name = proptools.StringPtr(apiScope.stubsSourceModuleName(module.BaseModuleName()))
props.Srcs = scopeProperties.Stub_srcs props.Srcs = scopeProperties.Stub_srcs
mctx.CreateModule(PrebuiltStubsSourcesFactory, &props) mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
} }