Generate java_api_library from java_sdk_library
This change enables java_sdk_library to generate java_api_library modules per api surface, so that from-text stubs can be generated per api domain scope. This module is only created when `--build-from-text-stub` flag is passed during build. Test: enable disabled modules in java/core-libraries/TxtStubLibraries.bp then m art.module.public.api.stubs.from-text --build-from-text-stub Bug: 276957733 Change-Id: Ic1ead15b3d0bcb921ca8d31bcaeeb4cd9ee8715c Merged-In: Ic1ead15b3d0bcb921ca8d31bcaeeb4cd9ee8715c
This commit is contained in:
@@ -302,6 +302,9 @@ type config struct {
|
||||
// modules that aren't mixed-built for at least one variant will cause a build
|
||||
// failure
|
||||
ensureAllowlistIntegrity bool
|
||||
|
||||
// List of Api libraries that contribute to Api surfaces.
|
||||
apiLibraries map[string]struct{}
|
||||
}
|
||||
|
||||
type deviceConfig struct {
|
||||
@@ -622,6 +625,33 @@ func NewConfig(cmdArgs CmdArgs, availableEnv map[string]string) (Config, error)
|
||||
config.BazelContext, err = NewBazelContext(config)
|
||||
config.Bp2buildPackageConfig = GetBp2BuildAllowList()
|
||||
|
||||
// TODO(b/276958307): Replace the hardcoded list to a sdk_library local prop.
|
||||
config.apiLibraries = map[string]struct{}{
|
||||
"android.net.ipsec.ike": {},
|
||||
"art.module.public.api": {},
|
||||
"conscrypt.module.public.api": {},
|
||||
"framework-adservices": {},
|
||||
"framework-appsearch": {},
|
||||
"framework-bluetooth": {},
|
||||
"framework-connectivity": {},
|
||||
"framework-connectivity-t": {},
|
||||
"framework-graphics": {},
|
||||
"framework-media": {},
|
||||
"framework-mediaprovider": {},
|
||||
"framework-ondevicepersonalization": {},
|
||||
"framework-permission": {},
|
||||
"framework-permission-s": {},
|
||||
"framework-scheduling": {},
|
||||
"framework-sdkextensions": {},
|
||||
"framework-statsd": {},
|
||||
"framework-sdksandbox": {},
|
||||
"framework-tethering": {},
|
||||
"framework-uwb": {},
|
||||
"framework-virtualization": {},
|
||||
"framework-wifi": {},
|
||||
"i18n.module.public.api": {},
|
||||
}
|
||||
|
||||
return Config{config}, err
|
||||
}
|
||||
|
||||
@@ -1979,8 +2009,20 @@ func (c *config) BuildFromTextStub() bool {
|
||||
func (c *config) SetBuildFromTextStub(b bool) {
|
||||
c.buildFromTextStub = b
|
||||
}
|
||||
|
||||
func (c *config) AddForceEnabledModules(forceEnabled []string) {
|
||||
for _, forceEnabledModule := range forceEnabled {
|
||||
c.bazelForceEnabledModules[forceEnabledModule] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *config) SetApiLibraries(libs []string) {
|
||||
c.apiLibraries = make(map[string]struct{})
|
||||
for _, lib := range libs {
|
||||
c.apiLibraries[lib] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *config) GetApiLibraries() map[string]struct{} {
|
||||
return c.apiLibraries
|
||||
}
|
||||
|
@@ -156,6 +156,9 @@ type apiScope struct {
|
||||
|
||||
// Whether the api scope can be treated as unstable, and should skip compat checks.
|
||||
unstable bool
|
||||
|
||||
// Represents the SDK kind of this scope.
|
||||
kind android.SdkKind
|
||||
}
|
||||
|
||||
// Initialize a scope, creating and adding appropriate dependency tags
|
||||
@@ -229,6 +232,10 @@ func (scope *apiScope) stubsLibraryModuleNameSuffix() string {
|
||||
return ".stubs" + scope.moduleSuffix
|
||||
}
|
||||
|
||||
func (scope *apiScope) apiLibraryModuleName(baseName string) string {
|
||||
return scope.stubsLibraryModuleName(baseName) + ".from-text"
|
||||
}
|
||||
|
||||
func (scope *apiScope) stubsLibraryModuleName(baseName string) string {
|
||||
return baseName + scope.stubsLibraryModuleNameSuffix()
|
||||
}
|
||||
@@ -289,6 +296,7 @@ var (
|
||||
return &module.sdkLibraryProperties.Public
|
||||
},
|
||||
sdkVersion: "current",
|
||||
kind: android.SdkPublic,
|
||||
})
|
||||
apiScopeSystem = initApiScope(&apiScope{
|
||||
name: "system",
|
||||
@@ -301,6 +309,7 @@ var (
|
||||
moduleSuffix: ".system",
|
||||
sdkVersion: "system_current",
|
||||
annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS)",
|
||||
kind: android.SdkSystem,
|
||||
})
|
||||
apiScopeTest = initApiScope(&apiScope{
|
||||
name: "test",
|
||||
@@ -314,6 +323,7 @@ var (
|
||||
sdkVersion: "test_current",
|
||||
annotation: "android.annotation.TestApi",
|
||||
unstable: true,
|
||||
kind: android.SdkTest,
|
||||
})
|
||||
apiScopeModuleLib = initApiScope(&apiScope{
|
||||
name: "module-lib",
|
||||
@@ -331,6 +341,7 @@ var (
|
||||
moduleSuffix: ".module_lib",
|
||||
sdkVersion: "module_current",
|
||||
annotation: "android.annotation.SystemApi(client=android.annotation.SystemApi.Client.MODULE_LIBRARIES)",
|
||||
kind: android.SdkModule,
|
||||
})
|
||||
apiScopeSystemServer = initApiScope(&apiScope{
|
||||
name: "system-server",
|
||||
@@ -361,6 +372,7 @@ var (
|
||||
// com.android.* classes are okay in this interface"
|
||||
"--hide", "InternalClasses",
|
||||
},
|
||||
kind: android.SdkSystemServer,
|
||||
})
|
||||
allApiScopes = apiScopes{
|
||||
apiScopePublic,
|
||||
@@ -842,6 +854,13 @@ func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope)
|
||||
return c.namingScheme.stubsSourceModuleName(apiScope, baseName)
|
||||
}
|
||||
|
||||
// Name of the java_api_library module that generates the from-text stubs source
|
||||
// and compiles to a jar file.
|
||||
func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) string {
|
||||
baseName := c.module.BaseModuleName()
|
||||
return c.namingScheme.apiLibraryModuleName(apiScope, baseName)
|
||||
}
|
||||
|
||||
// The component names for different outputs of the java_sdk_library.
|
||||
//
|
||||
// They are similar to the names used for the child modules it creates
|
||||
@@ -1269,7 +1288,9 @@ func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContex
|
||||
// Add dependencies to the stubs library
|
||||
stubModuleName := module.stubsLibraryModuleName(apiScope)
|
||||
// Use JavaApiLibraryName function to be redirected to stubs generated from .txt if applicable
|
||||
stubModuleName = android.JavaApiLibraryName(ctx.Config(), stubModuleName)
|
||||
if module.contributesToApiSurface(ctx.Config()) {
|
||||
stubModuleName = android.JavaApiLibraryName(ctx.Config(), stubModuleName)
|
||||
}
|
||||
ctx.AddVariationDependencies(nil, apiScope.stubsTag, stubModuleName)
|
||||
|
||||
// Add a dependency on the stubs source in order to access both stubs source and api information.
|
||||
@@ -1477,6 +1498,11 @@ func (module *SdkLibrary) latestIncompatibilitiesModuleName(apiScope *apiScope)
|
||||
return latestPrebuiltApiModuleName(module.distStem()+"-incompatibilities", apiScope)
|
||||
}
|
||||
|
||||
func (module *SdkLibrary) contributesToApiSurface(c android.Config) bool {
|
||||
_, exists := c.GetApiLibraries()[module.Name()]
|
||||
return exists
|
||||
}
|
||||
|
||||
func childModuleVisibility(childVisibility []string) []string {
|
||||
if childVisibility == nil {
|
||||
// No child visibility set. The child will use the visibility of the sdk_library.
|
||||
@@ -1758,6 +1784,46 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
|
||||
mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx)
|
||||
}
|
||||
|
||||
func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
|
||||
props := struct {
|
||||
Name *string
|
||||
Visibility []string
|
||||
Api_contributions []string
|
||||
Libs []string
|
||||
Static_libs []string
|
||||
Dep_api_srcs *string
|
||||
}{}
|
||||
|
||||
props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
|
||||
props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
|
||||
|
||||
apiContributions := []string{}
|
||||
|
||||
// Api surfaces are not independent of each other, but have subset relationships,
|
||||
// and so does the api files. To generate from-text stubs for api surfaces other than public,
|
||||
// all subset api domains' api_contriubtions must be added as well.
|
||||
scope := apiScope
|
||||
for scope != nil {
|
||||
apiContributions = append(apiContributions, module.stubsSourceModuleName(scope)+".api.contribution")
|
||||
scope = scope.extends
|
||||
}
|
||||
|
||||
props.Api_contributions = apiContributions
|
||||
props.Libs = module.properties.Libs
|
||||
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
|
||||
props.Libs = append(props.Libs, "stub-annotations")
|
||||
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
|
||||
props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text")
|
||||
|
||||
// android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n.
|
||||
// Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
|
||||
if apiScope.kind == android.SdkModule {
|
||||
props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
|
||||
}
|
||||
|
||||
mctx.CreateModule(ApiLibraryFactory, &props)
|
||||
}
|
||||
|
||||
func (module *SdkLibrary) compareAgainstLatestApi(apiScope *apiScope) bool {
|
||||
return !(apiScope.unstable || module.sdkLibraryProperties.Unsafe_ignore_missing_latest_api)
|
||||
}
|
||||
@@ -1954,6 +2020,10 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
|
||||
module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
|
||||
|
||||
module.createStubsLibrary(mctx, scope)
|
||||
|
||||
if module.contributesToApiSurface(mctx.Config()) {
|
||||
module.createApiLibrary(mctx, scope)
|
||||
}
|
||||
}
|
||||
|
||||
if module.requiresRuntimeImplementationLibrary() {
|
||||
@@ -2006,6 +2076,8 @@ type sdkLibraryComponentNamingScheme interface {
|
||||
stubsLibraryModuleName(scope *apiScope, baseName string) string
|
||||
|
||||
stubsSourceModuleName(scope *apiScope, baseName string) string
|
||||
|
||||
apiLibraryModuleName(scope *apiScope, baseName string) string
|
||||
}
|
||||
|
||||
type defaultNamingScheme struct {
|
||||
@@ -2019,6 +2091,10 @@ func (s *defaultNamingScheme) stubsSourceModuleName(scope *apiScope, baseName st
|
||||
return scope.stubsSourceModuleName(baseName)
|
||||
}
|
||||
|
||||
func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName string) string {
|
||||
return scope.apiLibraryModuleName(baseName)
|
||||
}
|
||||
|
||||
var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
|
||||
|
||||
func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
|
||||
|
@@ -35,6 +35,9 @@ func TestJavaSdkLibrary(t *testing.T) {
|
||||
"29": {"foo"},
|
||||
"30": {"bar", "barney", "baz", "betty", "foo", "fred", "quuz", "wilma"},
|
||||
}),
|
||||
android.FixtureModifyConfig(func(config android.Config) {
|
||||
config.SetApiLibraries([]string{"foo"})
|
||||
}),
|
||||
).RunTestWithBp(t, `
|
||||
droiddoc_exported_dir {
|
||||
name: "droiddoc-templates-sdk",
|
||||
@@ -121,6 +124,7 @@ func TestJavaSdkLibrary(t *testing.T) {
|
||||
result.ModuleForTests(apiScopeSystem.stubsSourceModuleName("foo"), "android_common")
|
||||
result.ModuleForTests(apiScopeTest.stubsSourceModuleName("foo"), "android_common")
|
||||
result.ModuleForTests(apiScopePublic.stubsSourceModuleName("foo")+".api.contribution", "")
|
||||
result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common")
|
||||
result.ModuleForTests("foo"+sdkXmlFileSuffix, "android_common")
|
||||
result.ModuleForTests("foo.api.public.28", "")
|
||||
result.ModuleForTests("foo.api.system.28", "")
|
||||
@@ -1412,3 +1416,62 @@ func TestJavaSdkLibrary_StubOnlyLibs_PassedToDroidstubs(t *testing.T) {
|
||||
fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
|
||||
android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
|
||||
}
|
||||
|
||||
func TestJavaSdkLibrary_ApiLibrary(t *testing.T) {
|
||||
result := android.GroupFixturePreparers(
|
||||
prepareForJavaTest,
|
||||
PrepareForTestWithJavaSdkLibraryFiles,
|
||||
FixtureWithLastReleaseApis("foo"),
|
||||
android.FixtureModifyConfig(func(config android.Config) {
|
||||
config.SetApiLibraries([]string{"foo"})
|
||||
}),
|
||||
).RunTestWithBp(t, `
|
||||
java_sdk_library {
|
||||
name: "foo",
|
||||
srcs: ["a.java", "b.java"],
|
||||
api_packages: ["foo"],
|
||||
system: {
|
||||
enabled: true,
|
||||
},
|
||||
module_lib: {
|
||||
enabled: true,
|
||||
},
|
||||
test: {
|
||||
enabled: true,
|
||||
},
|
||||
}
|
||||
`)
|
||||
|
||||
testCases := []struct {
|
||||
scope *apiScope
|
||||
apiContributions []string
|
||||
depApiSrcs string
|
||||
}{
|
||||
{
|
||||
scope: apiScopePublic,
|
||||
apiContributions: []string{"foo.stubs.source.api.contribution"},
|
||||
depApiSrcs: "android_stubs_current.from-text",
|
||||
},
|
||||
{
|
||||
scope: apiScopeSystem,
|
||||
apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
|
||||
depApiSrcs: "android_system_stubs_current.from-text",
|
||||
},
|
||||
{
|
||||
scope: apiScopeTest,
|
||||
apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
|
||||
depApiSrcs: "android_test_stubs_current.from-text",
|
||||
},
|
||||
{
|
||||
scope: apiScopeModuleLib,
|
||||
apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
|
||||
depApiSrcs: "android_module_lib_stubs_current_full.from-text",
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range testCases {
|
||||
m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary)
|
||||
android.AssertArrayString(t, "Module expected to contain api contributions", c.apiContributions, m.properties.Api_contributions)
|
||||
android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.depApiSrcs, *m.properties.Dep_api_srcs)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user