Extract class files from dep_api_srcs instead of java files

Currently, stub java files are extracted from srcjar file provided from
dep_api_srcs in java_api_library module generated in java_sdk_library
per api scope. However, compiling the java files may lead to difference
in the content of the generated class files even if the stub java files
are equivalent, as javac may arbitrarily add overridden methods. Thus,
create a stub jar file instead of creating a stub srcjar file and
compiling it, in order to guarantee stub jar files content equivalence
and thus enable hiddenapi during from-text stub build.

Note that this change does not fully resolve differences between the
full api surface csv and the per sdk_library csv. Instead, it removes
the difference caused by methods arbitrarily added by javac.

This change also renames dep_api_srcs to full_api_surface_stubs to be
more intuitive.

Test: rebase on top of aosp/2617274 and `m --build-from-text-stub`
Bug: 275570206
Change-Id: I22b6d56624633681f5c3b000370b5782655c7b8d
This commit is contained in:
Jihoon Kang
2023-06-22 23:13:51 +00:00
parent a56663f695
commit ca198c2639
4 changed files with 69 additions and 83 deletions

View File

@@ -1624,13 +1624,6 @@ func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleCon
}) })
} }
type JavaApiLibraryDepsInfo struct {
JavaInfo
StubsSrcJar android.Path
}
var JavaApiLibraryDepsProvider = blueprint.NewProvider(JavaApiLibraryDepsInfo{})
type ApiLibrary struct { type ApiLibrary struct {
android.ModuleBase android.ModuleBase
android.DefaultableModuleBase android.DefaultableModuleBase
@@ -1672,10 +1665,11 @@ type JavaApiLibraryProperties struct {
// merge zipped after metalava invocation // merge zipped after metalava invocation
Static_libs []string Static_libs []string
// Java Api library to provide the full API surface text files and jar file. // Java Api library to provide the full API surface stub jar file.
// If this property is set, the provided full API surface text files and // If this property is set, the stub jar of this module is created by
// jar file are passed to metalava invocation. // extracting the compiled class files provided by the
Dep_api_srcs *string // full_api_surface_stub module.
Full_api_surface_stub *string
} }
func ApiLibraryFactory() android.Module { func ApiLibraryFactory() android.Module {
@@ -1762,35 +1756,37 @@ func (al *ApiLibrary) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBui
} }
} }
// This method extracts the stub java files from the srcjar file provided from dep_api_srcs module // This method extracts the stub class files from the stub jar file provided
// and replaces the java stubs generated by invoking metalava in this module. // from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava.
// This method is used because metalava can generate compilable from-text stubs only when // This method is used because metalava can generate compilable from-text stubs only when
// the codebase encompasses all classes listed in the input API text file, but a class can extend // the codebase encompasses all classes listed in the input API text file, and a class can extend
// a class that is not within the same API domain. // a class that is not within the same API domain.
func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, depApiSrcsSrcJar android.Path) { func (al *ApiLibrary) extractApiSrcs(ctx android.ModuleContext, rule *android.RuleBuilder, stubsDir android.OptionalPath, fullApiSurfaceStubJar android.Path) {
generatedStubsList := android.PathForModuleOut(ctx, "metalava", "sources.txt") classFilesList := android.PathForModuleOut(ctx, "metalava", "classes.txt")
unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir") unzippedSrcJarDir := android.PathForModuleOut(ctx, "metalava", "unzipDir")
rule.Command(). rule.Command().
BuiltTool("list_files"). BuiltTool("list_files").
Text(stubsDir.String()). Text(stubsDir.String()).
FlagWithOutput("--out ", generatedStubsList). FlagWithOutput("--out ", classFilesList).
FlagWithArg("--extensions ", ".java"). FlagWithArg("--extensions ", ".java").
FlagWithArg("--root ", unzippedSrcJarDir.String()) FlagWithArg("--root ", unzippedSrcJarDir.String()).
Flag("--classes")
rule.Command(). rule.Command().
Text("unzip"). Text("unzip").
Flag("-q"). Flag("-q").
Input(depApiSrcsSrcJar). Input(fullApiSurfaceStubJar).
FlagWithArg("-d ", unzippedSrcJarDir.String()) FlagWithArg("-d ", unzippedSrcJarDir.String())
rule.Command(). rule.Command().
BuiltTool("soong_zip"). BuiltTool("soong_zip").
Flag("-srcjar"). Flag("-jar").
Flag("-write_if_changed"). Flag("-write_if_changed").
Flag("-ignore_missing_files").
FlagWithArg("-C ", unzippedSrcJarDir.String()). FlagWithArg("-C ", unzippedSrcJarDir.String()).
FlagWithInput("-l ", generatedStubsList). FlagWithInput("-l ", classFilesList).
FlagWithOutput("-o ", al.stubsSrcJar) FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
} }
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -1800,8 +1796,8 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
} }
ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...) ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...) ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
if al.properties.Dep_api_srcs != nil { if al.properties.Full_api_surface_stub != nil {
ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Dep_api_srcs)) ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
} }
} }
@@ -1823,7 +1819,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var srcFiles android.Paths var srcFiles android.Paths
var classPaths android.Paths var classPaths android.Paths
var staticLibs android.Paths var staticLibs android.Paths
var depApiSrcsStubsSrcJar android.Path var depApiSrcsStubsJar android.Path
ctx.VisitDirectDeps(func(dep android.Module) { ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep) tag := ctx.OtherModuleDependencyTag(dep)
switch tag { switch tag {
@@ -1841,9 +1837,8 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
staticLibs = append(staticLibs, provider.HeaderJars...) staticLibs = append(staticLibs, provider.HeaderJars...)
case depApiSrcsTag: case depApiSrcsTag:
provider := ctx.OtherModuleProvider(dep, JavaApiLibraryDepsProvider).(JavaApiLibraryDepsInfo) provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
classPaths = append(classPaths, provider.HeaderJars...) depApiSrcsStubsJar = provider.HeaderJars[0]
depApiSrcsStubsSrcJar = provider.StubsSrcJar
} }
}) })
@@ -1861,31 +1856,31 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
al.stubsFlags(ctx, cmd, stubsDir) al.stubsFlags(ctx, cmd, stubsDir)
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar") al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
if depApiSrcsStubsSrcJar != nil { if depApiSrcsStubsJar != nil {
al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsSrcJar) al.extractApiSrcs(ctx, rule, stubsDir, depApiSrcsStubsJar)
} else {
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
Flag("-jar").
FlagWithOutput("-o ", al.stubsSrcJar).
FlagWithArg("-C ", stubsDir.String()).
FlagWithArg("-D ", stubsDir.String())
} }
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
Flag("-jar").
FlagWithOutput("-o ", al.stubsSrcJar).
FlagWithArg("-C ", stubsDir.String()).
FlagWithArg("-D ", stubsDir.String())
rule.Build("metalava", "metalava merged") rule.Build("metalava", "metalava merged")
al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, ctx.ModuleName(), "stubs.jar") if depApiSrcsStubsJar == nil {
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName())) var flags javaBuilderFlags
flags.javaVersion = getStubsJavaVersion()
flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
flags.classpath = classpath(classPaths)
var flags javaBuilderFlags TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
flags.javaVersion = getStubsJavaVersion() android.Paths{al.stubsSrcJar}, flags, android.Paths{})
flags.javacFlags = strings.Join(al.properties.Javacflags, " ") }
flags.classpath = classpath(classPaths)
TransformJavaToClasses(ctx, al.stubsJarWithoutStaticLibs, 0, android.Paths{},
android.Paths{al.stubsSrcJar}, flags, android.Paths{})
builder := android.NewRuleBuilder(pctx, ctx) builder := android.NewRuleBuilder(pctx, ctx)
builder.Command(). builder.Command().
@@ -1917,13 +1912,6 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ImplementationJars: android.PathsIfNonNil(al.stubsJar), ImplementationJars: android.PathsIfNonNil(al.stubsJar),
AidlIncludeDirs: android.Paths{}, AidlIncludeDirs: android.Paths{},
}) })
ctx.SetProvider(JavaApiLibraryDepsProvider, JavaApiLibraryDepsInfo{
JavaInfo: JavaInfo{
HeaderJars: android.PathsIfNonNil(al.stubsJar),
},
StubsSrcJar: al.stubsSrcJar,
})
} }
func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath { func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {

View File

@@ -2208,7 +2208,7 @@ func TestJavaApiLibraryStaticLibsLink(t *testing.T) {
} }
} }
func TestJavaApiLibraryDepApiSrcs(t *testing.T) { func TestJavaApiLibraryFullApiSurfaceStub(t *testing.T) {
provider_bp_a := ` provider_bp_a := `
java_api_contribution { java_api_contribution {
name: "foo1", name: "foo1",
@@ -2234,7 +2234,7 @@ func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
name: "bar1", name: "bar1",
api_surface: "public", api_surface: "public",
api_contributions: ["foo1"], api_contributions: ["foo1"],
dep_api_srcs: "lib1", full_api_surface_stub: "lib1",
} }
`, `,
map[string][]byte{ map[string][]byte{
@@ -2247,9 +2247,7 @@ func TestJavaApiLibraryDepApiSrcs(t *testing.T) {
manifest := m.Output("metalava.sbox.textproto") manifest := m.Output("metalava.sbox.textproto")
sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand() manifestCommand := sboxProto.Commands[0].GetCommand()
android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
android.AssertStringDoesContain(t, "Command expected to contain module srcjar file", manifestCommand, "bar1-stubs.srcjar")
android.AssertStringDoesContain(t, "Command expected to contain output files list text file flag", manifestCommand, "--out __SBOX_SANDBOX_DIR__/out/sources.txt")
} }
func TestJavaApiLibraryFilegroupInput(t *testing.T) { func TestJavaApiLibraryFilegroupInput(t *testing.T) {

View File

@@ -1780,12 +1780,12 @@ func (module *SdkLibrary) createStubsSourcesAndApi(mctx android.DefaultableHookC
func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) { func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
props := struct { props := struct {
Name *string Name *string
Visibility []string Visibility []string
Api_contributions []string Api_contributions []string
Libs []string Libs []string
Static_libs []string Static_libs []string
Dep_api_srcs *string Full_api_surface_stub *string
}{} }{}
props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
@@ -1807,12 +1807,12 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext,
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...) props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
props.Libs = append(props.Libs, "stub-annotations") props.Libs = append(props.Libs, "stub-annotations")
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text") props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + ".from-text")
// android_module_lib_stubs_current.from-text only comprises api contributions from art, conscrypt and i18n. // 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. // Thus, replace with android_module_lib_stubs_current_full.from-text, which comprises every api domains.
if apiScope.kind == android.SdkModule { if apiScope.kind == android.SdkModule {
props.Dep_api_srcs = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text") props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
} }
mctx.CreateModule(ApiLibraryFactory, &props) mctx.CreateModule(ApiLibraryFactory, &props)

View File

@@ -1442,35 +1442,35 @@ func TestJavaSdkLibrary_ApiLibrary(t *testing.T) {
`) `)
testCases := []struct { testCases := []struct {
scope *apiScope scope *apiScope
apiContributions []string apiContributions []string
depApiSrcs string fullApiSurfaceStub string
}{ }{
{ {
scope: apiScopePublic, scope: apiScopePublic,
apiContributions: []string{"foo.stubs.source.api.contribution"}, apiContributions: []string{"foo.stubs.source.api.contribution"},
depApiSrcs: "android_stubs_current.from-text", fullApiSurfaceStub: "android_stubs_current.from-text",
}, },
{ {
scope: apiScopeSystem, scope: apiScopeSystem,
apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, apiContributions: []string{"foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"},
depApiSrcs: "android_system_stubs_current.from-text", fullApiSurfaceStub: "android_system_stubs_current.from-text",
}, },
{ {
scope: apiScopeTest, scope: apiScopeTest,
apiContributions: []string{"foo.stubs.source.test.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, 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", fullApiSurfaceStub: "android_test_stubs_current.from-text",
}, },
{ {
scope: apiScopeModuleLib, scope: apiScopeModuleLib,
apiContributions: []string{"foo.stubs.source.module_lib.api.contribution", "foo.stubs.source.system.api.contribution", "foo.stubs.source.api.contribution"}, 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", fullApiSurfaceStub: "android_module_lib_stubs_current_full.from-text",
}, },
} }
for _, c := range testCases { for _, c := range testCases {
m := result.ModuleForTests(c.scope.apiLibraryModuleName("foo"), "android_common").Module().(*ApiLibrary) 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.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) android.AssertStringEquals(t, "Module expected to contain full api surface api library", c.fullApiSurfaceStub, *m.properties.Full_api_surface_stub)
} }
} }