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

Commit d1063c15 authored by Jiyong Park's avatar Jiyong Park
Browse files

Introduce module type 'sdk'

This change introduces a new module type named 'sdk'. It is a logical
group of prebuilt modules that together provide a context (e.g. APIs)
in which Mainline modules (such as APEXes) are built.

A prebuilt module (e.g. java_import) can join an sdk by adding it to the
sdk module as shown below:

sdk {
    name: "mysdk#20",
    java_libs: ["myjavalib_mysdk_20"],
}

java_import {
    name: "myjavalib_mysdk_20",
    srcs: ["myjavalib-v20.jar"],
    sdk_member_name: "myjavalib",
}

sdk {
    name: "mysdk#21",
    java_libs: ["myjavalib_mysdk_21"],
}

java_import {
    name: "myjavalib_mysdk_21",
    srcs: ["myjavalib-v21.jar"],
    sdk_member_name: "myjavalib",
}

java_library {
    name: "myjavalib",
    srcs: ["**/*/*.java"],
}

An APEX can specify the SDK(s) that it wants to build with via the new
'uses_sdks' property.

apex {
    name: "myapex",
    java_libs: ["libX", "libY"],
    uses_sdks: ["mysdk#20"],
}

With this, libX, libY, and their transitive dependencies are all built
with the version 20 of myjavalib (the first java_import module) instead
of the other one (which is for version 21) and java_library having the
same name (which is for ToT).

Bug: 138182343
Test: m (sdk_test.go added)
Change-Id: I7e14c524a7d6a0d9f575fb20822080f39818c01e
parent 1f6c94a3
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ bootstrap_go_package {
        "android/proto.go",
        "android/register.go",
        "android/rule_builder.go",
        "android/sdk.go",
        "android/sh_binary.go",
        "android/singleton.go",
        "android/testing.go",
@@ -474,6 +475,26 @@ bootstrap_go_package {
    pluginFor: ["soong_build"],
}

bootstrap_go_package {
    name: "soong-sdk",
    pkgPath: "android/soong/sdk",
    deps: [
        "blueprint",
        "soong",
        "soong-android",
        "soong-apex",
        "soong-cc",
        "soong-java",
    ],
    srcs: [
        "sdk/sdk.go",
    ],
    testSrcs: [
        "sdk/sdk_test.go",
    ],
    pluginFor: ["soong_build"],
}

//
// Defaults to enable various configurations of host bionic
//

android/sdk.go

0 → 100644
+146 −0
Original line number Diff line number Diff line
// Copyright (C) 2019 The Android Open Source Project
//
// 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 android

import (
	"strings"

	"github.com/google/blueprint/proptools"
)

// SdkAware is the interface that must be supported by any module to become a member of SDK or to be
// built with SDK
type SdkAware interface {
	Module
	sdkBase() *SdkBase
	MakeMemberOf(sdk SdkRef)
	IsInAnySdk() bool
	ContainingSdk() SdkRef
	MemberName() string
	BuildWithSdks(sdks SdkRefs)
	RequiredSdks() SdkRefs
}

// SdkRef refers to a version of an SDK
type SdkRef struct {
	Name    string
	Version string
}

const (
	// currentVersion refers to the in-development version of an SDK
	currentVersion = "current"
)

// 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
// specified SDK
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
func ParseSdkRef(ctx BaseModuleContext, str string, property string) SdkRef {
	tokens := strings.Split(str, "#")
	if len(tokens) < 1 || len(tokens) > 2 {
		ctx.PropertyErrorf(property, "%q does not follow name#version syntax", str)
		return SdkRef{Name: "invalid sdk name", Version: "invalid sdk version"}
	}

	name := tokens[0]

	version := currentVersion // If version is omitted, defaults to "current"
	if len(tokens) == 2 {
		version = tokens[1]
	}

	return SdkRef{Name: name, Version: version}
}

type SdkRefs []SdkRef

func (refs SdkRefs) Contains(s SdkRef) bool {
	for _, r := range refs {
		if r == s {
			return true
		}
	}
	return false
}

type sdkProperties struct {
	// The SDK that this module is a member of. nil if it is not a member of any SDK
	ContainingSdk *SdkRef `blueprint:"mutated"`

	// The list of SDK names and versions that are used to build this module
	RequiredSdks SdkRefs `blueprint:"mutated"`

	// Name of the module that this sdk member is representing
	Sdk_member_name *string
}

// SdkBase is a struct that is expected to be included in module types to implement the SdkAware
// interface. InitSdkAwareModule should be called to initialize this struct.
type SdkBase struct {
	properties sdkProperties
}

func (s *SdkBase) sdkBase() *SdkBase {
	return s
}

// MakeMemberof sets this module to be a member of a specific SDK
func (s *SdkBase) MakeMemberOf(sdk SdkRef) {
	s.properties.ContainingSdk = &sdk
}

// IsInAnySdk returns true if this module is a member of any SDK
func (s *SdkBase) IsInAnySdk() bool {
	return s.properties.ContainingSdk != nil
}

// ContainingSdk returns the SDK that this module is a member of
func (s *SdkBase) ContainingSdk() SdkRef {
	if s.properties.ContainingSdk != nil {
		return *s.properties.ContainingSdk
	}
	return SdkRef{Name: "", Version: currentVersion}
}

// Membername returns the name of the module that this SDK member is overriding
func (s *SdkBase) MemberName() string {
	return proptools.String(s.properties.Sdk_member_name)
}

// BuildWithSdks is used to mark that this module has to be built with the given SDK(s).
func (s *SdkBase) BuildWithSdks(sdks SdkRefs) {
	s.properties.RequiredSdks = sdks
}

// RequiredSdks returns the SDK(s) that this module has to be built with
func (s *SdkBase) RequiredSdks() SdkRefs {
	return s.properties.RequiredSdks
}

// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
// SdkBase.
func InitSdkAwareModule(m SdkAware) {
	base := m.sdkBase()
	m.AddProperties(&base.properties)
}
+28 −8
Original line number Diff line number Diff line
@@ -185,7 +185,7 @@ func init() {
	pctx.HostBinToolVariable("zipalign", "zipalign")
	pctx.HostBinToolVariable("jsonmodify", "jsonmodify")

	android.RegisterModuleType("apex", apexBundleFactory)
	android.RegisterModuleType("apex", BundleFactory)
	android.RegisterModuleType("apex_test", testApexBundleFactory)
	android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
	android.RegisterModuleType("apex_defaults", defaultsFactory)
@@ -195,12 +195,14 @@ func init() {
		ctx.TopDown("apex_vndk_gather", apexVndkGatherMutator).Parallel()
		ctx.BottomUp("apex_vndk_add_deps", apexVndkAddDepsMutator).Parallel()
	})
	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
	android.PostDepsMutators(RegisterPostDepsMutators)
}

