Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa4a90d4 authored by Jihoon Kang's avatar Jihoon Kang
Browse files

Generate "exportable" stubs library in java_sdk_library

Given that now the droidstubs module generates the "exportable" stubs,
this change modifies java_sdk_library to generate the java_library
modules that compiles the "exportable" stubs per api scope.
The detailed naming scheme of the generated modules are available in the
bug linked in the footer.

Similar to the from-text java_api_library vs from-source java_library
static lib selection for the "everything" stubs, the "exportable" stubs
module can also toggle between the stubs java_api_library and the
java_library module. However, given that the "exportable" stubs
generation has not been implemented for from-text stubs, the module
always default to depend on the from-source "exportable" stubs compiling
java_library module.

Test: go test ./java
Bug: 315495926
Change-Id: I5798312c1338c55625b2030da728b056385171a4
parent 78f8914f
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1329,7 +1329,9 @@ type PrebuiltStubsSources struct {

func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
	switch tag {
	case "":
	// prebuilt droidstubs does not output "exportable" stubs.
	// Output the "everything" stubs srcjar file if the tag is ".exportable".
	case "", ".exportable":
		return android.Paths{p.stubsSrcJar}, nil
	default:
		return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+132 −62
Original line number Diff line number Diff line
@@ -231,6 +231,10 @@ func (scope *apiScope) stubsLibraryModuleNameSuffix() string {
	return ".stubs" + scope.moduleSuffix
}

func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string {
	return ".stubs.exportable" + scope.moduleSuffix
}

func (scope *apiScope) apiLibraryModuleName(baseName string) string {
	return scope.stubsLibraryModuleName(baseName) + ".from-text"
}
@@ -239,10 +243,18 @@ func (scope *apiScope) sourceStubLibraryModuleName(baseName string) string {
	return scope.stubsLibraryModuleName(baseName) + ".from-source"
}

func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string {
	return scope.exportableStubsLibraryModuleName(baseName) + ".from-source"
}

func (scope *apiScope) stubsLibraryModuleName(baseName string) string {
	return baseName + scope.stubsLibraryModuleNameSuffix()
}

func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string {
	return baseName + scope.exportableStubsLibraryModuleNameSuffix()
}

func (scope *apiScope) stubsSourceModuleName(baseName string) string {
	return baseName + ".stubs.source" + scope.moduleSuffix
}
@@ -895,6 +907,12 @@ func (c *commonToSdkLibraryAndImport) stubsLibraryModuleName(apiScope *apiScope)
	return c.namingScheme.stubsLibraryModuleName(apiScope, baseName)
}

// Name of the java_library module that compiles the exportable stubs source.
func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
	baseName := c.module.BaseModuleName()
	return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName)
}

// Name of the droidstubs module that generates the stubs source and may also
// generate/check the API.
func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
@@ -911,9 +929,16 @@ func (c *commonToSdkLibraryAndImport) apiLibraryModuleName(apiScope *apiScope) s

// Name of the java_library module that compiles the stubs
// generated from source Java files.
func (c *commonToSdkLibraryAndImport) sourceStubLibraryModuleName(apiScope *apiScope) string {
func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
	baseName := c.module.BaseModuleName()
	return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName)
}

// Name of the java_library module that compiles the exportable stubs
// generated from source Java files.
func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string {
	baseName := c.module.BaseModuleName()
	return c.namingScheme.sourceStubLibraryModuleName(apiScope, baseName)
	return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName)
}

// The component names for different outputs of the java_sdk_library.
@@ -1629,9 +1654,7 @@ func (module *SdkLibrary) createImplLibrary(mctx android.DefaultableHookContext)
	mctx.CreateModule(LibraryFactory, properties...)
}

// Creates a static java library that has API stubs
func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
	props := struct {
type libraryProperties struct {
	Name           *string
	Visibility     []string
	Srcs           []string
@@ -1653,12 +1676,12 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
		Dir     *string
		Tag     *string
	}
	}{}
}

	props.Name = proptools.StringPtr(module.sourceStubLibraryModuleName(apiScope))
func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
	props := libraryProperties{}
	props.Visibility = []string{"//visibility:override", "//visibility:private"}
	// sources are generated from the droiddoc
	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
	props.Sdk_version = proptools.StringPtr(sdkVersion)
	props.System_modules = module.deviceProperties.System_modules
