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

Commit 9b409bcd authored by Jiyong Park's avatar Jiyong Park
Browse files

Create scripts to update and freeze a module SDK

`m <sdk_name>` generates two scripts each of which is use to update the
current snapshot of the SDK and to freeze ToT as a new version,
respectively. Executing the scripts will copy necessary files (stub
libraries, AIDL files, etc.) along with Android.bp into the ./<apiver>
directory under the directory where the sdk is defined.

This change also introduces a new module type 'sdk_snapshot' that
represents a snapshot of an SDK. It will be auto-generated by the above
scripts, so developers are not expected to write this manually.

The module type 'sdk' is now used to simply specify the list of modules
that an SDK has.

Finally, this change changes the version separator from '#' to '@'
because '#' confuses Make.

Bug: 138182343
Test: m

Change-Id: Ifcbc3a39a2f6ad5b4f4b200ba55a1ce3281498cf
parent 8785e55e
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -491,6 +491,7 @@ bootstrap_go_package {
    ],
    ],
    srcs: [
    srcs: [
        "sdk/sdk.go",
        "sdk/sdk.go",
        "sdk/update.go",
    ],
    ],
    testSrcs: [
    testSrcs: [
        "sdk/sdk_test.go",
        "sdk/sdk_test.go",
+12 −19
Original line number Original line Diff line number Diff line
@@ -39,25 +39,17 @@ type SdkRef struct {
	Version string
	Version string
}
}


const (
// Unversioned determines if the SdkRef is referencing to the unversioned SDK module
	// currentVersion refers to the in-development version of an SDK
func (s SdkRef) Unversioned() bool {
	currentVersion = "current"
	return s.Version == ""
)

// IsCurrentVersion determines if the SdkRef is referencing to an in-development version of an SDK
func (s SdkRef) IsCurrentVersion() bool {
	return s.Version == currentVersion
}
}


// IsCurrentVersionOf determines if the SdkRef is referencing to an in-development version of the
// SdkVersionSeparator is a character used to separate an sdk name and its version
// specified SDK
const SdkVersionSeparator = '@'
func (s SdkRef) IsCurrentVersionOf(name string) bool {
	return s.Name == name && s.IsCurrentVersion()
}


// ParseSdkRef parses a `name#version` style string into a corresponding SdkRef struct
// ParseSdkRef parses a `name@version` style string into a corresponding SdkRef struct
func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {
func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {
	tokens := strings.Split(str, "#")
	tokens := strings.Split(str, string(SdkVersionSeparator))
	if len(tokens) < 1 || len(tokens) > 2 {
	if len(tokens) < 1 || len(tokens) > 2 {
		ctx.PropertyErrorf(property, "%q does not follow name#version syntax", str)
		ctx.PropertyErrorf(property, "%q does not follow name#version syntax", str)
		return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"}
		return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"}
@@ -65,7 +57,7 @@ func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {


	name := tokens[0]
	name := tokens[0]


	version := currentVersion // If version is omitted, defaults to "current"
	var version string
	if len(tokens) == 2 {
	if len(tokens) == 2 {
		version = tokens[1]
		version = tokens[1]
	}
	}
@@ -75,6 +67,7 @@ func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {


type SdkRefs []SdkRef
type SdkRefs []SdkRef


// Contains tells if the given SdkRef is in this list of SdkRef's
func (refs SdkRefs) Contains(s SdkRef) bool {
func (refs SdkRefs) Contains(s SdkRef) bool {
	for _, r := range refs {
	for _, r := range refs {
		if r == s {
		if r == s {
@@ -105,7 +98,7 @@ func (s *SdkBase) sdkBase() *SdkBase {
	return s
	return s
}
}


// MakeMemberof sets this module to be a member of a specific SDK
// MakeMemberOf sets this module to be a member of a specific SDK
func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
	s.properties.ContainingSdk = &sdk
	s.properties.ContainingSdk = &sdk
}
}
@@ -120,10 +113,10 @@ func (s *SdkBase) ContainingSdk() SdkRef {
	if s.properties.ContainingSdk != nil {
	if s.properties.ContainingSdk != nil {
		return *s.properties.ContainingSdk
		return *s.properties.ContainingSdk
	}
	}
	return SdkRef{Name: "", Version: currentVersion}
	return SdkRef{Name: "", Version: ""}
}
}


// Membername returns the name of the module that this SDK member is overriding
// MemberName returns the name of the module that this SDK member is overriding
func (s *SdkBase) MemberName() string {
func (s *SdkBase) MemberName() string {
	return proptools.String(s.properties.Sdk_member_name)
	return proptools.String(s.properties.Sdk_member_name)
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -145,7 +145,7 @@ func (j *TestHelperLibrary) AndroidMkEntries() android.AndroidMkEntries {
}
}


func (prebuilt *Import) AndroidMkEntries() android.AndroidMkEntries {
func (prebuilt *Import) AndroidMkEntries() android.AndroidMkEntries {
	if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().IsCurrentVersion() {
	if !prebuilt.IsForPlatform() || !prebuilt.ContainingSdk().Unversioned() {
		return android.AndroidMkEntries{
		return android.AndroidMkEntries{
			Disabled: true,
			Disabled: true,
		}
		}
+66 −7
Original line number Original line Diff line number Diff line
@@ -15,6 +15,9 @@
package sdk
package sdk


import (
import (
	"fmt"
	"strconv"

	"github.com/google/blueprint"
	"github.com/google/blueprint"


	"android/soong/android"
	"android/soong/android"
@@ -25,6 +28,7 @@ import (


func init() {
func init() {
	android.RegisterModuleType("sdk", ModuleFactory)
	android.RegisterModuleType("sdk", ModuleFactory)
	android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
	android.PreDepsMutators(RegisterPreDepsMutators)
	android.PreDepsMutators(RegisterPreDepsMutators)
	android.PostDepsMutators(RegisterPostDepsMutators)
	android.PostDepsMutators(RegisterPostDepsMutators)
}
}
@@ -34,12 +38,18 @@ type sdk struct {
	android.DefaultableModuleBase
	android.DefaultableModuleBase


	properties sdkProperties
	properties sdkProperties

	updateScript android.OutputPath
	freezeScript android.OutputPath
}
}


type sdkProperties struct {
type sdkProperties struct {
	// The list of java_import modules that provide Java stubs for this SDK
	// The list of java libraries in this SDK
	Java_libs []string
	Java_libs []string
	// The list of native libraries in this SDK
	Native_shared_libs []string
	Native_shared_libs []string

	Snapshot bool `blueprint:"mutated"`
}
}


// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
@@ -52,8 +62,44 @@ func ModuleFactory() android.Module {
	return s
	return s
}
}


// sdk_snapshot is a versioned snapshot of an SDK. This is an auto-generated module.
func SnapshotModuleFactory() android.Module {
	s := ModuleFactory()
	s.(*sdk).properties.Snapshot = true
	return s
}

func (s *sdk) snapshot() bool {
	return s.properties.Snapshot
}

func (s *sdk) frozenVersions(ctx android.BaseModuleContext) []string {
	if s.snapshot() {
		panic(fmt.Errorf("frozenVersions() called for sdk_snapshot %q", ctx.ModuleName()))
	}
	versions := []string{}
	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
		depTag := ctx.OtherModuleDependencyTag(child)
		if depTag == sdkMemberDepTag {
			return true
		}
		if versionedDepTag, ok := depTag.(sdkMemberVesionedDepTag); ok {
			v := versionedDepTag.version
			if v != "current" && !android.InList(v, versions) {
				versions = append(versions, versionedDepTag.version)
			}
		}
		return false
	})
	return android.SortedUniqueStrings(versions)
}

func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	// TODO(jiyong): add build rules for creating stubs from members of this SDK
	s.buildSnapshotGenerationScripts(ctx)
}

func (s *sdk) AndroidMkEntries() android.AndroidMkEntries {
	return s.androidMkEntriesForScript()
}
}


// RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
// RegisterPreDepsMutators registers pre-deps mutators to support modules implementing SdkAware
@@ -112,8 +158,21 @@ func memberMutator(mctx android.BottomUpMutatorContext) {


// Step 2: record that dependencies of SDK modules are members of the SDK modules
// Step 2: record that dependencies of SDK modules are members of the SDK modules
func memberDepsMutator(mctx android.TopDownMutatorContext) {
func memberDepsMutator(mctx android.TopDownMutatorContext) {
	if _, ok := mctx.Module().(*sdk); ok {
	if s, ok := mctx.Module().(*sdk); ok {
		mySdkRef := android.ParseSdkRef(mctx, mctx.ModuleName(), "name")
		mySdkRef := android.ParseSdkRef(mctx, mctx.ModuleName(), "name")
		if s.snapshot() && mySdkRef.Unversioned() {
			mctx.PropertyErrorf("name", "sdk_snapshot should be named as <name>@<version>. "+
				"Did you manually modify Android.bp?")
		}
		if !s.snapshot() && !mySdkRef.Unversioned() {
			mctx.PropertyErrorf("name", "sdk shouldn't be named as <name>@<version>.")
		}
		if mySdkRef.Version != "" && mySdkRef.Version != "current" {
			if _, err := strconv.Atoi(mySdkRef.Version); err != nil {
				mctx.PropertyErrorf("name", "version %q is neither a number nor \"current\"", mySdkRef.Version)
			}
		}

		mctx.VisitDirectDeps(func(child android.Module) {
		mctx.VisitDirectDeps(func(child android.Module) {
			if member, ok := child.(android.SdkAware); ok {
			if member, ok := child.(android.SdkAware); ok {
				member.MakeMemberOf(mySdkRef)
				member.MakeMemberOf(mySdkRef)
@@ -122,7 +181,7 @@ func memberDepsMutator(mctx android.TopDownMutatorContext) {
	}
	}
}
}


// Step 3: create dependencies from the in-development version of an SDK member to frozen versions
// Step 3: create dependencies from the unversioned SDK member to snapshot versions
// of the same member. By having these dependencies, they are mutated for multiple Mainline modules
// of the same member. By having these dependencies, they are mutated for multiple Mainline modules
// (apex and apk), each of which might want different sdks to be built with. For example, if both
// (apex and apk), each of which might want different sdks to be built with. For example, if both
// apex A and B are referencing libfoo which is a member of sdk 'mysdk', the two APEXes can be
// apex A and B are referencing libfoo which is a member of sdk 'mysdk', the two APEXes can be
@@ -130,7 +189,7 @@ func memberDepsMutator(mctx android.TopDownMutatorContext) {
// using.
// using.
func memberInterVersionMutator(mctx android.BottomUpMutatorContext) {
func memberInterVersionMutator(mctx android.BottomUpMutatorContext) {
	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
		if !m.ContainingSdk().IsCurrentVersion() {
		if !m.ContainingSdk().Unversioned() {
			memberName := m.MemberName()
			memberName := m.MemberName()
			tag := sdkMemberVesionedDepTag{member: memberName, version: m.ContainingSdk().Version}
			tag := sdkMemberVesionedDepTag{member: memberName, version: m.ContainingSdk().Version}
			mctx.AddReverseDependency(mctx.Module(), tag, memberName)
			mctx.AddReverseDependency(mctx.Module(), tag, memberName)
@@ -159,7 +218,7 @@ func sdkDepsMutator(mctx android.TopDownMutatorContext) {
// versioned module is used instead of the un-versioned (in-development) module libfoo
// versioned module is used instead of the un-versioned (in-development) module libfoo
func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
func sdkDepsReplaceMutator(mctx android.BottomUpMutatorContext) {
	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
	if m, ok := mctx.Module().(android.SdkAware); ok && m.IsInAnySdk() {
		if sdk := m.ContainingSdk(); !sdk.IsCurrentVersion() {
		if sdk := m.ContainingSdk(); !sdk.Unversioned() {
			if m.RequiredSdks().Contains(sdk) {
			if m.RequiredSdks().Contains(sdk) {
				// Note that this replacement is done only for the modules that have the same
				// Note that this replacement is done only for the modules that have the same
				// variations as the current module. Since current module is already mutated for
				// variations as the current module. Since current module is already mutated for
+21 −10
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ func testSdkContext(t *testing.T, bp string) (*android.TestContext, android.Conf


	// from this package
	// from this package
	ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
	ctx.RegisterModuleType("sdk", android.ModuleFactoryAdaptor(ModuleFactory))
	ctx.RegisterModuleType("sdk_snapshot", android.ModuleFactoryAdaptor(SnapshotModuleFactory))
	ctx.PreDepsMutators(RegisterPreDepsMutators)
	ctx.PreDepsMutators(RegisterPreDepsMutators)
	ctx.PostDepsMutators(RegisterPostDepsMutators)
	ctx.PostDepsMutators(RegisterPostDepsMutators)


@@ -155,12 +156,17 @@ func pathsToStrings(paths android.Paths) []string {
func TestBasicSdkWithJava(t *testing.T) {
func TestBasicSdkWithJava(t *testing.T) {
	ctx, _ := testSdk(t, `
	ctx, _ := testSdk(t, `
		sdk {
		sdk {
			name: "mysdk#1",
			name: "mysdk",
			java_libs: ["sdkmember"],
		}

		sdk_snapshot {
			name: "mysdk@1",
			java_libs: ["sdkmember_mysdk_1"],
			java_libs: ["sdkmember_mysdk_1"],
		}
		}


		sdk {
		sdk_snapshot {
			name: "mysdk#2",
			name: "mysdk@2",
			java_libs: ["sdkmember_mysdk_2"],
			java_libs: ["sdkmember_mysdk_2"],
		}
		}


@@ -195,7 +201,7 @@ func TestBasicSdkWithJava(t *testing.T) {
		apex {
		apex {
			name: "myapex",
			name: "myapex",
			java_libs: ["myjavalib"],
			java_libs: ["myjavalib"],
			uses_sdks: ["mysdk#1"],
			uses_sdks: ["mysdk@1"],
			key: "myapex.key",
			key: "myapex.key",
			certificate: ":myapex.cert",
			certificate: ":myapex.cert",
		}
		}
@@ -203,7 +209,7 @@ func TestBasicSdkWithJava(t *testing.T) {
		apex {
		apex {
			name: "myapex2",
			name: "myapex2",
			java_libs: ["myjavalib"],
			java_libs: ["myjavalib"],
			uses_sdks: ["mysdk#2"],
			uses_sdks: ["mysdk@2"],
			key: "myapex.key",
			key: "myapex.key",
			certificate: ":myapex.cert",
			certificate: ":myapex.cert",
		}
		}
@@ -223,12 +229,17 @@ func TestBasicSdkWithJava(t *testing.T) {
func TestBasicSdkWithCc(t *testing.T) {
func TestBasicSdkWithCc(t *testing.T) {
	ctx, _ := testSdk(t, `
	ctx, _ := testSdk(t, `
		sdk {
		sdk {
			name: "mysdk#1",
			name: "mysdk",
			native_shared_libs: ["sdkmember"],
		}

		sdk_snapshot {
			name: "mysdk@1",
			native_shared_libs: ["sdkmember_mysdk_1"],
			native_shared_libs: ["sdkmember_mysdk_1"],
		}
		}


		sdk {
		sdk_snapshot {
			name: "mysdk#2",
			name: "mysdk@2",
			native_shared_libs: ["sdkmember_mysdk_2"],
			native_shared_libs: ["sdkmember_mysdk_2"],
		}
		}


@@ -267,7 +278,7 @@ func TestBasicSdkWithCc(t *testing.T) {
		apex {
		apex {
			name: "myapex",
			name: "myapex",
			native_shared_libs: ["mycpplib"],
			native_shared_libs: ["mycpplib"],
			uses_sdks: ["mysdk#1"],
			uses_sdks: ["mysdk@1"],
			key: "myapex.key",
			key: "myapex.key",
			certificate: ":myapex.cert",
			certificate: ":myapex.cert",
		}
		}
@@ -275,7 +286,7 @@ func TestBasicSdkWithCc(t *testing.T) {
		apex {
		apex {
			name: "myapex2",
			name: "myapex2",
			native_shared_libs: ["mycpplib"],
			native_shared_libs: ["mycpplib"],
			uses_sdks: ["mysdk#2"],
			uses_sdks: ["mysdk@2"],
			key: "myapex.key",
			key: "myapex.key",
			certificate: ":myapex.cert",
			certificate: ":myapex.cert",
		}
		}
Loading