func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
	ctx.TopDown("apex_deps", apexDepsMutator)
	ctx.BottomUp("apex", apexMutator).Parallel()
	ctx.BottomUp("apex_flattened", apexFlattenedMutator).Parallel()
	ctx.BottomUp("apex_uses", apexUsesMutator).Parallel()
	})
}

var (
@@ -409,6 +411,12 @@ type apexBundleProperties struct {
	// To distinguish between flattened and non-flattened variants.
	// if set true, then this variant is flattened variant.
	Flattened bool `blueprint:"mutated"`

	// List of SDKs that are used to build this APEX. A reference to an SDK should be either
	// `name#version` or `name` which is an alias for `name#current`. If left empty, `platform#current`
	// is implied. This value affects all modules included in this APEX. In other words, they are
	// also built with the SDKs specified here.
	Uses_sdks []string
}

type apexTargetBundleProperties struct {
@@ -535,6 +543,7 @@ type apexFile struct {
type apexBundle struct {
	android.ModuleBase
	android.DefaultableModuleBase
	android.SdkBase

	properties       apexBundleProperties
	targetProperties apexTargetBundleProperties
@@ -737,6 +746,16 @@ func (a *apexBundle) DepsMutator(ctx android.BottomUpMutatorContext) {
	if cert != "" {
		ctx.AddDependency(ctx.Module(), certificateTag, cert)
	}

	// TODO(jiyong): ensure that all apexes are with non-empty uses_sdks
	if len(a.properties.Uses_sdks) > 0 {
		sdkRefs := []android.SdkRef{}
		for _, str := range a.properties.Uses_sdks {
			parsed := android.ParseSdkRef(ctx, str, "uses_sdks")
			sdkRefs = append(sdkRefs, parsed)
		}
		a.BuildWithSdks(sdkRefs)
	}
}

func (a *apexBundle) getCertString(ctx android.BaseModuleContext) string {
@@ -1706,6 +1725,7 @@ func newApexBundle() *apexBundle {
	})
	android.InitAndroidMultiTargetsArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
	android.InitDefaultableModule(module)
	android.InitSdkAwareModule(module)
	return module
}

@@ -1721,7 +1741,7 @@ func testApexBundleFactory() android.Module {
	return bundle
}

func apexBundleFactory() android.Module {
func BundleFactory() android.Module {
	return newApexBundle()
}

+2 −2
Original line number Diff line number Diff line
@@ -96,10 +96,10 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr
	config.TestProductVariables.Platform_vndk_version = proptools.StringPtr("VER")

	ctx := android.NewTestArchContext()
	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(apexBundleFactory))
	ctx.RegisterModuleType("apex", android.ModuleFactoryAdaptor(BundleFactory))
	ctx.RegisterModuleType("apex_test", android.ModuleFactoryAdaptor(testApexBundleFactory))
	ctx.RegisterModuleType("apex_vndk", android.ModuleFactoryAdaptor(vndkApexBundleFactory))
	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(apexKeyFactory))
	ctx.RegisterModuleType("apex_key", android.ModuleFactoryAdaptor(ApexKeyFactory))
	ctx.RegisterModuleType("apex_defaults", android.ModuleFactoryAdaptor(defaultsFactory))
	ctx.RegisterModuleType("prebuilt_apex", android.ModuleFactoryAdaptor(PrebuiltFactory))

+2 −2
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ import (
var String = proptools.String

func init() {
	android.RegisterModuleType("apex_key", apexKeyFactory)
	android.RegisterModuleType("apex_key", ApexKeyFactory)
	android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
}

@@ -53,7 +53,7 @@ type apexKeyProperties struct {
	Installable *bool
}

func apexKeyFactory() android.Module {
func ApexKeyFactory() android.Module {
	module := &apexKey{}
	module.AddProperties(&module.properties)
	android.InitAndroidArchModule(module, android.HostAndDeviceDefault, android.MultilibCommon)
Loading