@@ -1678,6 +1701,25 @@ func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext
	// interop with older developer tools that don't support 1.9.
	props.Java_version = proptools.StringPtr("1.8")

	return props
}

// Creates a static java library that has API stubs
func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {

	props := module.stubsLibraryProps(mctx, apiScope)
	props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope))
	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}

	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

// Create a static java library that compiles the "exportable" stubs
func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
	props := module.stubsLibraryProps(mctx, apiScope)
	props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope))
	props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"}

	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

@@ -1908,36 +1950,49 @@ func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext,
	mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

func (module *SdkLibrary) createTopLevelStubsLibrary(
	mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
	props := struct {
		Name           *string
		Visibility     []string
		Sdk_version    *string
		Static_libs    []string
		System_modules *string
		Dist           struct {
			Targets []string
			Dest    *string
			Dir     *string
			Tag     *string
		}
		Compile_dex *bool
	}{}
	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
	props := libraryProperties{}

	props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
	sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
	props.Sdk_version = proptools.StringPtr(sdkVersion)

	props.System_modules = module.deviceProperties.System_modules

	// The imports need to be compiled to dex if the java_sdk_library requests it.
	compileDex := module.dexProperties.Compile_dex
	if module.stubLibrariesCompiledForDex() {
		compileDex = proptools.BoolPtr(true)
	}
	props.Compile_dex = compileDex

	return props
}

func (module *SdkLibrary) createTopLevelStubsLibrary(
	mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {

	props := module.topLevelStubsLibraryProps(mctx, apiScope)
	props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))

	// Add the stub compiling java_library/java_api_library as static lib based on build config
	staticLib := module.sourceStubLibraryModuleName(apiScope)
	staticLib := module.sourceStubsLibraryModuleName(apiScope)
	if mctx.Config().BuildFromTextStub() && contributesToApiSurface {
		staticLib = module.apiLibraryModuleName(apiScope)
	}
	props.Static_libs = append(props.Static_libs, staticLib)
	props.System_modules = module.deviceProperties.System_modules

	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}

func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
	mctx android.DefaultableHookContext, apiScope *apiScope) {

	props := module.topLevelStubsLibraryProps(mctx, apiScope)
	props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))

	// Dist the class jar artifact for sdk builds.
	// "exportable" stubs are copied to dist for sdk builds instead of the "everything" stubs.
	if !Bool(module.sdkLibraryProperties.No_dist) {
		props.Dist.Targets = []string{"sdk", "win_sdk"}
		props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
@@ -1945,12 +2000,8 @@ func (module *SdkLibrary) createTopLevelStubsLibrary(
		props.Dist.Tag = proptools.StringPtr(".jar")
	}

	// The imports need to be compiled to dex if the java_sdk_library requests it.
	compileDex := module.dexProperties.Compile_dex
	if module.stubLibrariesCompiledForDex() {
		compileDex = proptools.BoolPtr(true)
	}
	props.Compile_dex = compileDex
	staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
	props.Static_libs = append(props.Static_libs, staticLib)

	mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -2157,6 +2208,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
		module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)

		module.createStubsLibrary(mctx, scope)
		module.createExportableStubsLibrary(mctx, scope)

		alternativeFullApiSurfaceStubLib := ""
		if scope == apiScopePublic {
@@ -2168,6 +2220,7 @@ func (module *SdkLibrary) CreateInternalModules(mctx android.DefaultableHookCont
		}

		module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface)
		module.createTopLevelExportableStubsLibrary(mctx, scope)
	}

	if module.requiresRuntimeImplementationLibrary() {
@@ -2223,7 +2276,11 @@ type sdkLibraryComponentNamingScheme interface {

	apiLibraryModuleName(scope *apiScope, baseName string) string

	sourceStubLibraryModuleName(scope *apiScope, baseName string) string
	sourceStubsLibraryModuleName(scope *apiScope, baseName string) string

	exportableStubsLibraryModuleName(scope *apiScope, baseName string) string

	exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string
}

type defaultNamingScheme struct {
@@ -2241,34 +2298,47 @@ func (s *defaultNamingScheme) apiLibraryModuleName(scope *apiScope, baseName str
	return scope.apiLibraryModuleName(baseName)
}

func (s *defaultNamingScheme) sourceStubLibraryModuleName(scope *apiScope, baseName string) string {
func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
	return scope.sourceStubLibraryModuleName(baseName)
}

func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string {
	return scope.exportableStubsLibraryModuleName(baseName)
}

func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
	return scope.exportableSourceStubsLibraryModuleName(baseName)
}

var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)

