Parameterize java_sdk_library by api scope
The java_sdk_library duplicated a lot of code related to api scopes and
also did a lot of switching on apiScope. This change eliminates that
duplication and switching by converting apiScope from an enum to a
structure containing api scope specific information.
It associates dependencies with corresponding scope by using a
scopeDependencyTag that contains a reference to the associated
apiScope.
Tested by:
1) Running the command below without the changes.
2) 'mv out/dist/apistubs $ANDROID_BUILD_TOP'
3) Applying these changes.
4) Running the command again.
5) Verifying that the out/dist/apistubs was identical to before the
change using 'meld out/dist/apistubs $ANDROID_BUILD_TOP/apistubs'
Bug: 148080325
Test: m TARGET_PRODUCT=sdk TARGET_BUILD_VARIANT=userdebug dist sdk
m droid
Change-Id: I0de3268b12254122e94ca83d09309b06ca2f9dbe
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 530e02c..0ef0f23 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+
"fmt"
"io"
"path"
@@ -24,6 +25,7 @@
"strings"
"sync"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -53,21 +55,96 @@
`</permissions>\n`
)
+// A tag to associated a dependency with a specific api scope.
+type scopeDependencyTag struct {
+ blueprint.BaseDependencyTag
+ name string
+ apiScope *apiScope
+}
+
+// Provides information about an api scope, e.g. public, system, test.
+type apiScope struct {
+ // The name of the api scope, e.g. public, system, test
+ name string
+
+ // The tag to use to depend on the stubs library module.
+ stubsTag scopeDependencyTag
+
+ // The tag to use to depend on the stubs
+ apiFileTag scopeDependencyTag
+
+ // The scope specific prefix to add to the api file base of "current.txt" or "removed.txt".
+ apiFilePrefix string
+
+ // The scope specific prefix to add to the sdk library module name to construct a scope specific
+ // module name.
+ moduleSuffix string
+
+ // The suffix to add to the make variable that references the location of the api file.
+ apiFileMakeVariableSuffix string
+
+ // SDK version that the stubs library is built against. Note that this is always
+ // *current. Older stubs library built with a numbered SDK version is created from
+ // the prebuilt jar.
+ sdkVersion string
+}
+
+// Initialize a scope, creating and adding appropriate dependency tags
+func initApiScope(scope *apiScope) *apiScope {
+ //apiScope := &scope
+ scope.stubsTag = scopeDependencyTag{
+ name: scope.name + "-stubs",
+ apiScope: scope,
+ }
+ scope.apiFileTag = scopeDependencyTag{
+ name: scope.name + "-api",
+ apiScope: scope,
+ }
+ return scope
+}
+
+func (scope *apiScope) stubsModuleName(baseName string) string {
+ return baseName + sdkStubsLibrarySuffix + scope.moduleSuffix
+}
+
+func (scope *apiScope) docsModuleName(baseName string) string {
+ return baseName + sdkDocsSuffix + scope.moduleSuffix
+}
+
+type apiScopes []*apiScope
+
+func (scopes apiScopes) Strings(accessor func(*apiScope) string) []string {
+ var list []string
+ for _, scope := range scopes {
+ list = append(list, accessor(scope))
+ }
+ return list
+}
+
var (
- publicApiStubsTag = dependencyTag{name: "public"}
- systemApiStubsTag = dependencyTag{name: "system"}
- testApiStubsTag = dependencyTag{name: "test"}
- publicApiFileTag = dependencyTag{name: "publicApi"}
- systemApiFileTag = dependencyTag{name: "systemApi"}
- testApiFileTag = dependencyTag{name: "testApi"}
-)
-
-type apiScope int
-
-const (
- apiScopePublic apiScope = iota
- apiScopeSystem
- apiScopeTest
+ apiScopePublic = initApiScope(&apiScope{
+ name: "public",
+ sdkVersion: "current",
+ })
+ apiScopeSystem = initApiScope(&apiScope{
+ name: "system",
+ apiFilePrefix: "system-",
+ moduleSuffix: sdkSystemApiSuffix,
+ apiFileMakeVariableSuffix: "_SYSTEM",
+ sdkVersion: "system_current",
+ })
+ apiScopeTest = initApiScope(&apiScope{
+ name: "test",
+ apiFilePrefix: "test-",
+ moduleSuffix: sdkTestApiSuffix,
+ apiFileMakeVariableSuffix: "_TEST",
+ sdkVersion: "test_current",
+ })
+ allApiScopes = apiScopes{
+ apiScopePublic,
+ apiScopeSystem,
+ apiScopeTest,
+ }
)
var (
@@ -142,22 +219,18 @@
//Html_doc *bool
}
+type scopePaths struct {
+ stubsHeaderPath android.Paths
+ stubsImplPath android.Paths
+ apiFilePath android.Path
+}
+
type SdkLibrary struct {
Library
sdkLibraryProperties sdkLibraryProperties
- publicApiStubsPath android.Paths
- systemApiStubsPath android.Paths
- testApiStubsPath android.Paths
-
- publicApiStubsImplPath android.Paths
- systemApiStubsImplPath android.Paths
- testApiStubsImplPath android.Paths
-
- publicApiFilePath android.Path
- systemApiFilePath android.Path
- testApiFilePath android.Path
+ scopePaths map[*apiScope]*scopePaths
permissionsFile android.Path
}
@@ -165,21 +238,36 @@
var _ Dependency = (*SdkLibrary)(nil)
var _ SdkLibraryDependency = (*SdkLibrary)(nil)
+func (module *SdkLibrary) getActiveApiScopes() apiScopes {
+ if module.sdkLibraryProperties.Has_system_and_test_apis {
+ return allApiScopes
+ } else {
+ return apiScopes{apiScopePublic}
+ }
+}
+
+func (module *SdkLibrary) getScopePaths(scope *apiScope) *scopePaths {
+ if module.scopePaths == nil {
+ module.scopePaths = make(map[*apiScope]*scopePaths)
+ }
+ paths := module.scopePaths[scope]
+ if paths == nil {
+ paths = &scopePaths{}
+ module.scopePaths[scope] = paths
+ }
+
+ return paths
+}
+
func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks()
- // Add dependencies to the stubs library
- if useBuiltStubs {
- ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic))
- }
- ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic))
-
- if module.sdkLibraryProperties.Has_system_and_test_apis {
+ for _, apiScope := range module.getActiveApiScopes() {
+ // Add dependencies to the stubs library
if useBuiltStubs {
- ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem))
- ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest))
+ ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsName(apiScope))
}
- ctx.AddVariationDependencies(nil, systemApiFileTag, module.docsName(apiScopeSystem))
- ctx.AddVariationDependencies(nil, testApiFileTag, module.docsName(apiScopeTest))
+
+ ctx.AddVariationDependencies(nil, apiScope.apiFileTag, module.docsName(apiScope))
}
module.Library.deps(ctx)
@@ -194,34 +282,26 @@
module.buildPermissionsFile(ctx)
// Record the paths to the header jars of the library (stubs and impl).
- // When this java_sdk_library is dependened 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.
ctx.VisitDirectDeps(func(to android.Module) {
otherName := ctx.OtherModuleName(to)
tag := ctx.OtherModuleDependencyTag(to)
if lib, ok := to.(Dependency); ok {
- switch tag {
- case publicApiStubsTag:
- module.publicApiStubsPath = lib.HeaderJars()
- module.publicApiStubsImplPath = lib.ImplementationJars()
- case systemApiStubsTag:
- module.systemApiStubsPath = lib.HeaderJars()
- module.systemApiStubsImplPath = lib.ImplementationJars()
- case testApiStubsTag:
- module.testApiStubsPath = lib.HeaderJars()
- module.testApiStubsImplPath = lib.ImplementationJars()
+ if scopeTag, ok := tag.(scopeDependencyTag); ok {
+ apiScope := scopeTag.apiScope
+ scopePaths := module.getScopePaths(apiScope)
+ scopePaths.stubsHeaderPath = lib.HeaderJars()
+ scopePaths.stubsImplPath = lib.ImplementationJars()
}
}
if doc, ok := to.(ApiFilePath); ok {
- switch tag {
- case publicApiFileTag:
- module.publicApiFilePath = doc.ApiFilePath()
- case systemApiFileTag:
- module.systemApiFilePath = doc.ApiFilePath()
- case testApiFileTag:
- module.testApiFilePath = doc.ApiFilePath()
- default:
+ if scopeTag, ok := tag.(scopeDependencyTag); ok {
+ apiScope := scopeTag.apiScope
+ scopePaths := module.getScopePaths(apiScope)
+ scopePaths.apiFilePath = doc.ApiFilePath()
+ } else {
ctx.ModuleErrorf("depends on module %q of unknown tag %q", otherName, tag)
}
}
@@ -273,42 +353,23 @@
owner = "android"
}
}
- // Create dist rules to install the stubs libs to the dist dir
- if len(module.publicApiStubsPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.publicApiStubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, "public",
- module.BaseModuleName()+".jar")+")")
- }
- if len(module.systemApiStubsPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.systemApiStubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, "system",
- module.BaseModuleName()+".jar")+")")
- }
- if len(module.testApiStubsPath) == 1 {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.testApiStubsImplPath.Strings()[0]+
- ":"+path.Join("apistubs", owner, "test",
- module.BaseModuleName()+".jar")+")")
- }
- if module.publicApiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.publicApiFilePath.String()+
- ":"+path.Join("apistubs", owner, "public", "api",
- module.BaseModuleName()+".txt")+")")
- }
- if module.systemApiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.systemApiFilePath.String()+
- ":"+path.Join("apistubs", owner, "system", "api",
- module.BaseModuleName()+".txt")+")")
- }
- if module.testApiFilePath != nil {
- fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
- module.testApiFilePath.String()+
- ":"+path.Join("apistubs", owner, "test", "api",
- module.BaseModuleName()+".txt")+")")
+
+ // Create dist rules to install the stubs libs and api files to the dist dir
+ for _, apiScope := range module.getActiveApiScopes() {
+ if scopePaths, ok := module.scopePaths[apiScope]; ok {
+ if len(scopePaths.stubsHeaderPath) == 1 {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ scopePaths.stubsImplPath.Strings()[0]+
+ ":"+path.Join("apistubs", owner, apiScope.name,
+ module.BaseModuleName()+".jar")+")")
+ }
+ if scopePaths.apiFilePath != nil {
+ fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+
+ scopePaths.apiFilePath.String()+
+ ":"+path.Join("apistubs", owner, apiScope.name, "api",
+ module.BaseModuleName()+".txt")+")")
+ }
+ }
}
}
},
@@ -317,27 +378,13 @@
}
// Module name of the stubs library
-func (module *SdkLibrary) stubsName(apiScope apiScope) string {
- stubsName := module.BaseModuleName() + sdkStubsLibrarySuffix
- switch apiScope {
- case apiScopeSystem:
- stubsName = stubsName + sdkSystemApiSuffix
- case apiScopeTest:
- stubsName = stubsName + sdkTestApiSuffix
- }
- return stubsName
+func (module *SdkLibrary) stubsName(apiScope *apiScope) string {
+ return apiScope.stubsModuleName(module.BaseModuleName())
}
// Module name of the docs
-func (module *SdkLibrary) docsName(apiScope apiScope) string {
- docsName := module.BaseModuleName() + sdkDocsSuffix
- switch apiScope {
- case apiScopeSystem:
- docsName = docsName + sdkSystemApiSuffix
- case apiScopeTest:
- docsName = docsName + sdkTestApiSuffix
- }
- return docsName
+func (module *SdkLibrary) docsName(apiScope *apiScope) string {
+ return apiScope.docsModuleName(module.BaseModuleName())
}
// Module name of the runtime implementation library
@@ -371,28 +418,12 @@
return module.BaseModuleName() + sdkXmlFileSuffix
}
-// SDK version that the stubs library is built against. Note that this is always
-// *current. Older stubs library built with a numberd SDK version is created from
-// the prebuilt jar.
-func (module *SdkLibrary) sdkVersionForScope(apiScope apiScope) string {
- switch apiScope {
- case apiScopePublic:
- return "current"
- case apiScopeSystem:
- return "system_current"
- case apiScopeTest:
- return "test_current"
- default:
- return "current"
- }
-}
-
// Get the sdk version for use when compiling the stubs library.
-func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope apiScope) string {
+func (module *SdkLibrary) sdkVersionForStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) string {
sdkDep := decodeSdkDep(mctx, sdkContext(&module.Library))
if sdkDep.hasStandardLibs() {
// If building against a standard sdk then use the sdk version appropriate for the scope.
- return module.sdkVersionForScope(apiScope)
+ return apiScope.sdkVersion
} else {
// Otherwise, use no system module.
return "none"
@@ -402,47 +433,20 @@
// $(INTERNAL_PLATFORM_<apiTagName>_API_FILE) points to the generated
// api file for the current source
// TODO: remove this when apicheck is done in soong
-func (module *SdkLibrary) apiTagName(apiScope apiScope) string {
- apiTagName := strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1)
- switch apiScope {
- case apiScopeSystem:
- apiTagName = apiTagName + "_SYSTEM"
- case apiScopeTest:
- apiTagName = apiTagName + "_TEST"
- }
- return apiTagName
+func (module *SdkLibrary) apiTagName(apiScope *apiScope) string {
+ return strings.Replace(strings.ToUpper(module.BaseModuleName()), ".", "_", -1) + apiScope.apiFileMakeVariableSuffix
}
-func (module *SdkLibrary) latestApiFilegroupName(apiScope apiScope) string {
- name := ":" + module.BaseModuleName() + ".api."
- switch apiScope {
- case apiScopePublic:
- name = name + "public"
- case apiScopeSystem:
- name = name + "system"
- case apiScopeTest:
- name = name + "test"
- }
- name = name + ".latest"
- return name
+func (module *SdkLibrary) latestApiFilegroupName(apiScope *apiScope) string {
+ return ":" + module.BaseModuleName() + ".api." + apiScope.name + ".latest"
}
-func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope apiScope) string {
- name := ":" + module.BaseModuleName() + "-removed.api."
- switch apiScope {
- case apiScopePublic:
- name = name + "public"
- case apiScopeSystem:
- name = name + "system"
- case apiScopeTest:
- name = name + "test"
- }
- name = name + ".latest"
- return name
+func (module *SdkLibrary) latestRemovedApiFilegroupName(apiScope *apiScope) string {
+ return ":" + module.BaseModuleName() + "-removed.api." + apiScope.name + ".latest"
}
// Creates a static java library that has API stubs
-func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiScope apiScope) {
+func (module *SdkLibrary) createStubsLibrary(mctx android.LoadHookContext, apiScope *apiScope) {
props := struct {
Name *string
Srcs []string
@@ -505,7 +509,7 @@
// Creates a droiddoc module that creates stubs source files from the given full source
// files
-func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope apiScope) {
+func (module *SdkLibrary) createStubsSources(mctx android.LoadHookContext, apiScope *apiScope) {
props := struct {
Name *string
Srcs []string
@@ -590,16 +594,8 @@
// List of APIs identified from the provided source files are created. They are later
// compared against to the not-yet-released (a.k.a current) list of APIs and to the
// last-released (a.k.a numbered) list of API.
- currentApiFileName := "current.txt"
- removedApiFileName := "removed.txt"
- switch apiScope {
- case apiScopeSystem:
- currentApiFileName = "system-" + currentApiFileName
- removedApiFileName = "system-" + removedApiFileName
- case apiScopeTest:
- currentApiFileName = "test-" + currentApiFileName
- removedApiFileName = "test-" + removedApiFileName
- }
+ currentApiFileName := apiScope.apiFilePrefix + "current.txt"
+ removedApiFileName := apiScope.apiFilePrefix + "removed.txt"
apiDir := module.getApiDir()
currentApiFileName = path.Join(apiDir, currentApiFileName)
removedApiFileName = path.Join(apiDir, removedApiFileName)
@@ -677,38 +673,48 @@
return android.Paths{jarPath.Path()}
}
-// to satisfy SdkLibraryDependency interface
-func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+func (module *SdkLibrary) sdkJars(
+ ctx android.BaseModuleContext,
+ sdkVersion sdkSpec,
+ headerJars bool) android.Paths {
+
// This module is just a wrapper for the stubs.
if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
return module.PrebuiltJars(ctx, sdkVersion)
} else {
+ if !sdkVersion.specified() {
+ if headerJars {
+ return module.Library.HeaderJars()
+ } else {
+ return module.Library.ImplementationJars()
+ }
+ }
+ var paths *scopePaths
switch sdkVersion.kind {
case sdkSystem:
- return module.systemApiStubsPath
+ paths = module.getScopePaths(apiScopeSystem)
case sdkPrivate:
return module.Library.HeaderJars()
default:
- return module.publicApiStubsPath
+ paths = module.getScopePaths(apiScopePublic)
+ }
+
+ if headerJars {
+ return paths.stubsHeaderPath
+ } else {
+ return paths.stubsImplPath
}
}
}
// to satisfy SdkLibraryDependency interface
+func (module *SdkLibrary) SdkHeaderJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
+ return module.sdkJars(ctx, sdkVersion, true /*headerJars*/)
+}
+
+// to satisfy SdkLibraryDependency interface
func (module *SdkLibrary) SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion sdkSpec) android.Paths {
- // This module is just a wrapper for the stubs.
- if ctx.Config().UnbundledBuildUsePrebuiltSdks() {
- return module.PrebuiltJars(ctx, sdkVersion)
- } else {
- switch sdkVersion.kind {
- case sdkSystem:
- return module.systemApiStubsImplPath
- case sdkPrivate:
- return module.Library.ImplementationJars()
- default:
- return module.publicApiStubsImplPath
- }
- }
+ return module.sdkJars(ctx, sdkVersion, false /*headerJars*/)
}
func (module *SdkLibrary) SetNoDist() {
@@ -744,17 +750,14 @@
module.sdkLibraryProperties.Has_system_and_test_apis = hasSystemAndTestApis
module.sdkLibraryProperties.No_dist = proptools.BoolPtr(!hasSystemAndTestApis)
- scopes := []string{""}
- if hasSystemAndTestApis {
- scopes = append(scopes, "system-", "test-")
- }
-
missing_current_api := false
+ activeScopes := module.getActiveApiScopes()
+
apiDir := module.getApiDir()
- for _, scope := range scopes {
+ for _, scope := range activeScopes {
for _, api := range []string{"current.txt", "removed.txt"} {
- path := path.Join(mctx.ModuleDir(), apiDir, scope+api)
+ path := path.Join(mctx.ModuleDir(), apiDir, scope.apiFilePrefix+api)
p := android.ExistentPathForSource(mctx, path)
if !p.Valid() {
mctx.ModuleErrorf("Current api file %#v doesn't exist", path)
@@ -774,22 +777,14 @@
mctx.ModuleErrorf("One or more current api files are missing. "+
"You can update them by:\n"+
"%s %q %s && m update-api",
- script, filepath.Join(mctx.ModuleDir(), apiDir), strings.Join(scopes, " "))
+ script, filepath.Join(mctx.ModuleDir(), apiDir),
+ strings.Join(activeScopes.Strings(func(s *apiScope) string { return s.apiFilePrefix }), " "))
return
}
- // for public API stubs
- module.createStubsLibrary(mctx, apiScopePublic)
- module.createStubsSources(mctx, apiScopePublic)
-
- if hasSystemAndTestApis {
- // for system API stubs
- module.createStubsLibrary(mctx, apiScopeSystem)
- module.createStubsSources(mctx, apiScopeSystem)
-
- // for test API stubs
- module.createStubsLibrary(mctx, apiScopeTest)
- module.createStubsSources(mctx, apiScopeTest)
+ for _, scope := range activeScopes {
+ module.createStubsLibrary(mctx, scope)
+ module.createStubsSources(mctx, scope)
}
if !proptools.Bool(module.sdkLibraryProperties.Api_only) {
@@ -909,7 +904,7 @@
func (module *sdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies to the prebuilt stubs library
- ctx.AddVariationDependencies(nil, publicApiStubsTag, module.BaseModuleName()+sdkStubsLibrarySuffix)
+ ctx.AddVariationDependencies(nil, apiScopePublic.stubsTag, module.BaseModuleName()+sdkStubsLibrarySuffix)
}
func (module *sdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -918,7 +913,7 @@
tag := ctx.OtherModuleDependencyTag(to)
switch tag {
- case publicApiStubsTag:
+ case apiScopePublic.stubsTag:
module.stubsPath = to.(Dependency).HeaderJars()
}
})