From 4ec24870e03eee77911d787d6d160e2389fc2a9f Mon Sep 17 00:00:00 2001 From: Jihoon Kang Date: Thu, 5 Oct 2023 17:26:09 +0000 Subject: [PATCH] Introduce system_modules property to java_api_library System_modules property provides the jars passed as bootclasspath when compiling the stubs in the java_api_library where its creating java_sdk_library's sdk_version is none, as the jars will not be provided from the full_surface_stub_libs but compiled by itself in the child change. The jar provided by the system_modules will also be passed to metalava to resolve hierarchy coming from outer dependencies. Test: m --build-from-text-stub Bug: 288624417 Change-Id: I8f3b89efa24bceb070d7a37fae3c7334dd7f0868 --- java/java.go | 36 ++++++++++++++++++++++++++++-------- java/java_test.go | 36 ++++++++++++++++++++++++++++++++++++ java/sdk_library.go | 3 +++ 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/java/java.go b/java/java.go index cac49a2c5..bde35e87a 100644 --- a/java/java.go +++ b/java/java.go @@ -1689,6 +1689,12 @@ type JavaApiLibraryProperties struct { // Version of previously released API file for compatibility check. Previous_api *string `android:"path"` + + // java_system_modules module providing the jar to be added to the + // bootclasspath when compiling the stubs. + // The jar will also be passed to metalava as a classpath to + // generate compilable stubs. + System_modules *string } func ApiLibraryFactory() android.Module { @@ -1708,7 +1714,8 @@ func (al *ApiLibrary) StubsJar() android.Path { } func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, - srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand { + srcs android.Paths, homeDir android.WritablePath, + classpath android.Paths) *android.RuleBuilderCommand { rule.Command().Text("rm -rf").Flag(homeDir.String()) rule.Command().Text("mkdir -p").Flag(homeDir.String()) @@ -1747,12 +1754,17 @@ func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder, FlagWithArg("--hide ", "InvalidNullabilityOverride"). FlagWithArg("--hide ", "ChangedDefault") - // The main purpose of the `--api-class-resolution api` option is to force metalava to ignore - // classes on the classpath when an API file contains missing classes. However, as this command - // does not specify `--classpath` this is not needed for that. However, this is also used as a - // signal to the special metalava code for generating stubs from text files that it needs to add - // some additional items into the API (e.g. default constructors). - cmd.FlagWithArg("--api-class-resolution ", "api") + if len(classpath) == 0 { + // The main purpose of the `--api-class-resolution api` option is to force metalava to ignore + // classes on the classpath when an API file contains missing classes. However, as this command + // does not specify `--classpath` this is not needed for that. However, this is also used as a + // signal to the special metalava code for generating stubs from text files that it needs to add + // some additional items into the API (e.g. default constructors). + cmd.FlagWithArg("--api-class-resolution ", "api") + } else { + cmd.FlagWithArg("--api-class-resolution ", "api:classpath") + cmd.FlagWithInputList("--classpath ", classpath, ":") + } return cmd } @@ -1815,6 +1827,9 @@ func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { if al.properties.Full_api_surface_stub != nil { ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub)) } + if al.properties.System_modules != nil { + ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules)) + } } // Map where key is the api scope name and value is the int value @@ -1854,6 +1869,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { var classPaths android.Paths var staticLibs android.Paths var depApiSrcsStubsJar android.Path + var systemModulesPaths android.Paths ctx.VisitDirectDeps(func(dep android.Module) { tag := ctx.OtherModuleDependencyTag(dep) switch tag { @@ -1872,6 +1888,9 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { case depApiSrcsTag: provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo) depApiSrcsStubsJar = provider.HeaderJars[0] + case systemModulesTag: + module := dep.(SystemModulesProvider) + systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...) } }) @@ -1885,7 +1904,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName()) } - cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir) + cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths) al.stubsFlags(ctx, cmd, stubsDir) @@ -1917,6 +1936,7 @@ func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { flags.javaVersion = getStubsJavaVersion() flags.javacFlags = strings.Join(al.properties.Javacflags, " ") flags.classpath = classpath(classPaths) + flags.bootClasspath = classpath(systemModulesPaths) annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar") diff --git a/java/java_test.go b/java/java_test.go index d51604a25..6b8b735f7 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -2447,3 +2447,39 @@ func TestJavaApiLibraryApiFilesSorting(t *testing.T) { "default/java/api/module-lib-current.txt default/java/api/system-server-current.txt" android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag) } + +func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) { + result := android.GroupFixturePreparers( + prepareForJavaTest, + PrepareForTestWithJavaSdkLibraryFiles, + FixtureWithLastReleaseApis("foo"), + android.FixtureModifyConfig(func(config android.Config) { + config.SetApiLibraries([]string{"foo"}) + }), + android.FixtureMergeMockFs( + map[string][]byte{ + "A.java": nil, + }, + ), + ).RunTestWithBp(t, ` + java_library { + name: "bar", + srcs: ["a.java"], + } + java_system_modules { + name: "baz", + libs: ["bar"], + } + java_sdk_library { + name: "foo", + srcs: ["A.java"], + system_modules: "baz", + } + `) + m := result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common") + manifest := m.Output("metalava.sbox.textproto") + sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest) + manifestCommand := sboxProto.Commands[0].GetCommand() + classPathFlag := "--classpath __SBOX_SANDBOX_DIR__/out/.intermediates/bar/android_common/turbine-combined/bar.jar" + android.AssertStringDoesContain(t, "command expected to contain classpath flag", manifestCommand, classPathFlag) +} diff --git a/java/sdk_library.go b/java/sdk_library.go index e410a41fa..f72c6086f 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -1837,6 +1837,7 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, Libs []string Static_libs []string Full_api_surface_stub *string + System_modules *string }{} props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope)) @@ -1875,6 +1876,8 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text") } + props.System_modules = module.deviceProperties.System_modules + mctx.CreateModule(ApiLibraryFactory, &props) }