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

Commit 0b555e32 authored by Spandan Das's avatar Spandan Das
Browse files

Create (API) bp2build converters for droidstubs

- The converter runs for api_bp2build, not bp2build workspace
- Since droidstubs is an internal module created by java_sdk_library,
  the conversion encompasses the latter as well
- Since droidstubs do not have an api_surface attribute, this conversion
  uses naming convention to infer the api_surface represented by the api
  file e.g. *stubs.source -> publicapi, *stubs.source.system -> systemapi)
- Also adds an SdkIntraCore enum to represent the API surface provided
  by one core module to another

There is also ongoing work to check in java_api_contribution modules in
Soong. Once we have that, we can update this converter to operate on
that module type instead

Test: go test ./bp2build
Change-Id: Ia85828e04c738d9ffcc524856d7c3034ee29bbf9
parent 067210f7
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -59,8 +59,14 @@ type apiDomain struct {

type apiDomainProperties struct {
	// cc library contributions (.h files/.map.txt) of this API domain
	// This dependency is a no-op in Soong, but the corresponding Bazel target in the bp2build workspace will provide a `CcApiContributionInfo` provider
	// This dependency is a no-op in Soong, but the corresponding Bazel target in the api_bp2build workspace
	// will provide a `CcApiContributionInfo` provider
	Cc_api_contributions []string

	// java library contributions (as .txt) of this API domain
	// This dependency is a no-op in Soong, but the corresponding Bazel target in the api_bp2build workspace
	// will provide a `JavaApiContributionInfo` provider
	Java_api_contributions []string
}

func ApiDomainFactory() Module {
@@ -103,6 +109,7 @@ func contributionBazelAttributes(ctx TopDownMutatorContext, contributions []stri

type bazelApiDomainAttributes struct {
	Cc_api_contributions   bazel.LabelListAttribute
	Java_api_contributions bazel.LabelListAttribute
}

var _ ApiProvider = (*apiDomain)(nil)
@@ -114,6 +121,7 @@ func (a *apiDomain) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
	}
	attrs := &bazelApiDomainAttributes{
		Cc_api_contributions:   contributionBazelAttributes(ctx, a.properties.Cc_api_contributions),
		Java_api_contributions: contributionBazelAttributes(ctx, a.properties.Java_api_contributions),
	}
	ctx.CreateBazelTargetModule(props, CommonAttributes{
		Name: ctx.ModuleName(),
+3 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ const (
	SdkNone
	SdkCore
	SdkCorePlatform
	SdkIntraCore // API surface provided by one core module to another
	SdkPublic
	SdkSystem
	SdkTest
@@ -69,6 +70,8 @@ func (k SdkKind) String() string {
		return "core"
	case SdkCorePlatform:
		return "core_platform"
	case SdkIntraCore:
		return "intracore"
	case SdkModule:
		return "module-lib"
	case SdkSystemServer:
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ bootstrap_go_package {
        "cc_test_conversion_test.go",
        "cc_yasm_conversion_test.go",
        "conversion_test.go",
        "droidstubs_conversion_test.go",
        "filegroup_conversion_test.go",
        "genrule_conversion_test.go",
        "gensrcs_conversion_test.go",
+104 −0
Original line number Diff line number Diff line
// Copyright 2022 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package bp2build

import (
	"testing"

	"android/soong/android"
	"android/soong/java"
)

func registerJavaApiModules(ctx android.RegistrationContext) {
	java.RegisterSdkLibraryBuildComponents(ctx)
	java.RegisterStubsBuildComponents(ctx)
}

func TestDroidstubsApiContributions(t *testing.T) {
	bp := `
	droidstubs {
		name: "framework-stubs",
		check_api: {
			current: {
				api_file: "framework.current.txt",
			},
		},
	}

	// Modules without check_api should not generate a Bazel API target
	droidstubs {
		name: "framework-docs",
	}

	// java_sdk_library is a macro that creates droidstubs
	java_sdk_library {
		name: "module-stubs",
		srcs: ["A.java"],

		// These api surfaces are added by default, but add them explicitly to make
		// this test hermetic
		public: {
			enabled: true,
		},
		system: {
			enabled: true,
		},

		// Disable other api surfaces to keep unit test scope limited
		module_lib: {
			enabled: false,
		},
		test: {
			enabled: false,
		},
	}
	`
	expectedBazelTargets := []string{
		MakeBazelTargetNoRestrictions(
			"java_api_contribution",
			"framework-stubs.contribution",
			AttrNameToString{
				"api":                    `"framework.current.txt"`,
				"api_surface":            `"publicapi"`,
				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
			}),
		MakeBazelTargetNoRestrictions(
			"java_api_contribution",
			"module-stubs.stubs.source.contribution",
			AttrNameToString{
				"api":                    `"api/current.txt"`,
				"api_surface":            `"publicapi"`,
				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
			}),
		MakeBazelTargetNoRestrictions(
			"java_api_contribution",
			"module-stubs.stubs.source.system.contribution",
			AttrNameToString{
				"api":                    `"api/system-current.txt"`,
				"api_surface":            `"systemapi"`,
				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
			}),
	}
	RunApiBp2BuildTestCase(t, registerJavaApiModules, Bp2buildTestCase{
		Blueprint:            bp,
		ExpectedBazelTargets: expectedBazelTargets,
		Filesystem: map[string]string{
			"api/current.txt":        "",
			"api/removed.txt":        "",
			"api/system-current.txt": "",
			"api/system-removed.txt": "",
		},
	})
}
+70 −0
Original line number Diff line number Diff line
@@ -18,11 +18,13 @@ import (
	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strings"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/bazel"
	"android/soong/java/config"
	"android/soong/remoteexec"
)
@@ -834,6 +836,74 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	}
}

var _ android.ApiProvider = (*Droidstubs)(nil)

type bazelJavaApiContributionAttributes struct {
	Api         bazel.LabelAttribute
	Api_surface *string
}

func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
	props := bazel.BazelTargetModuleProperties{
		Rule_class:        "java_api_contribution",
		Bzl_load_location: "//build/bazel/rules/apis:java_api_contribution.bzl",
	}
	apiFile := d.properties.Check_api.Current.Api_file
	// Do not generate a target if check_api is not set
	if apiFile == nil {
		return
	}
	attrs := &bazelJavaApiContributionAttributes{
		Api: *bazel.MakeLabelAttribute(
			android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label,
		),
		Api_surface: proptools.StringPtr(bazelApiSurfaceName(d.Name())),
	}
	ctx.CreateBazelTargetModule(props, android.CommonAttributes{
		Name: android.ApiContributionTargetName(ctx.ModuleName()),
	}, attrs)
}

// TODO (b/262014796): Export the API contributions of CorePlatformApi
// A map to populate the api surface of a droidstub from a substring appearing in its name
// This map assumes that droidstubs (either checked-in or created by java_sdk_library)
// use a strict naming convention
var (
	droidstubsModuleNamingToSdkKind = map[string]android.SdkKind{
		//public is commented out since the core libraries use public in their java_sdk_library names
		"intracore":     android.SdkIntraCore,
		"intra.core":    android.SdkIntraCore,
		"system_server": android.SdkSystemServer,
		"system-server": android.SdkSystemServer,
		"system":        android.SdkSystem,
		"module_lib":    android.SdkModule,
		"module-lib":    android.SdkModule,
		"test":          android.SdkTest,
	}
)

// A helper function that returns the api surface of the corresponding java_api_contribution Bazel target
// The api_surface is populated using the naming convention of the droidstubs module.
func bazelApiSurfaceName(name string) string {
	// Sort the keys so that longer strings appear first
	// Otherwise substrings like system will match both system and system_server
	sortedKeys := make([]string, 0)
	for key := range droidstubsModuleNamingToSdkKind {
		sortedKeys = append(sortedKeys, key)
	}
	sort.Slice(sortedKeys, func(i, j int) bool {
		return len(sortedKeys[i]) > len(sortedKeys[j])
	})
	for _, sortedKey := range sortedKeys {
		if strings.Contains(name, sortedKey) {
			sdkKind := droidstubsModuleNamingToSdkKind[sortedKey]
			return sdkKind.String() + "api"
		}
	}
	// Default is publicapi
	return android.SdkPublic.String() + "api"
}

func StubsDefaultsFactory() android.Module {
	module := &DocDefaults{}

Loading