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

Commit fb6d7812 authored by Colin Cross's avatar Colin Cross
Browse files

Split out sdk.go from java.go

Split out SDK handling functions from java.go to sdk.go and tests
from java_test.go to sdk.go.

Test: sdk_test.go
Change-Id: I83ef48cbe5230572c1d4ecc0e89021d2f7c71b76
parent c33514e3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ bootstrap_go_package {
        "java/java_resources.go",
        "java/prebuilt_apis.go",
        "java/proto.go",
        "java/sdk.go",
        "java/sdk_library.go",
        "java/support_libraries.go",
        "java/system_modules.go",
@@ -258,6 +259,7 @@ bootstrap_go_package {
        "java/dexpreopt_test.go",
        "java/java_test.go",
        "java/jdeps_test.go",
        "java/sdk_test.go",
    ],
    pluginFor: ["soong_build"],
}
+0 −148
Original line number Diff line number Diff line
@@ -430,154 +430,6 @@ func (j *Module) targetSdkVersion() string {
	return j.sdkVersion()
}

type sdkContext interface {
	// sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
	sdkVersion() string
	// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
	minSdkVersion() string
	// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
	targetSdkVersion() string
}

func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
	switch v {
	case "", "current", "system_current", "test_current", "core_current":
		return ctx.Config().DefaultAppTargetSdk()
	default:
		return v
	}
}

// Returns a sdk version as a number.  For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns android.FutureApiLevel (10000).
func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
	switch v {
	case "", "current", "test_current", "system_current", "core_current":
		return ctx.Config().DefaultAppTargetSdkInt(), nil
	default:
		n := android.GetNumericSdkVersion(v)
		if i, err := strconv.Atoi(n); err != nil {
			return -1, fmt.Errorf("invalid sdk version %q", n)
		} else {
			return i, nil
		}
	}
}

func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) {
	n, err := sdkVersionToNumber(ctx, v)
	if err != nil {
		return "", err
	}
	return strconv.Itoa(n), nil
}

func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep {
	v := sdkContext.sdkVersion()
	i, err := sdkVersionToNumber(ctx, v)
	if err != nil {
		ctx.PropertyErrorf("sdk_version", "%s", err)
		return sdkDep{}
	}

	// Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
	// or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
	if strings.HasPrefix(v, "system_") && i != android.FutureApiLevel {
		allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
		if ctx.DeviceSpecific() || ctx.SocSpecific() {
			if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
				allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
			}
		}
		version := strings.TrimPrefix(v, "system_")
		if len(allowed_versions) > 0 && !android.InList(version, allowed_versions) {
			ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
				v, allowed_versions)
		}
	}

	toPrebuilt := func(sdk string) sdkDep {
		var api, v string
		if strings.Contains(sdk, "_") {
			t := strings.Split(sdk, "_")
			api = t[0]
			v = t[1]
		} else {
			api = "public"
			v = sdk
		}
		dir := filepath.Join("prebuilts", "sdk", v, api)
		jar := filepath.Join(dir, "android.jar")
		// There's no aidl for other SDKs yet.
		// TODO(77525052): Add aidl files for other SDKs too.
		public_dir := filepath.Join("prebuilts", "sdk", v, "public")
		aidl := filepath.Join(public_dir, "framework.aidl")
		jarPath := android.ExistentPathForSource(ctx, jar)
		aidlPath := android.ExistentPathForSource(ctx, aidl)
		lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath)

		if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
			return sdkDep{
				invalidVersion: true,
				modules:        []string{fmt.Sprintf("sdk_%s_%s_android", api, v)},
			}
		}

		if !jarPath.Valid() {
			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
			return sdkDep{}
		}

		if !aidlPath.Valid() {
			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
			return sdkDep{}
		}

		return sdkDep{
			useFiles: true,
			jars:     android.Paths{jarPath.Path(), lambdaStubsPath},
			aidl:     aidlPath.Path(),
		}
	}

	toModule := func(m, r string) sdkDep {
		ret := sdkDep{
			useModule:          true,
			modules:            []string{m, config.DefaultLambdaStubsLibrary},
			systemModules:      m + "_system_modules",
			frameworkResModule: r,
		}
		if m == "core.current.stubs" {
			ret.systemModules = "core-system-modules"
		} else if m == "core.platform.api.stubs" {
			ret.systemModules = "core-platform-api-stubs-system-modules"
		}
		return ret
	}

	if ctx.Config().UnbundledBuildPrebuiltSdks() && v != "" {
		return toPrebuilt(v)
	}

	switch v {
	case "":
		return sdkDep{
			useDefaultLibs:     true,
			frameworkResModule: "framework-res",
		}
	case "current":
		return toModule("android_stubs_current", "framework-res")
	case "system_current":
		return toModule("android_system_stubs_current", "framework-res")
	case "test_current":
		return toModule("android_test_stubs_current", "framework-res")
	case "core_current":
		return toModule("core.current.stubs", "")
	default:
		return toPrebuilt(v)
	}
}