func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool {
	return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) ||
		strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix())
}

func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
	name = strings.TrimSuffix(name, ".from-source")

	// This suffix-based approach is fragile and could potentially mis-trigger.
	// TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
	if strings.HasSuffix(name, apiScopePublic.stubsLibraryModuleNameSuffix()) {
	if hasStubsLibrarySuffix(name, apiScopePublic) {
		if name == "hwbinder.stubs" || name == "libcore_private.stubs" {
			// Due to a previous bug, these modules were not considered stubs, so we retain that.
			return false, javaPlatform
		}
		return true, javaSdk
	}
	if strings.HasSuffix(name, apiScopeSystem.stubsLibraryModuleNameSuffix()) {
	if hasStubsLibrarySuffix(name, apiScopeSystem) {
		return true, javaSystem
	}
	if strings.HasSuffix(name, apiScopeModuleLib.stubsLibraryModuleNameSuffix()) {
	if hasStubsLibrarySuffix(name, apiScopeModuleLib) {
		return true, javaModule
	}
	if strings.HasSuffix(name, apiScopeTest.stubsLibraryModuleNameSuffix()) {
	if hasStubsLibrarySuffix(name, apiScopeTest) {
		return true, javaSystem
	}
	if strings.HasSuffix(name, apiScopeSystemServer.stubsLibraryModuleNameSuffix()) {
	if hasStubsLibrarySuffix(name, apiScopeSystemServer) {
		return true, javaSystemServer
	}
	return false, javaPlatform
+54 −1
Original line number Diff line number Diff line
@@ -1423,7 +1423,7 @@ func TestJavaSdkLibraryDist(t *testing.T) {

	for _, tt := range testCases {
		t.Run(tt.module, func(t *testing.T) {
			m := result.ModuleForTests(tt.module+".stubs", "android_common").Module().(*Library)
			m := result.ModuleForTests(apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library)
			dists := m.Dists()
			if len(dists) != 1 {
				t.Fatalf("expected exactly 1 dist entry, got %d", len(dists))
@@ -1693,3 +1693,56 @@ func TestSdkLibraryDependency(t *testing.T) {

	android.AssertStringDoesContain(t, "bar.xml java_sdk_xml command", barPermissions.RuleParams.Command, `dependency=\"foo\"`)
}

func TestSdkLibraryExportableStubsLibrary(t *testing.T) {
	result := android.GroupFixturePreparers(
		prepareForJavaTest,
		PrepareForTestWithJavaSdkLibraryFiles,
		FixtureWithLastReleaseApis("foo"),
		android.FixtureModifyConfig(func(config android.Config) {
			config.SetApiLibraries([]string{"foo"})
		}),
	).RunTestWithBp(t, `
		aconfig_declarations {
			name: "bar",
			package: "com.example.package",
			srcs: [
				"bar.aconfig",
			],
		}
		java_sdk_library {
			name: "foo",
			srcs: ["a.java", "b.java"],
			api_packages: ["foo"],
			system: {
				enabled: true,
			},
			module_lib: {
				enabled: true,
			},
			test: {
				enabled: true,
			},
			aconfig_declarations: [
				"bar",
			],
		}
	`)

	exportableStubsLibraryModuleName := apiScopePublic.exportableStubsLibraryModuleName("foo")
	exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo")

	// Check modules generation
	topLevelModule := result.ModuleForTests(exportableStubsLibraryModuleName, "android_common")
	result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common")

	// Check static lib dependency
	android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+
		"exportable source stubs library module", true,
		CheckModuleHasDependency(t, result.TestContext, exportableStubsLibraryModuleName,
			"android_common", exportableSourceStubsLibraryModuleName),
	)
	android.AssertArrayString(t, "exportable source stub library is a static lib of the"+
		"top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName},
		topLevelModule.Module().(*Library).properties.Static_libs)
}