func (j *Module) deps(ctx android.BottomUpMutatorContext) {
	if ctx.Device() {
		if !Bool(j.properties.No_standard_libs) {
+0 −238
Original line number Diff line number Diff line
@@ -19,13 +19,10 @@ import (
	"io/ioutil"
	"os"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"
	"testing"

	"github.com/google/blueprint/proptools"

	"android/soong/android"
	"android/soong/cc"
	"android/soong/genrule"
@@ -354,241 +351,6 @@ func TestBinary(t *testing.T) {

}

var classpathTestcases = []struct {
	name          string
	unbundled     bool
	moduleType    string
	host          android.OsClass
	properties    string
	bootclasspath []string
	system        string
	classpath     []string
}{
	{
		name:          "default",
		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
		system:        "core-platform-api-stubs-system-modules",
		classpath:     []string{"ext", "framework"},
	},
	{
		name:          "blank sdk version",
		properties:    `sdk_version: "",`,
		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
		system:        "core-platform-api-stubs-system-modules",
		classpath:     []string{"ext", "framework"},
	},
	{

		name:          "sdk v14",
		properties:    `sdk_version: "14",`,
		bootclasspath: []string{`""`},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
		classpath:     []string{"prebuilts/sdk/14/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
	},
	{

		name:          "current",
		properties:    `sdk_version: "current",`,
		bootclasspath: []string{"android_stubs_current", "core-lambda-stubs"},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
	},
	{

		name:          "system_current",
		properties:    `sdk_version: "system_current",`,
		bootclasspath: []string{"android_system_stubs_current", "core-lambda-stubs"},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
	},
	{

		name:          "system_14",
		properties:    `sdk_version: "system_14",`,
		bootclasspath: []string{`""`},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
		classpath:     []string{"prebuilts/sdk/14/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
	},
	{

		name:          "test_current",
		properties:    `sdk_version: "test_current",`,
		bootclasspath: []string{"android_test_stubs_current", "core-lambda-stubs"},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
	},
	{

		name:          "core_current",
		properties:    `sdk_version: "core_current",`,
		bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
	},
	{

		name:          "nostdlib",
		properties:    `no_standard_libs: true, system_modules: "none"`,
		system:        "none",
		bootclasspath: []string{`""`},
		classpath:     []string{},
	},
	{

		name:          "nostdlib system_modules",
		properties:    `no_standard_libs: true, system_modules: "core-platform-api-stubs-system-modules"`,
		system:        "core-platform-api-stubs-system-modules",
		bootclasspath: []string{`""`},
		classpath:     []string{},
	},
	{

		name:          "host default",
		moduleType:    "java_library_host",
		properties:    ``,
		host:          android.Host,
		bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
		classpath:     []string{},
	},
	{
		name:       "host nostdlib",
		moduleType: "java_library_host",
		host:       android.Host,
		properties: `no_standard_libs: true`,
		classpath:  []string{},
	},
	{

		name:          "host supported default",
		host:          android.Host,
		properties:    `host_supported: true,`,
		classpath:     []string{},
		bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
	},
	{
		name:       "host supported nostdlib",
		host:       android.Host,
		properties: `host_supported: true, no_standard_libs: true, system_modules: "none"`,
		classpath:  []string{},
	},
	{

		name:          "unbundled sdk v14",
		unbundled:     true,
		properties:    `sdk_version: "14",`,
		bootclasspath: []string{`""`},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
		classpath:     []string{"prebuilts/sdk/14/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
	},
	{

		name:          "unbundled current",
		unbundled:     true,
		properties:    `sdk_version: "current",`,
		bootclasspath: []string{`""`},
		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
		classpath:     []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
	},
}

func TestClasspath(t *testing.T) {
	for _, testcase := range classpathTestcases {
		t.Run(testcase.name, func(t *testing.T) {
			moduleType := "java_library"
			if testcase.moduleType != "" {
				moduleType = testcase.moduleType
			}

			bp := moduleType + ` {
				name: "foo",
				srcs: ["a.java"],
				` + testcase.properties + `
			}`

			variant := "android_common"
			if testcase.host == android.Host {
				variant = android.BuildOs.String() + "_common"
			}

			convertModulesToPaths := func(cp []string) []string {
				ret := make([]string, len(cp))
				for i, e := range cp {
					ret[i] = moduleToPath(e)
				}
				return ret
			}

			bootclasspath := convertModulesToPaths(testcase.bootclasspath)
			classpath := convertModulesToPaths(testcase.classpath)

			bc := strings.Join(bootclasspath, ":")
			if bc != "" {
				bc = "-bootclasspath " + bc
			}

			c := strings.Join(classpath, ":")
			if c != "" {
				c = "-classpath " + c
			}
			system := ""
			if testcase.system == "none" {
				system = "--system=none"
			} else if testcase.system != "" {
				system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system") + "/"
			}

			t.Run("1.8", func(t *testing.T) {
				// Test default javac 1.8
				config := testConfig(nil)
				if testcase.unbundled {
					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
				}
				ctx := testContext(config, bp, nil)
				run(t, ctx, config)

				javac := ctx.ModuleForTests("foo", variant).Rule("javac")

				got := javac.Args["bootClasspath"]
				if got != bc {
					t.Errorf("bootclasspath expected %q != got %q", bc, got)
				}

				got = javac.Args["classpath"]
				if got != c {
					t.Errorf("classpath expected %q != got %q", c, got)
				}

				var deps []string
				if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
					deps = append(deps, bootclasspath...)
				}
				deps = append(deps, classpath...)

				if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
					t.Errorf("implicits expected %q != got %q", deps, javac.Implicits.Strings())
				}
			})

			// Test again with javac 1.9
			t.Run("1.9", func(t *testing.T) {
				config := testConfig(map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"})
				if testcase.unbundled {
					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
				}
				ctx := testContext(config, bp, nil)
				run(t, ctx, config)

				javac := ctx.ModuleForTests("foo", variant).Rule("javac")
				got := javac.Args["bootClasspath"]
				expected := system
				if testcase.system == "bootclasspath" {
					expected = bc
				}
				if got != expected {
					t.Errorf("bootclasspath expected %q != got %q", expected, got)
				}
			})
		})
	}

}

func TestPrebuilts(t *testing.T) {
	ctx := testJava(t, `
		java_library {

java/sdk.go

0 → 100644
+172 −0
Original line number Diff line number Diff line
// Copyright 2019 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 java

import (
	"android/soong/android"
	"android/soong/java/config"
	"fmt"
	"path/filepath"
	"strconv"
	"strings"
)

type sdkContext interface {
	// sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
	sdkVersion() string
	// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
	minSdkVersion() string
	// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
	targetSdkVersion() string
}

func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
	switch v {
	case "", "current", "system_current", "test_current", "core_current":
		return ctx.Config().DefaultAppTargetSdk()
	default:
		return v
	}
}

// Returns a sdk version as a number.  For modules targeting an unreleased SDK (meaning it does not yet have a number)
// it returns android.FutureApiLevel (10000).
func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
	switch v {
	case "", "current", "test_current", "system_current", "core_current":
		return ctx.Config().DefaultAppTargetSdkInt(), nil
	default:
		n := android.GetNumericSdkVersion(v)
		if i, err := strconv.Atoi(n); err != nil {
			return -1, fmt.Errorf("invalid sdk version %q", n)
		} else {
			return i, nil
		}
	}
}

func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) {
	n, err := sdkVersionToNumber(ctx, v)
	if err != nil {
		return "", err
	}
	return strconv.Itoa(n), nil
}

func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep {
	v := sdkContext.sdkVersion()
	i, err := sdkVersionToNumber(ctx, v)
	if err != nil {
		ctx.PropertyErrorf("sdk_version", "%s", err)
		return sdkDep{}
	}

	// Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
	// or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
	if strings.HasPrefix(v, "system_") && i != android.FutureApiLevel {
		allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
		if ctx.DeviceSpecific() || ctx.SocSpecific() {
			if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
				allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
			}
		}
		version := strings.TrimPrefix(v, "system_")
		if len(allowed_versions) > 0 && !android.InList(version, allowed_versions) {
			ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
				v, allowed_versions)
		}
	}

	toPrebuilt := func(sdk string) sdkDep {
		var api, v string
		if strings.Contains(sdk, "_") {
			t := strings.Split(sdk, "_")
			api = t[0]
			v = t[1]
		} else {
			api = "public"
			v = sdk
		}
		dir := filepath.Join("prebuilts", "sdk", v, api)
		jar := filepath.Join(dir, "android.jar")
		// There's no aidl for other SDKs yet.
		// TODO(77525052): Add aidl files for other SDKs too.
		public_dir := filepath.Join("prebuilts", "sdk", v, "public")
		aidl := filepath.Join(public_dir, "framework.aidl")
		jarPath := android.ExistentPathForSource(ctx, jar)
		aidlPath := android.ExistentPathForSource(ctx, aidl)
		lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath)

		if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
			return sdkDep{
				invalidVersion: true,
				modules:        []string{fmt.Sprintf("sdk_%s_%s_android", api, v)},
			}
		}

		if !jarPath.Valid() {
			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
			return sdkDep{}
		}

		if !aidlPath.Valid() {
			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
			return sdkDep{}
		}

		return sdkDep{
			useFiles: true,
			jars:     android.Paths{jarPath.Path(), lambdaStubsPath},
			aidl:     aidlPath.Path(),
		}
	}

	toModule := func(m, r string) sdkDep {
		ret := sdkDep{
			useModule:          true,
			modules:            []string{m, config.DefaultLambdaStubsLibrary},
			systemModules:      m + "_system_modules",
			frameworkResModule: r,
		}
		if m == "core.current.stubs" {
			ret.systemModules = "core-system-modules"
		} else if m == "core.platform.api.stubs" {
			ret.systemModules = "core-platform-api-stubs-system-modules"
		}
		return ret
	}

	if ctx.Config().UnbundledBuildPrebuiltSdks() && v != "" {
		return toPrebuilt(v)
	}

	switch v {
	case "":
		return sdkDep{
			useDefaultLibs:     true,
			frameworkResModule: "framework-res",
		}
	case "current":
		return toModule("android_stubs_current", "framework-res")
	case "system_current":
		return toModule("android_system_stubs_current", "framework-res")
	case "test_current":
		return toModule("android_test_stubs_current", "framework-res")
	case "core_current":
		return toModule("core.current.stubs", "")
	default:
		return toPrebuilt(v)
	}
}

java/sdk_test.go

0 → 100644
+260 −0

File added.

Preview size limit exceeded, changes collapsed.