diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/aar.go | 9 | ||||
| -rw-r--r-- | java/androidmk.go | 15 | ||||
| -rw-r--r-- | java/androidmk_test.go | 178 | ||||
| -rw-r--r-- | java/app.go | 165 | ||||
| -rw-r--r-- | java/app_test.go | 128 | ||||
| -rw-r--r-- | java/builder.go | 145 | ||||
| -rw-r--r-- | java/config/config.go | 52 | ||||
| -rw-r--r-- | java/device_host_converter_test.go | 8 | ||||
| -rw-r--r-- | java/dexpreopt.go | 4 | ||||
| -rw-r--r-- | java/dexpreopt_bootjars.go | 52 | ||||
| -rw-r--r-- | java/dexpreopt_bootjars_test.go | 2 | ||||
| -rw-r--r-- | java/dexpreopt_test.go | 6 | ||||
| -rw-r--r-- | java/droiddoc.go | 1303 | ||||
| -rw-r--r-- | java/gen.go | 6 | ||||
| -rw-r--r-- | java/hiddenapi_singleton.go | 12 | ||||
| -rw-r--r-- | java/java.go | 108 | ||||
| -rw-r--r-- | java/java_test.go | 90 | ||||
| -rw-r--r-- | java/kotlin_test.go | 4 | ||||
| -rw-r--r-- | java/platform_compat_config.go | 92 | ||||
| -rw-r--r-- | java/plugin_test.go | 6 | ||||
| -rw-r--r-- | java/proto.go | 2 | ||||
| -rw-r--r-- | java/sdk.go | 2 | ||||
| -rw-r--r-- | java/sdk_library.go | 23 | ||||
| -rw-r--r-- | java/sdk_test.go | 6 | ||||
| -rw-r--r-- | java/support_libraries.go | 2 |
25 files changed, 1546 insertions, 874 deletions
diff --git a/java/aar.go b/java/aar.go index ce3d1263c..a4e6f910d 100644 --- a/java/aar.go +++ b/java/aar.go @@ -69,6 +69,9 @@ type aaptProperties struct { // path to AndroidManifest.xml. If unset, defaults to "AndroidManifest.xml". Manifest *string `android:"path"` + + // paths to additional manifest files to merge with main manifest. + Additional_manifests []string `android:"path"` } type aapt struct { @@ -220,7 +223,11 @@ func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext sdkContext, ex a.transitiveManifestPaths = append(android.Paths{manifestPath}, transitiveStaticLibManifests...) if len(transitiveStaticLibManifests) > 0 { - a.mergedManifestFile = manifestMerger(ctx, manifestPath, transitiveStaticLibManifests, a.isLibrary) + // Merge additional manifest files with app manifest. + additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests) + additionalManifests = append(additionalManifests, transitiveStaticLibManifests...) + + a.mergedManifestFile = manifestMerger(ctx, manifestPath, additionalManifests, a.isLibrary) if !a.isLibrary { // Only use the merged manifest for applications. For libraries, the transitive closure of manifests // will be propagated to the final application and merged there. The merged manifest for libraries is diff --git a/java/androidmk.go b/java/androidmk.go index 90fdd0f77..ad0e171f3 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -55,6 +55,11 @@ func (library *Library) AndroidMkHostDex(w io.Writer, name string, data android. } func (library *Library) AndroidMk() android.AndroidMkData { + if !library.IsForPlatform() { + return android.AndroidMkData{ + Disabled: true, + } + } return android.AndroidMkData{ Class: "JAVA_LIBRARIES", OutputFile: android.OptionalPathForPath(library.outputFile), @@ -141,6 +146,11 @@ func (j *TestHelperLibrary) AndroidMk() android.AndroidMkData { } func (prebuilt *Import) AndroidMk() android.AndroidMkData { + if !prebuilt.IsForPlatform() { + return android.AndroidMkData{ + Disabled: true, + } + } return android.AndroidMkData{ Class: "JAVA_LIBRARIES", OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile), @@ -157,6 +167,11 @@ func (prebuilt *Import) AndroidMk() android.AndroidMkData { } func (prebuilt *DexImport) AndroidMk() android.AndroidMkData { + if !prebuilt.IsForPlatform() { + return android.AndroidMkData{ + Disabled: true, + } + } return android.AndroidMkData{ Class: "JAVA_LIBRARIES", OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile), diff --git a/java/androidmk_test.go b/java/androidmk_test.go new file mode 100644 index 000000000..fbf2baa97 --- /dev/null +++ b/java/androidmk_test.go @@ -0,0 +1,178 @@ +// 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 ( + "bytes" + "io" + "io/ioutil" + "strings" + "testing" + + "android/soong/android" +) + +type testAndroidMk struct { + *testing.T + body []byte +} + +type testAndroidMkModule struct { + *testing.T + props map[string]string +} + +func newTestAndroidMk(t *testing.T, r io.Reader) *testAndroidMk { + t.Helper() + buf, err := ioutil.ReadAll(r) + if err != nil { + t.Fatal("failed to open read Android.mk.", err) + } + return &testAndroidMk{ + T: t, + body: buf, + } +} + +func parseAndroidMkProps(lines []string) map[string]string { + props := make(map[string]string) + for _, line := range lines { + line = strings.TrimLeft(line, " ") + if line == "" || strings.HasPrefix(line, "#") { + continue + } + tokens := strings.Split(line, " ") + if tokens[1] == "+=" { + props[tokens[0]] += " " + strings.Join(tokens[2:], " ") + } else { + props[tokens[0]] = strings.Join(tokens[2:], " ") + } + } + return props +} + +func (t *testAndroidMk) moduleFor(moduleName string) *testAndroidMkModule { + t.Helper() + lines := strings.Split(string(t.body), "\n") + index := android.IndexList("LOCAL_MODULE := "+moduleName, lines) + if index == -1 { + t.Fatalf("%q is not found.", moduleName) + } + lines = lines[index:] + includeIndex := android.IndexListPred(func(line string) bool { + return strings.HasPrefix(line, "include") + }, lines) + if includeIndex == -1 { + t.Fatalf("%q is not properly defined. (\"include\" not found).", moduleName) + } + props := parseAndroidMkProps(lines[:includeIndex]) + return &testAndroidMkModule{ + T: t.T, + props: props, + } +} + +func (t *testAndroidMkModule) hasRequired(dep string) { + t.Helper() + required, ok := t.props["LOCAL_REQUIRED_MODULES"] + if !ok { + t.Error("LOCAL_REQUIRED_MODULES is not found.") + return + } + if !android.InList(dep, strings.Split(required, " ")) { + t.Errorf("%q is expected in LOCAL_REQUIRED_MODULES, but not found in %q.", dep, required) + } +} + +func (t *testAndroidMkModule) hasNoRequired(dep string) { + t.Helper() + required, ok := t.props["LOCAL_REQUIRED_MODULES"] + if !ok { + return + } + if android.InList(dep, strings.Split(required, " ")) { + t.Errorf("%q is not expected in LOCAL_REQUIRED_MODULES, but found.", dep) + } +} + +func getAndroidMk(t *testing.T, ctx *android.TestContext, config android.Config, name string) *testAndroidMk { + t.Helper() + lib, _ := ctx.ModuleForTests(name, "android_common").Module().(*Library) + data := android.AndroidMkDataForTest(t, config, "", lib) + w := &bytes.Buffer{} + data.Custom(w, name, "", "", data) + return newTestAndroidMk(t, w) +} + +func TestRequired(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + required: ["libfoo"], + } + `) + + mk := getAndroidMk(t, ctx, config, "foo") + mk.moduleFor("foo").hasRequired("libfoo") +} + +func TestHostdex(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + hostdex: true, + } + `) + + mk := getAndroidMk(t, ctx, config, "foo") + mk.moduleFor("foo") + mk.moduleFor("foo-hostdex") +} + +func TestHostdexRequired(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + hostdex: true, + required: ["libfoo"], + } + `) + + mk := getAndroidMk(t, ctx, config, "foo") + mk.moduleFor("foo").hasRequired("libfoo") + mk.moduleFor("foo-hostdex").hasRequired("libfoo") +} + +func TestHostdexSpecificRequired(t *testing.T) { + ctx, config := testJava(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + hostdex: true, + target: { + hostdex: { + required: ["libfoo"], + }, + }, + } + `) + + mk := getAndroidMk(t, ctx, config, "foo") + mk.moduleFor("foo").hasNoRequired("libfoo") + mk.moduleFor("foo-hostdex").hasRequired("libfoo") +} diff --git a/java/app.go b/java/app.go index e12b56c58..674e5ece0 100644 --- a/java/app.go +++ b/java/app.go @@ -30,8 +30,7 @@ import ( "android/soong/tradefed" ) -var supportedDpis = [...]string{"Ldpi", "Mdpi", "Hdpi", "Xhdpi", "Xxhdpi", "Xxxhdpi"} -var dpiVariantsStruct reflect.Type +var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"} func init() { android.RegisterModuleType("android_app", AndroidAppFactory) @@ -40,22 +39,6 @@ func init() { android.RegisterModuleType("android_app_certificate", AndroidAppCertificateFactory) android.RegisterModuleType("override_android_app", OverrideAndroidAppModuleFactory) android.RegisterModuleType("android_app_import", AndroidAppImportFactory) - - // Dynamically construct a struct for the dpi_variants property in android_app_import. - perDpiStruct := reflect.StructOf([]reflect.StructField{ - { - Name: "Apk", - Type: reflect.TypeOf((*string)(nil)), - }, - }) - dpiVariantsFields := make([]reflect.StructField, len(supportedDpis)) - for i, dpi := range supportedDpis { - dpiVariantsFields[i] = reflect.StructField{ - Name: string(dpi), - Type: perDpiStruct, - } - } - dpiVariantsStruct = reflect.StructOf(dpiVariantsFields) } // AndroidManifest.xml merging @@ -208,9 +191,12 @@ func (a *AndroidApp) OverridablePropertiesDepsMutator(ctx android.BottomUpMutato } } +func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { + a.generateAndroidBuildActions(ctx) +} + func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) { - a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx) - a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex) + a.checkPlatformAPI(ctx) a.generateAndroidBuildActions(ctx) } @@ -439,6 +425,9 @@ func processMainCert(m android.ModuleBase, certPropValue string, certificates [] func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) { var apkDeps android.Paths + a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx) + a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex) + // Check if the install APK name needs to be overridden. a.installApkName = ctx.DeviceConfig().OverridePackageNameFor(a.Name()) @@ -601,8 +590,6 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName) } } - a.aapt.useEmbeddedNativeLibs = a.useEmbeddedNativeLibs(ctx) - a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex) a.generateAndroidBuildActions(ctx) a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites) @@ -744,7 +731,8 @@ type AndroidAppImport struct { android.DefaultableModuleBase prebuilt android.Prebuilt - properties AndroidAppImportProperties + properties AndroidAppImportProperties + dpiVariants interface{} outputFile android.Path certificate *Certificate @@ -756,27 +744,7 @@ type AndroidAppImport struct { type AndroidAppImportProperties struct { // A prebuilt apk to import - Apk string - - // Per-DPI settings. This property makes it possible to specify a different source apk path for - // each DPI. - // - // Example: - // - // android_app_import { - // name: "example_import", - // apk: "prebuilts/example.apk", - // dpi_variants: { - // mdpi: { - // apk: "prebuilts/example_mdpi.apk", - // }, - // xhdpi: { - // apk: "prebuilts/example_xhdpi.apk", - // }, - // }, - // certificate: "PRESIGNED", - // } - Dpi_variants interface{} + Apk *string // The name of a certificate in the default certificate directory, blank to use the default // product certificate, or an android_app_certificate module name in the form ":module". @@ -799,39 +767,43 @@ type AndroidAppImportProperties struct { Overrides []string } -func getApkPathForDpi(dpiVariantsValue reflect.Value, dpi string) string { - dpiField := dpiVariantsValue.FieldByName(proptools.FieldNameForProperty(dpi)) - if !dpiField.IsValid() { - return "" - } - apkValue := dpiField.FieldByName("Apk").Elem() - if apkValue.IsValid() { - return apkValue.String() - } - return "" -} - -// Chooses a source APK path to use based on the module's per-DPI settings and the product config. -func (a *AndroidAppImport) getSrcApkPath(ctx android.ModuleContext) string { +// Chooses a source APK path to use based on the module and product specs. +func (a *AndroidAppImport) updateSrcApkPath(ctx android.LoadHookContext) { config := ctx.Config() - dpiVariantsValue := reflect.ValueOf(a.properties.Dpi_variants).Elem() - if !dpiVariantsValue.IsValid() { - return a.properties.Apk + + dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants") + // Try DPI variant matches in the reverse-priority order so that the highest priority match + // overwrites everything else. + // TODO(jungjw): Can we optimize this by making it priority order? + for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- { + dpi := config.ProductAAPTPrebuiltDPI()[i] + if inList(dpi, supportedDpis) { + MergePropertiesFromVariant(ctx, &a.properties, dpiProps, dpi, "dpi_variants") + } } - // Match PRODUCT_AAPT_PREF_CONFIG first and then PRODUCT_AAPT_PREBUILT_DPI. if config.ProductAAPTPreferredConfig() != "" { - if apk := getApkPathForDpi(dpiVariantsValue, config.ProductAAPTPreferredConfig()); apk != "" { - return apk + dpi := config.ProductAAPTPreferredConfig() + if inList(dpi, supportedDpis) { + MergePropertiesFromVariant(ctx, &a.properties, dpiProps, dpi, "dpi_variants") } } - for _, dpi := range config.ProductAAPTPrebuiltDPI() { - if apk := getApkPathForDpi(dpiVariantsValue, dpi); apk != "" { - return apk - } +} + +func MergePropertiesFromVariant(ctx android.BaseModuleContext, + dst interface{}, variantGroup reflect.Value, variant, variantGroupPath string) { + src := variantGroup.FieldByName(proptools.FieldNameForProperty(variant)) + if !src.IsValid() { + ctx.ModuleErrorf("field %q does not exist", variantGroupPath+"."+variant) } - // No match. Use the generic one. - return a.properties.Apk + err := proptools.ExtendMatchingProperties([]interface{}{dst}, src.Interface(), nil, proptools.OrderAppend) + if err != nil { + if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok { + ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error()) + } else { + panic(err) + } + } } func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) { @@ -848,7 +820,7 @@ func (a *AndroidAppImport) uncompressEmbeddedJniLibs( rule := android.NewRuleBuilder() rule.Command(). Textf(`if (zipinfo %s 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). - Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). + BuiltTool(ctx, "zip2zip"). FlagWithInput("-i ", inputPath). FlagWithOutput("-o ", outputPath). FlagWithArg("-0 ", "'lib/**/*.so'"). @@ -875,7 +847,7 @@ func (a *AndroidAppImport) uncompressDex( rule := android.NewRuleBuilder() rule.Command(). Textf(`if (zipinfo %s '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then`, inputPath). - Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). + BuiltTool(ctx, "zip2zip"). FlagWithInput("-i ", inputPath). FlagWithOutput("-o ", outputPath). FlagWithArg("-0 ", "'classes*.dex'"). @@ -896,8 +868,7 @@ func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext // TODO: LOCAL_EXTRACT_APK/LOCAL_EXTRACT_DPI_APK // TODO: LOCAL_PACKAGE_SPLITS - var srcApk android.Path - srcApk = android.PathForModuleSrc(ctx, a.getSrcApkPath(ctx)) + srcApk := a.prebuilt.SingleSourcePath(ctx) if a.usesLibrary.enforceUsesLibraries() { srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk) @@ -959,16 +930,56 @@ func (a *AndroidAppImport) Name() string { return a.prebuilt.Name(a.ModuleBase.Name()) } +// Populates dpi_variants property and its fields at creation time. +func (a *AndroidAppImport) addDpiVariants() { + // TODO(jungjw): Do we want to do some filtering here? + props := reflect.ValueOf(&a.properties).Type() + + dpiFields := make([]reflect.StructField, len(supportedDpis)) + for i, dpi := range supportedDpis { + dpiFields[i] = reflect.StructField{ + Name: proptools.FieldNameForProperty(dpi), + Type: props, + } + } + dpiStruct := reflect.StructOf(dpiFields) + a.dpiVariants = reflect.New(reflect.StructOf([]reflect.StructField{ + { + Name: "Dpi_variants", + Type: dpiStruct, + }, + })).Interface() + a.AddProperties(a.dpiVariants) +} + // android_app_import imports a prebuilt apk with additional processing specified in the module. +// DPI-specific apk source files can be specified using dpi_variants. Example: +// +// android_app_import { +// name: "example_import", +// apk: "prebuilts/example.apk", +// dpi_variants: { +// mdpi: { +// apk: "prebuilts/example_mdpi.apk", +// }, +// xhdpi: { +// apk: "prebuilts/example_xhdpi.apk", +// }, +// }, +// certificate: "PRESIGNED", +// } func AndroidAppImportFactory() android.Module { module := &AndroidAppImport{} - module.properties.Dpi_variants = reflect.New(dpiVariantsStruct).Interface() module.AddProperties(&module.properties) module.AddProperties(&module.dexpreoptProperties) module.AddProperties(&module.usesLibrary.usesLibraryProperties) + module.addDpiVariants() + android.AddLoadHook(module, func(ctx android.LoadHookContext) { + module.updateSrcApkPath(ctx) + }) InitJavaModule(module, android.DeviceSupported) - android.InitSingleSourcePrebuiltModule(module, &module.properties.Apk) + android.InitSingleSourcePrebuiltModule(module, &module.properties, "Apk") return module } @@ -1060,7 +1071,7 @@ func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, man outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml") rule := android.NewRuleBuilder() - cmd := rule.Command().Tool(ctx.Config().HostToolPath(ctx, "manifest_check")). + cmd := rule.Command().BuiltTool(ctx, "manifest_check"). Flag("--enforce-uses-libraries"). Input(manifest). FlagWithOutput("-o ", outputFile) diff --git a/java/app_test.go b/java/app_test.go index 721dd4dc2..f6a307e97 100644 --- a/java/app_test.go +++ b/java/app_test.go @@ -43,7 +43,7 @@ var ( } ) -func testAppContext(config android.Config, bp string, fs map[string][]byte) *android.TestContext { +func testAppContext(bp string, fs map[string][]byte) *android.TestContext { appFS := map[string][]byte{} for k, v := range fs { appFS[k] = v @@ -53,13 +53,13 @@ func testAppContext(config android.Config, bp string, fs map[string][]byte) *and appFS[file] = nil } - return testContext(config, bp, appFS) + return testContext(bp, appFS) } func testApp(t *testing.T, bp string) *android.TestContext { config := testConfig(nil) - ctx := testAppContext(config, bp, nil) + ctx := testAppContext(bp, nil) run(t, ctx, config) @@ -72,6 +72,7 @@ func TestApp(t *testing.T) { ctx := testApp(t, moduleType+` { name: "foo", srcs: ["a.java"], + sdk_version: "current" } `) @@ -117,6 +118,7 @@ func TestAppSplits(t *testing.T) { name: "foo", srcs: ["a.java"], package_splits: ["v4", "v7,hdpi"], + sdk_version: "current" }`) foo := ctx.ModuleForTests("foo", "android_common") @@ -139,6 +141,40 @@ func TestAppSplits(t *testing.T) { } } +func TestPlatformAPIs(t *testing.T) { + testJava(t, ` + android_app { + name: "foo", + srcs: ["a.java"], + platform_apis: true, + } + `) + + testJava(t, ` + android_app { + name: "foo", + srcs: ["a.java"], + sdk_version: "current", + } + `) + + testJavaError(t, "platform_apis must be true when sdk_version is empty.", ` + android_app { + name: "bar", + srcs: ["b.java"], + } + `) + + testJavaError(t, "platform_apis must be false when sdk_version is not empty.", ` + android_app { + name: "bar", + srcs: ["b.java"], + sdk_version: "system_current", + platform_apis: true, + } + `) +} + func TestResourceDirs(t *testing.T) { testCases := []struct { name string @@ -169,6 +205,7 @@ func TestResourceDirs(t *testing.T) { bp := ` android_app { name: "foo", + sdk_version: "current", %s } ` @@ -176,7 +213,7 @@ func TestResourceDirs(t *testing.T) { for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { config := testConfig(nil) - ctx := testContext(config, fmt.Sprintf(bp, testCase.prop), fs) + ctx := testContext(fmt.Sprintf(bp, testCase.prop), fs) run(t, ctx, config) module := ctx.ModuleForTests("foo", "android_common") @@ -349,12 +386,14 @@ func TestAndroidResources(t *testing.T) { bp := ` android_app { name: "foo", + sdk_version: "current", resource_dirs: ["foo/res"], static_libs: ["lib", "lib3"], } android_app { name: "bar", + sdk_version: "current", resource_dirs: ["bar/res"], } @@ -388,7 +427,7 @@ func TestAndroidResources(t *testing.T) { config.TestProductVariables.EnforceRROExcludedOverlays = testCase.enforceRROExcludedOverlays } - ctx := testAppContext(config, bp, fs) + ctx := testAppContext(bp, fs) run(t, ctx, config) resourceListToFiles := func(module android.TestingModule, list []string) (files []string) { @@ -461,6 +500,7 @@ func TestAppSdkVersion(t *testing.T) { platformSdkCodename string platformSdkFinal bool expectedMinSdkVersion string + platformApis bool }{ { name: "current final SDK", @@ -481,6 +521,7 @@ func TestAppSdkVersion(t *testing.T) { { name: "default final SDK", sdkVersion: "", + platformApis: true, platformSdkInt: 27, platformSdkCodename: "REL", platformSdkFinal: true, @@ -489,6 +530,7 @@ func TestAppSdkVersion(t *testing.T) { { name: "default non-final SDK", sdkVersion: "", + platformApis: true, platformSdkInt: 27, platformSdkCodename: "OMR1", platformSdkFinal: false, @@ -504,18 +546,23 @@ func TestAppSdkVersion(t *testing.T) { for _, moduleType := range []string{"android_app", "android_library"} { for _, test := range testCases { t.Run(moduleType+" "+test.name, func(t *testing.T) { + platformApiProp := "" + if test.platformApis { + platformApiProp = "platform_apis: true," + } bp := fmt.Sprintf(`%s { name: "foo", srcs: ["a.java"], sdk_version: "%s", - }`, moduleType, test.sdkVersion) + %s + }`, moduleType, test.sdkVersion, platformApiProp) config := testConfig(nil) config.TestProductVariables.Platform_sdk_version = &test.platformSdkInt config.TestProductVariables.Platform_sdk_codename = &test.platformSdkCodename config.TestProductVariables.Platform_sdk_final = &test.platformSdkFinal - ctx := testAppContext(config, bp, nil) + ctx := testAppContext(bp, nil) run(t, ctx, config) @@ -547,7 +594,7 @@ func TestAppSdkVersion(t *testing.T) { } func TestJNIABI(t *testing.T) { - ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", system_shared_libs: [], @@ -620,7 +667,7 @@ func TestJNIABI(t *testing.T) { } func TestJNIPackaging(t *testing.T) { - ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", system_shared_libs: [], @@ -630,18 +677,21 @@ func TestJNIPackaging(t *testing.T) { android_app { name: "app", jni_libs: ["libjni"], + sdk_version: "current", } android_app { name: "app_noembed", jni_libs: ["libjni"], use_embedded_native_libs: false, + sdk_version: "current", } android_app { name: "app_embed", jni_libs: ["libjni"], use_embedded_native_libs: true, + sdk_version: "current", } android_test { @@ -715,6 +765,7 @@ func TestCertificates(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } `, certificateOverride: "", @@ -726,7 +777,8 @@ func TestCertificates(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], - certificate: ":new_certificate" + certificate: ":new_certificate", + sdk_version: "current", } android_app_certificate { @@ -743,7 +795,8 @@ func TestCertificates(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], - certificate: "expiredkey" + certificate: "expiredkey", + sdk_version: "current", } `, certificateOverride: "", @@ -755,7 +808,8 @@ func TestCertificates(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], - certificate: "expiredkey" + certificate: "expiredkey", + sdk_version: "current", } android_app_certificate { @@ -774,7 +828,7 @@ func TestCertificates(t *testing.T) { if test.certificateOverride != "" { config.TestProductVariables.CertificateOverrides = []string{test.certificateOverride} } - ctx := testAppContext(config, test.bp, nil) + ctx := testAppContext(test.bp, nil) run(t, ctx, config) foo := ctx.ModuleForTests("foo", "android_common") @@ -801,6 +855,7 @@ func TestPackageNameOverride(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } `, packageNameOverride: "", @@ -815,6 +870,7 @@ func TestPackageNameOverride(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } `, packageNameOverride: "foo:bar", @@ -832,7 +888,7 @@ func TestPackageNameOverride(t *testing.T) { if test.packageNameOverride != "" { config.TestProductVariables.PackageNameOverrides = []string{test.packageNameOverride} } - ctx := testAppContext(config, test.bp, nil) + ctx := testAppContext(test.bp, nil) run(t, ctx, config) foo := ctx.ModuleForTests("foo", "android_common") @@ -856,16 +912,18 @@ func TestInstrumentationTargetOverridden(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } android_test { name: "bar", instrumentation_for: "foo", + sdk_version: "current", } ` config := testConfig(nil) config.TestProductVariables.ManifestPackageNameOverrides = []string{"foo:org.dandroid.bp"} - ctx := testAppContext(config, bp, nil) + ctx := testAppContext(bp, nil) run(t, ctx, config) @@ -879,12 +937,13 @@ func TestInstrumentationTargetOverridden(t *testing.T) { } func TestOverrideAndroidApp(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` android_app { name: "foo", srcs: ["a.java"], certificate: "expiredkey", overrides: ["qux"], + sdk_version: "current", } override_android_app { @@ -980,10 +1039,11 @@ func TestOverrideAndroidApp(t *testing.T) { } func TestOverrideAndroidAppDependency(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } override_android_app { @@ -1021,7 +1081,7 @@ func TestOverrideAndroidAppDependency(t *testing.T) { } func TestAndroidAppImport(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", @@ -1050,7 +1110,7 @@ func TestAndroidAppImport(t *testing.T) { } func TestAndroidAppImport_NoDexPreopt(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", @@ -1071,7 +1131,7 @@ func TestAndroidAppImport_NoDexPreopt(t *testing.T) { } func TestAndroidAppImport_Presigned(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` android_app_import { name: "foo", apk: "prebuilts/apk/app.apk", @@ -1138,7 +1198,7 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { { name: "AAPTPreferredConfig matches", aaptPreferredConfig: proptools.StringPtr("xhdpi"), - aaptPrebuiltDPI: []string{"xxhdpi", "lhdpi"}, + aaptPrebuiltDPI: []string{"xxhdpi", "ldpi"}, expected: "prebuilts/apk/app_xhdpi.apk", }, { @@ -1166,7 +1226,7 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { config := testConfig(nil) config.TestProductVariables.AAPTPreferredConfig = test.aaptPreferredConfig config.TestProductVariables.AAPTPrebuiltDPI = test.aaptPrebuiltDPI - ctx := testAppContext(config, bp, nil) + ctx := testAppContext(bp, nil) run(t, ctx, config) @@ -1183,7 +1243,7 @@ func TestAndroidAppImport_DpiVariants(t *testing.T) { } func TestStl(t *testing.T) { - ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` cc_library { name: "libjni", } @@ -1253,18 +1313,21 @@ func TestUsesLibraries(t *testing.T) { name: "foo", srcs: ["a.java"], api_packages: ["foo"], + sdk_version: "current", } java_sdk_library { name: "bar", srcs: ["a.java"], api_packages: ["bar"], + sdk_version: "current", } android_app { name: "app", srcs: ["a.java"], uses_libs: ["foo"], + sdk_version: "current", optional_uses_libs: [ "bar", "baz", @@ -1286,7 +1349,7 @@ func TestUsesLibraries(t *testing.T) { config := testConfig(nil) config.TestProductVariables.MissingUsesLibraries = []string{"baz"} - ctx := testAppContext(config, bp, nil) + ctx := testAppContext(bp, nil) run(t, ctx, config) @@ -1339,6 +1402,7 @@ func TestCodelessApp(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } `, noCode: false, @@ -1348,6 +1412,7 @@ func TestCodelessApp(t *testing.T) { bp: ` android_app { name: "foo", + sdk_version: "current", } `, noCode: true, @@ -1358,11 +1423,13 @@ func TestCodelessApp(t *testing.T) { android_app { name: "foo", static_libs: ["lib"], + sdk_version: "current", } java_library { name: "lib", srcs: ["a.java"], + sdk_version: "current", } `, noCode: false, @@ -1373,10 +1440,12 @@ func TestCodelessApp(t *testing.T) { android_app { name: "foo", static_libs: ["lib"], + sdk_version: "current", } java_library { name: "lib", + sdk_version: "current", } `, // TODO(jungjw): this should probably be true @@ -1398,7 +1467,7 @@ func TestCodelessApp(t *testing.T) { } func TestEmbedNotice(t *testing.T) { - ctx := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` + ctx, _ := testJava(t, cc.GatherRequiredDepsForTest(android.Android)+` android_app { name: "foo", srcs: ["a.java"], @@ -1406,6 +1475,7 @@ func TestEmbedNotice(t *testing.T) { jni_libs: ["libjni"], notice: "APP_NOTICE", embed_notices: true, + sdk_version: "current", } // No embed_notice flag @@ -1414,6 +1484,7 @@ func TestEmbedNotice(t *testing.T) { srcs: ["a.java"], jni_libs: ["libjni"], notice: "APP_NOTICE", + sdk_version: "current", } // No NOTICE files @@ -1421,6 +1492,7 @@ func TestEmbedNotice(t *testing.T) { name: "baz", srcs: ["a.java"], embed_notices: true, + sdk_version: "current", } cc_library { @@ -1435,6 +1507,7 @@ func TestEmbedNotice(t *testing.T) { srcs: [ ":gen", ], + sdk_version: "current", } genrule { @@ -1510,6 +1583,7 @@ func TestUncompressDex(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", } `, uncompressedPlatform: true, @@ -1522,6 +1596,7 @@ func TestUncompressDex(t *testing.T) { name: "foo", use_embedded_dex: true, srcs: ["a.java"], + sdk_version: "current", } `, uncompressedPlatform: true, @@ -1534,6 +1609,7 @@ func TestUncompressDex(t *testing.T) { name: "foo", privileged: true, srcs: ["a.java"], + sdk_version: "current", } `, uncompressedPlatform: true, @@ -1549,7 +1625,7 @@ func TestUncompressDex(t *testing.T) { config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true) } - ctx := testAppContext(config, bp, nil) + ctx := testAppContext(bp, nil) run(t, ctx, config) diff --git a/java/builder.go b/java/builder.go index a48e8b1a2..f174cf0c6 100644 --- a/java/builder.go +++ b/java/builder.go @@ -62,6 +62,37 @@ var ( "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", "outDir", "annoDir", "javaVersion") + _ = pctx.VariableFunc("kytheCorpus", + func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() }) + // Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about + // "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ... + // to field java.nio.Buffer.address" + kytheExtract = pctx.AndroidStaticRule("kythe", + blueprint.RuleParams{ + Command: `${config.ZipSyncCmd} -d $srcJarDir ` + + `-l $srcJarDir/list -f "*.java" $srcJars && ` + + `( [ ! -s $srcJarDir/list -a ! -s $out.rsp ] || ` + + `KYTHE_ROOT_DIRECTORY=. KYTHE_OUTPUT_FILE=$out ` + + `KYTHE_CORPUS=${kytheCorpus} ` + + `${config.SoongJavacWrapper} ${config.JavaCmd} ` + + `--add-opens=java.base/java.nio=ALL-UNNAMED ` + + `-jar ${config.JavaKytheExtractorJar} ` + + `${config.JavacHeapFlags} ${config.CommonJdkFlags} ` + + `$processorpath $processor $javacFlags $bootClasspath $classpath ` + + `-source $javaVersion -target $javaVersion ` + + `-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list)`, + CommandDeps: []string{ + "${config.JavaCmd}", + "${config.JavaKytheExtractorJar}", + "${config.ZipSyncCmd}", + }, + CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, + Rspfile: "$out.rsp", + RspfileContent: "$in", + }, + "javacFlags", "bootClasspath", "classpath", "processorpath", "processor", "srcJars", "srcJarDir", + "outDir", "annoDir", "javaVersion") + turbine = pctx.AndroidStaticRule("turbine", blueprint.RuleParams{ Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` + @@ -148,16 +179,15 @@ func init() { } type javaBuilderFlags struct { - javacFlags string - bootClasspath classpath - classpath classpath - processorPath classpath - processor string - systemModules classpath - systemModulesDeps android.Paths - aidlFlags string - aidlDeps android.Paths - javaVersion string + javacFlags string + bootClasspath classpath + classpath classpath + processorPath classpath + processor string + systemModules *systemModules + aidlFlags string + aidlDeps android.Paths + javaVersion string errorProneExtraJavacFlags string errorProneProcessorPath classpath @@ -197,6 +227,61 @@ func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath, "errorprone", "errorprone") } +// Emits the rule to generate Xref input file (.kzip file) for the given set of source files and source jars +// to compile with given set of builder flags, etc. +func emitXrefRule(ctx android.ModuleContext, xrefFile android.WritablePath, + srcFiles, srcJars android.Paths, + flags javaBuilderFlags, deps android.Paths, + intermediatesDir string) { + + deps = append(deps, srcJars...) + + var bootClasspath string + if flags.javaVersion == "1.9" { + var systemModuleDeps android.Paths + bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device()) + deps = append(deps, systemModuleDeps...) + } else { + deps = append(deps, flags.bootClasspath...) + if len(flags.bootClasspath) == 0 && ctx.Device() { + // explicitly specify -bootclasspath "" if the bootclasspath is empty to + // ensure java does not fall back to the default bootclasspath. + bootClasspath = `-bootclasspath ""` + } else { + bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath") + } + } + + deps = append(deps, flags.classpath...) + deps = append(deps, flags.processorPath...) + + processor := "-proc:none" + if flags.processor != "" { + processor = "-processor " + flags.processor + } + + ctx.Build(pctx, + android.BuildParams{ + Rule: kytheExtract, + Description: "Xref Java extractor", + Output: xrefFile, + Inputs: srcFiles, + Implicits: deps, + Args: map[string]string{ + "annoDir": android.PathForModuleOut(ctx, intermediatesDir, "anno").String(), + "bootClasspath": bootClasspath, + "classpath": flags.classpath.FormJavaClassPath("-classpath"), + "javacFlags": flags.javacFlags, + "javaVersion": flags.javaVersion, + "outDir": android.PathForModuleOut(ctx, "javac", "classes.xref").String(), + "processorpath": flags.processorPath.FormJavaClassPath("-processorpath"), + "processor": processor, + "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, "srcjars.xref").String(), + "srcJars": strings.Join(srcJars.Strings(), " "), + }, + }) +} + func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath, srcFiles, srcJars android.Paths, flags javaBuilderFlags) { @@ -249,8 +334,9 @@ func transformJavaToClasses(ctx android.ModuleContext, outputFile android.Writab var bootClasspath string if flags.javaVersion == "1.9" { - deps = append(deps, flags.systemModulesDeps...) - bootClasspath = flags.systemModules.FormJavaSystemModulesPath("--system=", ctx.Device()) + var systemModuleDeps android.Paths + bootClasspath, systemModuleDeps = flags.systemModules.FormJavaSystemModulesPath(ctx.Device()) + deps = append(deps, systemModuleDeps...) } else { deps = append(deps, flags.bootClasspath...) if len(flags.bootClasspath) == 0 && ctx.Device() { @@ -411,7 +497,7 @@ func TransformZipAlign(ctx android.ModuleContext, outputFile android.WritablePat }) } -type classpath []android.Path +type classpath android.Paths func (x *classpath) FormJavaClassPath(optName string) string { if optName != "" && !strings.HasSuffix(optName, "=") && !strings.HasSuffix(optName, " ") { @@ -424,21 +510,6 @@ func (x *classpath) FormJavaClassPath(optName string) string { } } -// Returns a --system argument in the form javac expects with -source 1.9. If forceEmpty is true, -// returns --system=none if the list is empty to ensure javac does not fall back to the default -// system modules. -func (x *classpath) FormJavaSystemModulesPath(optName string, forceEmpty bool) string { - if len(*x) > 1 { - panic("more than one system module") - } else if len(*x) == 1 { - return optName + (*x)[0].String() - } else if forceEmpty { - return optName + "none" - } else { - return "" - } -} - func (x *classpath) FormTurbineClasspath(optName string) []string { if x == nil || *x == nil { return nil @@ -466,3 +537,21 @@ func (x *classpath) Strings() []string { } return ret } + +type systemModules struct { + dir android.Path + deps android.Paths +} + +// Returns a --system argument in the form javac expects with -source 1.9. If forceEmpty is true, +// returns --system=none if the list is empty to ensure javac does not fall back to the default +// system modules. +func (x *systemModules) FormJavaSystemModulesPath(forceEmpty bool) (string, android.Paths) { + if x != nil { + return "--system=" + x.dir.String(), x.deps + } else if forceEmpty { + return "--system=none", nil + } else { + return "", nil + } +} diff --git a/java/config/config.go b/java/config/config.go index b72e89d80..6be83c397 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -42,18 +42,24 @@ var ( "android.car", "android.car7", "conscrypt", + "core-icu4j", "core-oj", "core-libart", "updatable-media", } ) +const ( + JavaVmFlags = `-XX:OnError="cat hs_err_pid%p.log" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads` + JavacVmFlags = `-J-XX:OnError="cat hs_err_pid%p.log" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads` +) + func init() { pctx.Import("github.com/google/blueprint/bootstrap") pctx.StaticVariable("JavacHeapSize", "2048M") pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}") - pctx.StaticVariable("DexFlags", "-JXX:+TieredCompilation -JXX:TieredStopAtLevel=1") + pctx.StaticVariable("DexFlags", "-JXX:OnError='cat hs_err_pid%p.log' -JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads") pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{ `-Xmaxerrs 9999999`, @@ -70,8 +76,9 @@ func init() { // b/65004097: prevent using java.lang.invoke.StringConcatFactory when using -target 1.9 `-XDstringConcat=inline`, }, " ")) - pctx.StaticVariable("JavaVmFlags", "-XX:OnError=\"cat hs_err_pid%p.log\" -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads") - pctx.StaticVariable("JavacVmFlags", "-J-XX:OnError=\"cat hs_err_pid%p.log\" -J-XX:CICompilerCount=6 -J-XX:+UseDynamicNumberOfGCThreads") + + pctx.StaticVariable("JavaVmFlags", JavaVmFlags) + pctx.StaticVariable("JavacVmFlags", JavacVmFlags) pctx.VariableConfigMethod("hostPrebuiltTag", android.Config.PrebuiltOS) @@ -89,6 +96,7 @@ func init() { pctx.SourcePathVariable("JlinkCmd", "${JavaToolchain}/jlink") pctx.SourcePathVariable("JmodCmd", "${JavaToolchain}/jmod") pctx.SourcePathVariable("JrtFsJar", "${JavaHome}/lib/jrt-fs.jar") + pctx.SourcePathVariable("JavaKytheExtractorJar", "prebuilts/build-tools/common/framework/javac_extractor.jar") pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime") pctx.SourcePathVariable("GenKotlinBuildFileCmd", "build/soong/scripts/gen-kotlin-build-file.sh") @@ -155,3 +163,41 @@ func init() { pctx.HostBinToolVariable("Class2Greylist", "class2greylist") pctx.HostBinToolVariable("HiddenAPI", "hiddenapi") } + +// JavaCmd returns a SourcePath object with the path to the java command. +func JavaCmd(ctx android.PathContext) android.SourcePath { + return javaTool(ctx, "java") +} + +// JavadocCmd returns a SourcePath object with the path to the java command. +func JavadocCmd(ctx android.PathContext) android.SourcePath { + return javaTool(ctx, "javadoc") +} + +func javaTool(ctx android.PathContext, tool string) android.SourcePath { + type javaToolKey string + + key := android.NewCustomOnceKey(javaToolKey(tool)) + + return ctx.Config().OnceSourcePath(key, func() android.SourcePath { + return javaToolchain(ctx).Join(ctx, tool) + }) + +} + +var javaToolchainKey = android.NewOnceKey("javaToolchain") + +func javaToolchain(ctx android.PathContext) android.SourcePath { + return ctx.Config().OnceSourcePath(javaToolchainKey, func() android.SourcePath { + return javaHome(ctx).Join(ctx, "bin") + }) +} + +var javaHomeKey = android.NewOnceKey("javaHome") + +func javaHome(ctx android.PathContext) android.SourcePath { + return ctx.Config().OnceSourcePath(javaHomeKey, func() android.SourcePath { + // This is set up and guaranteed by soong_ui + return android.PathForSource(ctx, ctx.Config().Getenv("ANDROID_JAVA_HOME")) + }) +} diff --git a/java/device_host_converter_test.go b/java/device_host_converter_test.go index 9b9d0d899..44aae9b36 100644 --- a/java/device_host_converter_test.go +++ b/java/device_host_converter_test.go @@ -50,9 +50,7 @@ func TestDeviceForHost(t *testing.T) { } ` - config := testConfig(nil) - ctx := testContext(config, bp, nil) - run(t, ctx, config) + ctx, config := testJava(t, bp) deviceModule := ctx.ModuleForTests("device_module", "android_common") deviceTurbineCombined := deviceModule.Output("turbine-combined/device_module.jar") @@ -133,9 +131,7 @@ func TestHostForDevice(t *testing.T) { } ` - config := testConfig(nil) - ctx := testContext(config, bp, nil) - run(t, ctx, config) + ctx, config := testJava(t, bp) hostModule := ctx.ModuleForTests("host_module", config.BuildOsCommonVariant) hostJavac := hostModule.Output("javac/host_module.jar") diff --git a/java/dexpreopt.go b/java/dexpreopt.go index ed12fe6d2..6214dac44 100644 --- a/java/dexpreopt.go +++ b/java/dexpreopt.go @@ -143,6 +143,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo strippedDexJarFile := android.PathForModuleOut(ctx, "dexpreopt", dexJarFile.Base()) var profileClassListing android.OptionalPath + var profileBootListing android.OptionalPath profileIsTextListing := false if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) { // If dex_preopt.profile_guided is not set, default it based on the existence of the @@ -150,6 +151,8 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo if String(d.dexpreoptProperties.Dex_preopt.Profile) != "" { profileClassListing = android.OptionalPathForPath( android.PathForModuleSrc(ctx, String(d.dexpreoptProperties.Dex_preopt.Profile))) + profileBootListing = android.ExistentPathForSource(ctx, + ctx.ModuleDir(), String(d.dexpreoptProperties.Dex_preopt.Profile)+"-boot") profileIsTextListing = true } else { profileClassListing = android.ExistentPathForSource(ctx, @@ -169,6 +172,7 @@ func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.Mo ProfileClassListing: profileClassListing, ProfileIsTextListing: profileIsTextListing, + ProfileBootListing: profileBootListing, EnforceUsesLibraries: d.enforceUsesLibs, PresentOptionalUsesLibraries: d.optionalUsesLibs, diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index fe468a9e0..2a142baee 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -216,6 +216,7 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI } profile := bootImageProfileRule(ctx, image, missingDeps) + bootFrameworkProfileRule(ctx, image, missingDeps) var allFiles android.Paths @@ -229,7 +230,7 @@ func buildBootImage(ctx android.SingletonContext, config bootImageConfig) *bootI if image.zip != nil { rule := android.NewRuleBuilder() rule.Command(). - Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). + BuiltTool(ctx, "soong_zip"). FlagWithOutput("-o ", image.zip). FlagWithArg("-C ", image.dir.String()). FlagWithInputList("-f ", allFiles, " -f ") @@ -297,6 +298,7 @@ func buildBootImageRuleForArch(ctx android.SingletonContext, image *bootImage, FlagForEachArg("--dex-location=", image.dexLocations). Flag("--generate-debug-info"). Flag("--generate-build-id"). + Flag("--image-format=lz4hc"). FlagWithOutput("--oat-symbols=", symbolsFile). Flag("--strip"). FlagWithOutput("--oat-file=", outputPath.ReplaceExtension(ctx, "oat")). @@ -424,6 +426,52 @@ func bootImageProfileRule(ctx android.SingletonContext, image *bootImage, missin var bootImageProfileRuleKey = android.NewOnceKey("bootImageProfileRule") +func bootFrameworkProfileRule(ctx android.SingletonContext, image *bootImage, missingDeps []string) android.WritablePath { + global := dexpreoptGlobalConfig(ctx) + + if global.DisableGenerateProfile || ctx.Config().IsPdkBuild() || ctx.Config().UnbundledBuild() { + return nil + } + return ctx.Config().Once(bootFrameworkProfileRuleKey, func() interface{} { + tools := global.Tools + + rule := android.NewRuleBuilder() + rule.MissingDeps(missingDeps) + + // Some branches like master-art-host don't have frameworks/base, so manually + // handle the case that the default is missing. Those branches won't attempt to build the profile rule, + // and if they do they'll get a missing deps error. + defaultProfile := "frameworks/base/config/boot-profile.txt" + path := android.ExistentPathForSource(ctx, defaultProfile) + var bootFrameworkProfile android.Path + if path.Valid() { + bootFrameworkProfile = path.Path() + } else { + missingDeps = append(missingDeps, defaultProfile) + bootFrameworkProfile = android.PathForOutput(ctx, "missing") + } + + profile := image.dir.Join(ctx, "boot.bprof") + + rule.Command(). + Text(`ANDROID_LOG_TAGS="*:e"`). + Tool(tools.Profman). + Flag("--generate-boot-profile"). + FlagWithInput("--create-profile-from=", bootFrameworkProfile). + FlagForEachInput("--apk=", image.dexPaths.Paths()). + FlagForEachArg("--dex-location=", image.dexLocations). + FlagWithOutput("--reference-profile-file=", profile) + + rule.Install(profile, "/system/etc/boot-image.bprof") + rule.Build(pctx, ctx, "bootFrameworkProfile", "profile boot framework jars") + image.profileInstalls = append(image.profileInstalls, rule.Installs()...) + + return profile + }).(android.WritablePath) +} + +var bootFrameworkProfileRuleKey = android.NewOnceKey("bootFrameworkProfileRule") + func dumpOatRules(ctx android.SingletonContext, image *bootImage) { var archs []android.ArchType for arch := range image.images { @@ -438,7 +486,7 @@ func dumpOatRules(ctx android.SingletonContext, image *bootImage) { rule := android.NewRuleBuilder() rule.Command(). // TODO: for now, use the debug version for better error reporting - Tool(ctx.Config().HostToolPath(ctx, "oatdumpd")). + BuiltTool(ctx, "oatdumpd"). FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPaths.Paths(), ":"). FlagWithList("--runtime-arg -Xbootclasspath-locations:", image.dexLocations, ":"). FlagWithArg("--image=", dexpreopt.PathToLocation(image.images[arch], arch)).Implicit(image.images[arch]). diff --git a/java/dexpreopt_bootjars_test.go b/java/dexpreopt_bootjars_test.go index f91ff6925..4c38399d3 100644 --- a/java/dexpreopt_bootjars_test.go +++ b/java/dexpreopt_bootjars_test.go @@ -51,7 +51,7 @@ func TestDexpreoptBootJars(t *testing.T) { dexpreoptConfig.RuntimeApexJars = []string{"foo", "bar", "baz"} setDexpreoptTestGlobalConfig(config, dexpreoptConfig) - ctx := testContext(config, bp, nil) + ctx := testContext(bp, nil) ctx.RegisterSingletonType("dex_bootjars", android.SingletonFactoryAdaptor(dexpreoptBootJarsFactory)) diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go index 7d0109fda..5550a4c17 100644 --- a/java/dexpreopt_test.go +++ b/java/dexpreopt_test.go @@ -30,6 +30,7 @@ func TestDexpreoptEnabled(t *testing.T) { android_app { name: "foo", srcs: ["a.java"], + sdk_version: "current", }`, enabled: true, }, @@ -57,6 +58,7 @@ func TestDexpreoptEnabled(t *testing.T) { bp: ` android_app { name: "foo", + sdk_version: "current", }`, enabled: false, }, @@ -66,11 +68,13 @@ func TestDexpreoptEnabled(t *testing.T) { android_app { name: "foo", static_libs: ["lib"], + sdk_version: "current", } java_library { name: "lib", srcs: ["a.java"], + sdk_version: "current", }`, enabled: true, }, @@ -142,7 +146,7 @@ func TestDexpreoptEnabled(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ctx := testJava(t, test.bp) + ctx, _ := testJava(t, test.bp) dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeDescription("dexpreopt") enabled := dexpreopt.Rule != nil diff --git a/java/droiddoc.go b/java/droiddoc.go index 25101de81..9956270c9 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -15,126 +15,15 @@ package java import ( - "android/soong/android" - "android/soong/java/config" "fmt" "path/filepath" "runtime" "strings" - "github.com/google/blueprint" "github.com/google/blueprint/proptools" -) -var ( - javadoc = pctx.AndroidStaticRule("javadoc", - blueprint.RuleParams{ - Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + - `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.SoongJavacWrapper} ${config.JavadocCmd} -encoding UTF-8 @$out.rsp @$srcJarDir/list ` + - `$opts $bootclasspathArgs $classpathArgs $sourcepathArgs ` + - `-d $outDir -quiet && ` + - `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` + - `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir $postDoclavaCmds && ` + - `rm -rf "$srcJarDir"`, - - CommandDeps: []string{ - "${config.ZipSyncCmd}", - "${config.JavadocCmd}", - "${config.SoongZipCmd}", - }, - CommandOrderOnly: []string{"${config.SoongJavacWrapper}"}, - Rspfile: "$out.rsp", - RspfileContent: "$in", - Restat: true, - }, - "outDir", "srcJarDir", "stubsDir", "srcJars", "opts", - "bootclasspathArgs", "classpathArgs", "sourcepathArgs", "docZip", "postDoclavaCmds") - - apiCheck = pctx.AndroidStaticRule("apiCheck", - blueprint.RuleParams{ - Command: `( ${config.ApiCheckCmd} -JXmx1024m -J"classpath $classpath" $opts ` + - `$apiFile $apiFileToCheck $removedApiFile $removedApiFileToCheck ` + - `&& touch $out ) || (echo -e "$msg" ; exit 38)`, - CommandDeps: []string{ - "${config.ApiCheckCmd}", - }, - }, - "classpath", "opts", "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck", "msg") - - updateApi = pctx.AndroidStaticRule("updateApi", - blueprint.RuleParams{ - Command: `( ( cp -f $srcApiFile $destApiFile && cp -f $srcRemovedApiFile $destRemovedApiFile ) ` + - `&& touch $out ) || (echo failed to update public API ; exit 38)`, - }, - "srcApiFile", "destApiFile", "srcRemovedApiFile", "destRemovedApiFile") - - metalava = pctx.AndroidStaticRule("metalava", - blueprint.RuleParams{ - Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` + - `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + - `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + - `$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` + - `$opts && ` + - `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` + - `rm -rf "$srcJarDir"`, - CommandDeps: []string{ - "${config.ZipSyncCmd}", - "${config.JavaCmd}", - "${config.MetalavaJar}", - "${config.SoongZipCmd}", - }, - Rspfile: "$out.rsp", - RspfileContent: "$in", - Restat: true, - }, - "outDir", "srcJarDir", "stubsDir", "srcJars", "javaVersion", "bootclasspathArgs", - "classpathArgs", "sourcepathArgs", "opts") - - metalavaApiCheck = pctx.AndroidStaticRule("metalavaApiCheck", - blueprint.RuleParams{ - Command: `( rm -rf "$srcJarDir" && mkdir -p "$srcJarDir" && ` + - `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.MetalavaJar} -encoding UTF-8 -source $javaVersion @$out.rsp @$srcJarDir/list ` + - `$bootclasspathArgs $classpathArgs $sourcepathArgs --no-banner --color --quiet --format=v2 ` + - `$opts && touch $out && rm -rf "$srcJarDir") || ` + - `( echo -e "$msg" ; exit 38 )`, - CommandDeps: []string{ - "${config.ZipSyncCmd}", - "${config.JavaCmd}", - "${config.MetalavaJar}", - }, - Rspfile: "$out.rsp", - RspfileContent: "$in", - }, - "srcJarDir", "srcJars", "javaVersion", "bootclasspathArgs", "classpathArgs", "sourcepathArgs", "opts", "msg") - - nullabilityWarningsCheck = pctx.AndroidStaticRule("nullabilityWarningsCheck", - blueprint.RuleParams{ - Command: `( diff $expected $actual && touch $out ) || ( echo -e "$msg" ; exit 38 )`, - }, - "expected", "actual", "msg") - - dokka = pctx.AndroidStaticRule("dokka", - blueprint.RuleParams{ - Command: `rm -rf "$outDir" "$srcJarDir" "$stubsDir" && ` + - `mkdir -p "$outDir" "$srcJarDir" "$stubsDir" && ` + - `${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` + - `${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.DokkaJar} $srcJarDir ` + - `$classpathArgs -format dac -dacRoot /reference/kotlin -output $outDir $opts && ` + - `${config.SoongZipCmd} -write_if_changed -d -o $docZip -C $outDir -D $outDir && ` + - `${config.SoongZipCmd} -write_if_changed -jar -o $out -C $stubsDir -D $stubsDir && ` + - `rm -rf "$srcJarDir"`, - CommandDeps: []string{ - "${config.ZipSyncCmd}", - "${config.DokkaJar}", - "${config.MetalavaJar}", - "${config.SoongZipCmd}", - }, - Restat: true, - }, - "outDir", "srcJarDir", "stubsDir", "srcJars", "classpathArgs", "opts", "docZip") + "android/soong/android" + "android/soong/java/config" ) func init() { @@ -222,6 +111,9 @@ type ApiToCheck struct { // :module syntax). Removed_api_file *string `android:"path"` + // If not blank, path to the baseline txt file for approved API check violations. + Baseline_file *string `android:"path"` + // Arguments to the apicheck tool. Args *string } @@ -238,7 +130,7 @@ type DroiddocProperties struct { // proofread file contains all of the text content of the javadocs concatenated into one file, // suitable for spell-checking and other goodness. - Proofread_file *string `android:"path"` + Proofread_file *string // a todo file lists the program elements that are missing documentation. // At some point, this might be improved to show more warnings. @@ -404,14 +296,6 @@ type droiddocBuilderFlags struct { doclavaStubsFlags string doclavaDocsFlags string postDoclavaCmds string - - metalavaStubsFlags string - metalavaAnnotationsFlags string - metalavaMergeAnnoDirFlags string - metalavaInclusionAnnotationsFlags string - metalavaApiLevelsAnnotationsFlags string - - metalavaApiToXmlFlags string } func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) { @@ -454,23 +338,6 @@ type ApiFilePath interface { ApiFilePath() android.Path } -func transformUpdateApi(ctx android.ModuleContext, destApiFile, destRemovedApiFile, - srcApiFile, srcRemovedApiFile android.Path, output android.WritablePath) { - ctx.Build(pctx, android.BuildParams{ - Rule: updateApi, - Description: "Update API", - Output: output, - Implicits: append(android.Paths{}, srcApiFile, srcRemovedApiFile, - destApiFile, destRemovedApiFile), - Args: map[string]string{ - "destApiFile": destApiFile.String(), - "srcApiFile": srcApiFile.String(), - "destRemovedApiFile": destRemovedApiFile.String(), - "srcRemovedApiFile": srcRemovedApiFile.String(), - }, - }) -} - // // Javadoc // @@ -500,6 +367,7 @@ func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) { } } +// javadoc converts .java source files to documentation using javadoc. func JavadocFactory() android.Module { module := &Javadoc{} @@ -509,6 +377,7 @@ func JavadocFactory() android.Module { return module } +// javadoc_host converts .java source files to documentation using javadoc. func JavadocHostFactory() android.Module { module := &Javadoc{} @@ -653,6 +522,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { deps.classpath = append(deps.classpath, dep.SdkImplementationJars(ctx, j.sdkVersion())...) case Dependency: deps.classpath = append(deps.classpath, dep.HeaderJars()...) + deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...) case android.SourceFileProducer: checkProducesJars(ctx, dep) deps.classpath = append(deps.classpath, dep.Srcs()...) @@ -689,8 +559,7 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { if sm.outputDir == nil && len(sm.outputDeps) == 0 { panic("Missing directory for system module dependency") } - deps.systemModules = sm.outputDir - deps.systemModulesDeps = sm.outputDeps + deps.systemModules = &systemModules{sm.outputDir, sm.outputDeps} } }) // do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs @@ -706,9 +575,6 @@ func (j *Javadoc) collectDeps(ctx android.ModuleContext) deps { j.srcFiles = srcFiles.FilterOutByExt(".srcjar") j.srcFiles = append(j.srcFiles, deps.srcs...) - j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip") - j.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") - if j.properties.Local_sourcepaths == nil && len(j.srcFiles) > 0 { j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".") } @@ -759,52 +625,43 @@ func (j *Javadoc) DepsMutator(ctx android.BottomUpMutatorContext) { func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { deps := j.collectDeps(ctx) - var implicits android.Paths - implicits = append(implicits, deps.bootClasspath...) - implicits = append(implicits, deps.classpath...) + j.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip") + + outDir := android.PathForModuleOut(ctx, "out") + srcJarDir := android.PathForModuleOut(ctx, "srcjars") + + j.stubsSrcJar = nil + + rule := android.NewRuleBuilder() + + rule.Command().Text("rm -rf").Text(outDir.String()) + rule.Command().Text("mkdir -p").Text(outDir.String()) - var bootClasspathArgs, classpathArgs, sourcepathArgs string + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, j.srcJars) javaVersion := getJavaVersion(ctx, String(j.properties.Java_version), sdkContext(j)) - if len(deps.bootClasspath) > 0 { - var systemModules classpath - if deps.systemModules != nil { - systemModules = append(systemModules, deps.systemModules) - } - implicits = append(implicits, deps.systemModulesDeps...) - bootClasspathArgs = systemModules.FormJavaSystemModulesPath("--system ", ctx.Device()) - bootClasspathArgs = bootClasspathArgs + " --patch-module java.base=." - } - if len(deps.classpath.Strings()) > 0 { - classpathArgs = "-classpath " + strings.Join(deps.classpath.Strings(), ":") - } - - implicits = append(implicits, j.srcJars...) - implicits = append(implicits, j.argFiles...) - - opts := "-source " + javaVersion + " -J-Xmx1024m -XDignore.symbol.file -Xdoclint:none" - - sourcepathArgs = "-sourcepath " + strings.Join(j.sourcepaths.Strings(), ":") - - ctx.Build(pctx, android.BuildParams{ - Rule: javadoc, - Description: "Javadoc", - Output: j.stubsSrcJar, - ImplicitOutput: j.docZip, - Inputs: j.srcFiles, - Implicits: implicits, - Args: map[string]string{ - "outDir": android.PathForModuleOut(ctx, "out").String(), - "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), - "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), - "srcJars": strings.Join(j.srcJars.Strings(), " "), - "opts": opts, - "bootclasspathArgs": bootClasspathArgs, - "classpathArgs": classpathArgs, - "sourcepathArgs": sourcepathArgs, - "docZip": j.docZip.String(), - }, - }) + + cmd := javadocSystemModulesCmd(ctx, rule, j.srcFiles, outDir, srcJarDir, srcJarList, + deps.systemModules, deps.classpath, j.sourcepaths) + + cmd.FlagWithArg("-source ", javaVersion). + Flag("-J-Xmx1024m"). + Flag("-XDignore.symbol.file"). + Flag("-Xdoclint:none") + + rule.Command(). + BuiltTool(ctx, "soong_zip"). + Flag("-write_if_changed"). + Flag("-d"). + FlagWithOutput("-o ", j.docZip). + FlagWithArg("-C ", outDir.String()). + FlagWithArg("-D ", outDir.String()) + + rule.Restat() + + zipSyncCleanupCmd(rule, srcJarDir) + + rule.Build(pctx, ctx, "javadoc", "javadoc") } // @@ -831,6 +688,7 @@ type Droiddoc struct { apiFilePath android.Path } +// droiddoc converts .java source files to documentation using doclava or dokka. func DroiddocFactory() android.Module { module := &Droiddoc{} @@ -841,6 +699,7 @@ func DroiddocFactory() android.Module { return module } +// droiddoc_host converts .java source files to documentation using doclava or dokka. func DroiddocHostFactory() android.Module { module := &Droiddoc{} @@ -867,58 +726,25 @@ func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) { } } -func (d *Droiddoc) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, - deps deps) (droiddocBuilderFlags, error) { - var flags droiddocBuilderFlags - - *implicits = append(*implicits, deps.bootClasspath...) - *implicits = append(*implicits, deps.classpath...) - - if len(deps.bootClasspath.Strings()) > 0 { - // For OpenJDK 8 we can use -bootclasspath to define the core libraries code. - flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath") - } - flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath") - // Dokka doesn't support bootClasspath, so combine these two classpath vars for Dokka. - dokkaClasspath := classpath{} - dokkaClasspath = append(dokkaClasspath, deps.bootClasspath...) - dokkaClasspath = append(dokkaClasspath, deps.classpath...) - flags.dokkaClasspathArgs = dokkaClasspath.FormJavaClassPath("-classpath") - - // TODO(nanzhang): Remove this if- statement once we finish migration for all Doclava - // based stubs generation. - // In the future, all the docs generation depends on Metalava stubs (droidstubs) srcjar - // dir. We need add the srcjar dir to -sourcepath arg, so that Javadoc can figure out - // the correct package name base path. - if len(d.Javadoc.properties.Local_sourcepaths) > 0 { - flags.sourcepathArgs = "-sourcepath " + strings.Join(d.Javadoc.sourcepaths.Strings(), ":") - } else { - flags.sourcepathArgs = "-sourcepath " + android.PathForModuleOut(ctx, "srcjars").String() - } - - return flags, nil -} - -func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits *android.Paths, - jsilver, doclava android.Path) string { - - *implicits = append(*implicits, jsilver) - *implicits = append(*implicits, doclava) - +func (d *Droiddoc) doclavaDocsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, docletPath classpath) { var date string if runtime.GOOS == "darwin" { date = `date -r` } else { - date = `date -d` + date = `date -d @` } // Droiddoc always gets "-source 1.8" because it doesn't support 1.9 sources. For modules with 1.9 // sources, droiddoc will get sources produced by metalava which will have already stripped out the // 1.9 language features. - args := " -source 1.8 -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file " + - "-doclet com.google.doclava.Doclava -docletpath " + jsilver.String() + ":" + doclava.String() + " " + - "-hdf page.build " + ctx.Config().BuildId() + "-" + ctx.Config().BuildNumberFromFile() + " " + - `-hdf page.now "$$(` + date + ` @$$(cat ` + ctx.Config().Getenv("BUILD_DATETIME_FILE") + `) "+%d %b %Y %k:%M")" ` + cmd.FlagWithArg("-source ", "1.8"). + Flag("-J-Xmx1600m"). + Flag("-J-XX:-OmitStackTraceInFastThrow"). + Flag("-XDignore.symbol.file"). + FlagWithArg("-doclet ", "com.google.doclava.Doclava"). + FlagWithInputList("-docletpath ", docletPath.Paths(), ":"). + FlagWithArg("-hdf page.build ", ctx.Config().BuildId()+"-"+ctx.Config().BuildNumberFromFile()). + FlagWithArg("-hdf page.now ", `"$(`+date+`$(cat `+ctx.Config().Getenv("BUILD_DATETIME_FILE")+`) "+%d %b %Y %k:%M")" `) if String(d.properties.Custom_template) == "" { // TODO: This is almost always droiddoc-templates-sdk @@ -927,23 +753,22 @@ func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits ctx.VisitDirectDepsWithTag(droiddocTemplateTag, func(m android.Module) { if t, ok := m.(*ExportedDroiddocDir); ok { - *implicits = append(*implicits, t.deps...) - args = args + " -templatedir " + t.dir.String() + cmd.FlagWithArg("-templatedir ", t.dir.String()).Implicits(t.deps) } else { ctx.PropertyErrorf("custom_template", "module %q is not a droiddoc_template", ctx.OtherModuleName(m)) } }) if len(d.properties.Html_dirs) > 0 { - htmlDir := d.properties.Html_dirs[0] - *implicits = append(*implicits, android.PathsForModuleSrc(ctx, []string{filepath.Join(d.properties.Html_dirs[0], "**/*")})...) - args = args + " -htmldir " + htmlDir + htmlDir := android.PathForModuleSrc(ctx, d.properties.Html_dirs[0]) + cmd.FlagWithArg("-htmldir ", htmlDir.String()). + Implicits(android.PathsForModuleSrc(ctx, []string{filepath.Join(d.properties.Html_dirs[0], "**/*")})) } if len(d.properties.Html_dirs) > 1 { - htmlDir2 := d.properties.Html_dirs[1] - *implicits = append(*implicits, android.PathsForModuleSrc(ctx, []string{filepath.Join(htmlDir2, "**/*")})...) - args = args + " -htmldir2 " + htmlDir2 + htmlDir2 := android.PathForModuleSrc(ctx, d.properties.Html_dirs[1]) + cmd.FlagWithArg("-htmldir2 ", htmlDir2.String()). + Implicits(android.PathsForModuleSrc(ctx, []string{filepath.Join(d.properties.Html_dirs[1], "**/*")})) } if len(d.properties.Html_dirs) > 2 { @@ -951,51 +776,43 @@ func (d *Droiddoc) collectDoclavaDocsFlags(ctx android.ModuleContext, implicits } knownTags := android.PathsForModuleSrc(ctx, d.properties.Knowntags) - *implicits = append(*implicits, knownTags...) + cmd.FlagForEachInput("-knowntags ", knownTags) - for _, kt := range knownTags { - args = args + " -knowntags " + kt.String() - } - - for _, hdf := range d.properties.Hdf { - args = args + " -hdf " + hdf - } + cmd.FlagForEachArg("-hdf ", d.properties.Hdf) if String(d.properties.Proofread_file) != "" { proofreadFile := android.PathForModuleOut(ctx, String(d.properties.Proofread_file)) - args = args + " -proofread " + proofreadFile.String() + cmd.FlagWithOutput("-proofread ", proofreadFile) } if String(d.properties.Todo_file) != "" { // tricky part: // we should not compute full path for todo_file through PathForModuleOut(). // the non-standard doclet will get the full path relative to "-o". - args = args + " -todo " + String(d.properties.Todo_file) + cmd.FlagWithArg("-todo ", String(d.properties.Todo_file)). + ImplicitOutput(android.PathForModuleOut(ctx, String(d.properties.Todo_file))) } if String(d.properties.Resourcesdir) != "" { // TODO: should we add files under resourcesDir to the implicits? It seems that // resourcesDir is one sub dir of htmlDir resourcesDir := android.PathForModuleSrc(ctx, String(d.properties.Resourcesdir)) - args = args + " -resourcesdir " + resourcesDir.String() + cmd.FlagWithArg("-resourcesdir ", resourcesDir.String()) } if String(d.properties.Resourcesoutdir) != "" { // TODO: it seems -resourceoutdir reference/android/images/ didn't get generated anywhere. - args = args + " -resourcesoutdir " + String(d.properties.Resourcesoutdir) + cmd.FlagWithArg("-resourcesoutdir ", String(d.properties.Resourcesoutdir)) } - return args } -func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, - implicitOutputs *android.WritablePaths) string { - var doclavaFlags string +func (d *Droiddoc) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.WritablePath) { if apiCheckEnabled(d.properties.Check_api.Current, "current") || apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || String(d.properties.Api_filename) != "" { + d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt") - doclavaFlags += " -api " + d.apiFile.String() - *implicitOutputs = append(*implicitOutputs, d.apiFile) + cmd.FlagWithOutput("-api ", d.apiFile) d.apiFilePath = d.apiFile } @@ -1003,223 +820,324 @@ func (d *Droiddoc) collectStubsFlags(ctx android.ModuleContext, apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || String(d.properties.Removed_api_filename) != "" { d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt") - doclavaFlags += " -removedApi " + d.removedApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.removedApiFile) + cmd.FlagWithOutput("-removedApi ", d.removedApiFile) } if String(d.properties.Private_api_filename) != "" { d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename)) - doclavaFlags += " -privateApi " + d.privateApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.privateApiFile) + cmd.FlagWithOutput("-privateApi ", d.privateApiFile) } if String(d.properties.Dex_api_filename) != "" { d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename)) - doclavaFlags += " -dexApi " + d.dexApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.dexApiFile) + cmd.FlagWithOutput("-dexApi ", d.dexApiFile) } if String(d.properties.Private_dex_api_filename) != "" { d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename)) - doclavaFlags += " -privateDexApi " + d.privateDexApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile) + cmd.FlagWithOutput("-privateDexApi ", d.privateDexApiFile) } if String(d.properties.Removed_dex_api_filename) != "" { d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename)) - doclavaFlags += " -removedDexApi " + d.removedDexApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile) + cmd.FlagWithOutput("-removedDexApi ", d.removedDexApiFile) } if String(d.properties.Exact_api_filename) != "" { d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename)) - doclavaFlags += " -exactApi " + d.exactApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.exactApiFile) + cmd.FlagWithOutput("-exactApi ", d.exactApiFile) } if String(d.properties.Dex_mapping_filename) != "" { d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename)) - doclavaFlags += " -apiMapping " + d.apiMappingFile.String() - *implicitOutputs = append(*implicitOutputs, d.apiMappingFile) + cmd.FlagWithOutput("-apiMapping ", d.apiMappingFile) } if String(d.properties.Proguard_filename) != "" { d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename)) - doclavaFlags += " -proguard " + d.proguardFile.String() - *implicitOutputs = append(*implicitOutputs, d.proguardFile) + cmd.FlagWithOutput("-proguard ", d.proguardFile) } if BoolDefault(d.properties.Create_stubs, true) { - doclavaFlags += " -stubs " + android.PathForModuleOut(ctx, "stubsDir").String() + cmd.FlagWithArg("-stubs ", stubsDir.String()) } if Bool(d.properties.Write_sdk_values) { - doclavaFlags += " -sdkvalues " + android.PathForModuleOut(ctx, "out").String() + cmd.FlagWithArg("-sdkvalues ", android.PathForModuleOut(ctx, "out").String()) } - - return doclavaFlags } -func (d *Droiddoc) getPostDoclavaCmds(ctx android.ModuleContext, implicits *android.Paths) string { - var cmds string +func (d *Droiddoc) postDoclavaCmds(ctx android.ModuleContext, rule *android.RuleBuilder) { if String(d.properties.Static_doc_index_redirect) != "" { - static_doc_index_redirect := ctx.ExpandSource(String(d.properties.Static_doc_index_redirect), - "static_doc_index_redirect") - *implicits = append(*implicits, static_doc_index_redirect) - cmds = cmds + " && cp " + static_doc_index_redirect.String() + " " + - android.PathForModuleOut(ctx, "out", "index.html").String() + staticDocIndexRedirect := android.PathForModuleSrc(ctx, String(d.properties.Static_doc_index_redirect)) + rule.Command().Text("cp"). + Input(staticDocIndexRedirect). + Output(android.PathForModuleOut(ctx, "out", "index.html")) } if String(d.properties.Static_doc_properties) != "" { - static_doc_properties := ctx.ExpandSource(String(d.properties.Static_doc_properties), - "static_doc_properties") - *implicits = append(*implicits, static_doc_properties) - cmds = cmds + " && cp " + static_doc_properties.String() + " " + - android.PathForModuleOut(ctx, "out", "source.properties").String() + staticDocProperties := android.PathForModuleSrc(ctx, String(d.properties.Static_doc_properties)) + rule.Command().Text("cp"). + Input(staticDocProperties). + Output(android.PathForModuleOut(ctx, "out", "source.properties")) } - return cmds } -func (d *Droiddoc) transformDoclava(ctx android.ModuleContext, implicits android.Paths, - implicitOutputs android.WritablePaths, - bootclasspathArgs, classpathArgs, sourcepathArgs, opts, postDoclavaCmds string) { - ctx.Build(pctx, android.BuildParams{ - Rule: javadoc, - Description: "Doclava", - Output: d.Javadoc.stubsSrcJar, - Inputs: d.Javadoc.srcFiles, - Implicits: implicits, - ImplicitOutputs: implicitOutputs, - Args: map[string]string{ - "outDir": android.PathForModuleOut(ctx, "out").String(), - "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), - "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), - "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), - "opts": opts, - "bootclasspathArgs": bootclasspathArgs, - "classpathArgs": classpathArgs, - "sourcepathArgs": sourcepathArgs, - "docZip": d.Javadoc.docZip.String(), - "postDoclavaCmds": postDoclavaCmds, - }, - }) +func javadocCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths, + outDir, srcJarDir, srcJarList android.Path, sourcepaths android.Paths) *android.RuleBuilderCommand { + + cmd := rule.Command(). + BuiltTool(ctx, "soong_javac_wrapper").Tool(config.JavadocCmd(ctx)). + Flag(config.JavacVmFlags). + FlagWithArg("-encoding ", "UTF-8"). + FlagWithRspFileInputList("@", srcs). + FlagWithInput("@", srcJarList) + + // TODO(ccross): Remove this if- statement once we finish migration for all Doclava + // based stubs generation. + // In the future, all the docs generation depends on Metalava stubs (droidstubs) srcjar + // dir. We need add the srcjar dir to -sourcepath arg, so that Javadoc can figure out + // the correct package name base path. + if len(sourcepaths) > 0 { + cmd.FlagWithList("-sourcepath ", sourcepaths.Strings(), ":") + } else { + cmd.FlagWithArg("-sourcepath ", srcJarDir.String()) + } + + cmd.FlagWithArg("-d ", outDir.String()). + Flag("-quiet") + + return cmd } -func (d *Droiddoc) transformCheckApi(ctx android.ModuleContext, apiFile, removedApiFile android.Path, - checkApiClasspath classpath, msg, opts string, output android.WritablePath) { - ctx.Build(pctx, android.BuildParams{ - Rule: apiCheck, - Description: "Doclava Check API", - Output: output, - Inputs: nil, - Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile}, - checkApiClasspath...), - Args: map[string]string{ - "msg": msg, - "classpath": checkApiClasspath.FormJavaClassPath(""), - "opts": opts, - "apiFile": apiFile.String(), - "apiFileToCheck": d.apiFile.String(), - "removedApiFile": removedApiFile.String(), - "removedApiFileToCheck": d.removedApiFile.String(), - }, - }) +func javadocSystemModulesCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths, + outDir, srcJarDir, srcJarList android.Path, systemModules *systemModules, + classpath classpath, sourcepaths android.Paths) *android.RuleBuilderCommand { + + cmd := javadocCmd(ctx, rule, srcs, outDir, srcJarDir, srcJarList, sourcepaths) + + flag, deps := systemModules.FormJavaSystemModulesPath(ctx.Device()) + cmd.Flag(flag).Implicits(deps) + + cmd.FlagWithArg("--patch-module ", "java.base=.") + + if len(classpath) > 0 { + cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":") + } + + return cmd } -func (d *Droiddoc) transformDokka(ctx android.ModuleContext, implicits android.Paths, - classpathArgs, opts string) { - ctx.Build(pctx, android.BuildParams{ - Rule: dokka, - Description: "Dokka", - Output: d.Javadoc.stubsSrcJar, - Inputs: d.Javadoc.srcFiles, - Implicits: implicits, - Args: map[string]string{ - "outDir": android.PathForModuleOut(ctx, "dokka-out").String(), - "srcJarDir": android.PathForModuleOut(ctx, "dokka-srcjars").String(), - "stubsDir": android.PathForModuleOut(ctx, "dokka-stubsDir").String(), - "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), - "classpathArgs": classpathArgs, - "opts": opts, - "docZip": d.Javadoc.docZip.String(), - }, - }) +func javadocBootclasspathCmd(ctx android.ModuleContext, rule *android.RuleBuilder, srcs android.Paths, + outDir, srcJarDir, srcJarList android.Path, bootclasspath, classpath classpath, + sourcepaths android.Paths) *android.RuleBuilderCommand { + + cmd := javadocCmd(ctx, rule, srcs, outDir, srcJarDir, srcJarList, sourcepaths) + + if len(bootclasspath) == 0 && ctx.Device() { + // explicitly specify -bootclasspath "" if the bootclasspath is empty to + // ensure java does not fall back to the default bootclasspath. + cmd.FlagWithArg("-bootclasspath ", `""`) + } else if len(bootclasspath) > 0 { + cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":") + } + + if len(classpath) > 0 { + cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":") + } + + return cmd +} + +func dokkaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, + outDir, srcJarDir android.Path, bootclasspath, classpath classpath) *android.RuleBuilderCommand { + + // Dokka doesn't support bootClasspath, so combine these two classpath vars for Dokka. + dokkaClasspath := append(bootclasspath.Paths(), classpath.Paths()...) + + return rule.Command(). + BuiltTool(ctx, "dokka"). + Flag(config.JavacVmFlags). + Flag(srcJarDir.String()). + FlagWithInputList("-classpath ", dokkaClasspath, ":"). + FlagWithArg("-format ", "dac"). + FlagWithArg("-dacRoot ", "/reference/kotlin"). + FlagWithArg("-output ", outDir.String()) } func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { deps := d.Javadoc.collectDeps(ctx) + d.Javadoc.docZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"docs.zip") + d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") + jsilver := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jsilver.jar") doclava := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "doclava.jar") java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME") checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")} - var implicits android.Paths - implicits = append(implicits, d.Javadoc.srcJars...) - implicits = append(implicits, d.Javadoc.argFiles...) + outDir := android.PathForModuleOut(ctx, "out") + srcJarDir := android.PathForModuleOut(ctx, "srcjars") + stubsDir := android.PathForModuleOut(ctx, "stubsDir") - var implicitOutputs android.WritablePaths - implicitOutputs = append(implicitOutputs, d.Javadoc.docZip) - for _, o := range d.Javadoc.properties.Out { - implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o)) - } + rule := android.NewRuleBuilder() - flags, err := d.initBuilderFlags(ctx, &implicits, deps) - if err != nil { - return + rule.Command().Text("rm -rf").Text(outDir.String()).Text(stubsDir.String()) + rule.Command().Text("mkdir -p").Text(outDir.String()).Text(stubsDir.String()) + + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars) + + var cmd *android.RuleBuilderCommand + if Bool(d.properties.Dokka_enabled) { + cmd = dokkaCmd(ctx, rule, outDir, srcJarDir, deps.bootClasspath, deps.classpath) + } else { + cmd = javadocBootclasspathCmd(ctx, rule, d.Javadoc.srcFiles, outDir, srcJarDir, srcJarList, + deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths) } - flags.doclavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs) + d.stubsFlags(ctx, cmd, stubsDir) + + cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles) + + var desc string if Bool(d.properties.Dokka_enabled) { - d.transformDokka(ctx, implicits, flags.classpathArgs, d.Javadoc.args) + desc = "dokka" } else { - flags.doclavaDocsFlags = d.collectDoclavaDocsFlags(ctx, &implicits, jsilver, doclava) - flags.postDoclavaCmds = d.getPostDoclavaCmds(ctx, &implicits) - d.transformDoclava(ctx, implicits, implicitOutputs, flags.bootClasspathArgs, flags.classpathArgs, - flags.sourcepathArgs, flags.doclavaDocsFlags+flags.doclavaStubsFlags+" "+d.Javadoc.args, - flags.postDoclavaCmds) + d.doclavaDocsFlags(ctx, cmd, classpath{jsilver, doclava}) + + for _, o := range d.Javadoc.properties.Out { + cmd.ImplicitOutput(android.PathForModuleGen(ctx, o)) + } + + d.postDoclavaCmds(ctx, rule) + desc = "doclava" } + rule.Command(). + BuiltTool(ctx, "soong_zip"). + Flag("-write_if_changed"). + Flag("-d"). + FlagWithOutput("-o ", d.docZip). + FlagWithArg("-C ", outDir.String()). + FlagWithArg("-D ", outDir.String()) + + rule.Command(). + BuiltTool(ctx, "soong_zip"). + Flag("-write_if_changed"). + Flag("-jar"). + FlagWithOutput("-o ", d.stubsSrcJar). + FlagWithArg("-C ", stubsDir.String()). + FlagWithArg("-D ", stubsDir.String()) + + rule.Restat() + + zipSyncCleanupCmd(rule, srcJarDir) + + rule.Build(pctx, ctx, "javadoc", desc) + if apiCheckEnabled(d.properties.Check_api.Current, "current") && !ctx.Config().IsPdkBuild() { - apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file), - "check_api.current.api_file") - removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file), - "check_api.current_removed_api_file") + + apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file)) + removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file)) d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp") - d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath, - fmt.Sprintf(`\n******************************\n`+ - `You have tried to change the API from what has been previously approved.\n\n`+ - `To make these errors go away, you have two choices:\n`+ - ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+ - ` errors above.\n\n`+ - ` 2. You can update current.txt by executing the following command:\n`+ - ` make %s-update-current-api\n\n`+ - ` To submit the revised current.txt to the main Android repository,\n`+ - ` you will need approval.\n`+ - `******************************\n`, ctx.ModuleName()), String(d.properties.Check_api.Current.Args), - d.checkCurrentApiTimestamp) + + rule := android.NewRuleBuilder() + + rule.Command().Text("( true") + + rule.Command(). + BuiltTool(ctx, "apicheck"). + Flag("-JXmx1024m"). + FlagWithInputList("-Jclasspath\\ ", checkApiClasspath.Paths(), ":"). + OptionalFlag(d.properties.Check_api.Current.Args). + Input(apiFile). + Input(d.apiFile). + Input(removedApiFile). + Input(d.removedApiFile) + + msg := fmt.Sprintf(`\n******************************\n`+ + `You have tried to change the API from what has been previously approved.\n\n`+ + `To make these errors go away, you have two choices:\n`+ + ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+ + ` errors above.\n\n`+ + ` 2. You can update current.txt by executing the following command:\n`+ + ` make %s-update-current-api\n\n`+ + ` To submit the revised current.txt to the main Android repository,\n`+ + ` you will need approval.\n`+ + `******************************\n`, ctx.ModuleName()) + + rule.Command(). + Text("touch").Output(d.checkCurrentApiTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "doclavaCurrentApiCheck", "check current API") d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp") - transformUpdateApi(ctx, apiFile, removedApiFile, d.apiFile, d.removedApiFile, - d.updateCurrentApiTimestamp) + + // update API rule + rule = android.NewRuleBuilder() + + rule.Command().Text("( true") + + rule.Command(). + Text("cp").Flag("-f"). + Input(d.apiFile).Flag(apiFile.String()) + + rule.Command(). + Text("cp").Flag("-f"). + Input(d.removedApiFile).Flag(removedApiFile.String()) + + msg = "failed to update public API" + + rule.Command(). + Text("touch").Output(d.updateCurrentApiTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "doclavaCurrentApiUpdate", "update current API") } if apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") && !ctx.Config().IsPdkBuild() { - apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file), - "check_api.last_released.api_file") - removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file), - "check_api.last_released.removed_api_file") + + apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file)) + removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file)) d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp") - d.transformCheckApi(ctx, apiFile, removedApiFile, checkApiClasspath, - `\n******************************\n`+ - `You have tried to change the API from what has been previously released in\n`+ - `an SDK. Please fix the errors listed above.\n`+ - `******************************\n`, String(d.properties.Check_api.Last_released.Args), - d.checkLastReleasedApiTimestamp) + + rule := android.NewRuleBuilder() + + rule.Command(). + Text("("). + BuiltTool(ctx, "apicheck"). + Flag("-JXmx1024m"). + FlagWithInputList("-Jclasspath\\ ", checkApiClasspath.Paths(), ":"). + OptionalFlag(d.properties.Check_api.Last_released.Args). + Input(apiFile). + Input(d.apiFile). + Input(removedApiFile). + Input(d.removedApiFile) + + msg := `\n******************************\n` + + `You have tried to change the API from what has been previously released in\n` + + `an SDK. Please fix the errors listed above.\n` + + `******************************\n` + + rule.Command(). + Text("touch").Output(d.checkLastReleasedApiTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "doclavaLastApiCheck", "check last API") } } @@ -1258,6 +1176,9 @@ type Droidstubs struct { jdiffStubsSrcJar android.WritablePath } +// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be +// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to +// a droiddoc module to generate documentation. func DroidstubsFactory() android.Module { module := &Droidstubs{} @@ -1268,6 +1189,10 @@ func DroidstubsFactory() android.Module { return module } +// droidstubs_host passes sources files through Metalava to generate stub .java files that only contain the API +// to be documented, filtering out hidden classes and methods. The resulting .java files are intended to be +// passed to a droiddoc_host module to generate documentation. Use a droidstubs_host instead of a droidstubs +// module when symbols needed by the source files are provided by java_library_host modules. func DroidstubsHostFactory() android.Module { module := &Droidstubs{} @@ -1308,34 +1233,12 @@ func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) { } } -func (d *Droidstubs) initBuilderFlags(ctx android.ModuleContext, implicits *android.Paths, - deps deps) (droiddocBuilderFlags, error) { - var flags droiddocBuilderFlags - - *implicits = append(*implicits, deps.bootClasspath...) - *implicits = append(*implicits, deps.classpath...) - - // continue to use -bootclasspath even if Metalava under -source 1.9 is enabled - // since it doesn't support system modules yet. - if len(deps.bootClasspath.Strings()) > 0 { - // For OpenJDK 8 we can use -bootclasspath to define the core libraries code. - flags.bootClasspathArgs = deps.bootClasspath.FormJavaClassPath("-bootclasspath") - } - flags.classpathArgs = deps.classpath.FormJavaClassPath("-classpath") - - flags.sourcepathArgs = "-sourcepath \"" + strings.Join(d.Javadoc.sourcepaths.Strings(), ":") + "\"" - return flags, nil -} - -func (d *Droidstubs) collectStubsFlags(ctx android.ModuleContext, - implicitOutputs *android.WritablePaths) string { - var metalavaFlags string +func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.WritablePath) { if apiCheckEnabled(d.properties.Check_api.Current, "current") || apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || String(d.properties.Api_filename) != "" { d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt") - metalavaFlags = metalavaFlags + " --api " + d.apiFile.String() - *implicitOutputs = append(*implicitOutputs, d.apiFile) + cmd.FlagWithOutput("--api ", d.apiFile) d.apiFilePath = d.apiFile } @@ -1343,159 +1246,144 @@ func (d *Droidstubs) collectStubsFlags(ctx android.ModuleContext, apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") || String(d.properties.Removed_api_filename) != "" { d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt") - metalavaFlags = metalavaFlags + " --removed-api " + d.removedApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.removedApiFile) + cmd.FlagWithOutput("--removed-api ", d.removedApiFile) } if String(d.properties.Private_api_filename) != "" { d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename)) - metalavaFlags = metalavaFlags + " --private-api " + d.privateApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.privateApiFile) + cmd.FlagWithOutput("--private-api ", d.privateApiFile) } if String(d.properties.Dex_api_filename) != "" { d.dexApiFile = android.PathForModuleOut(ctx, String(d.properties.Dex_api_filename)) - metalavaFlags += " --dex-api " + d.dexApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.dexApiFile) + cmd.FlagWithOutput("--dex-api ", d.dexApiFile) } if String(d.properties.Private_dex_api_filename) != "" { d.privateDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_dex_api_filename)) - metalavaFlags = metalavaFlags + " --private-dex-api " + d.privateDexApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.privateDexApiFile) + cmd.FlagWithOutput("--private-dex-api ", d.privateDexApiFile) } if String(d.properties.Removed_dex_api_filename) != "" { d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename)) - metalavaFlags = metalavaFlags + " --removed-dex-api " + d.removedDexApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.removedDexApiFile) + cmd.FlagWithOutput("--removed-dex-api ", d.removedDexApiFile) } if String(d.properties.Exact_api_filename) != "" { d.exactApiFile = android.PathForModuleOut(ctx, String(d.properties.Exact_api_filename)) - metalavaFlags = metalavaFlags + " --exact-api " + d.exactApiFile.String() - *implicitOutputs = append(*implicitOutputs, d.exactApiFile) + cmd.FlagWithOutput("--exact-api ", d.exactApiFile) } if String(d.properties.Dex_mapping_filename) != "" { d.apiMappingFile = android.PathForModuleOut(ctx, String(d.properties.Dex_mapping_filename)) - metalavaFlags = metalavaFlags + " --dex-api-mapping " + d.apiMappingFile.String() - *implicitOutputs = append(*implicitOutputs, d.apiMappingFile) + cmd.FlagWithOutput("--dex-api-mapping ", d.apiMappingFile) } if String(d.properties.Proguard_filename) != "" { d.proguardFile = android.PathForModuleOut(ctx, String(d.properties.Proguard_filename)) - metalavaFlags += " --proguard " + d.proguardFile.String() - *implicitOutputs = append(*implicitOutputs, d.proguardFile) + cmd.FlagWithOutput("--proguard ", d.proguardFile) } if Bool(d.properties.Write_sdk_values) { - metalavaFlags = metalavaFlags + " --sdk-values " + android.PathForModuleOut(ctx, "out").String() + cmd.FlagWithArg("--sdk-values ", android.PathForModuleOut(ctx, "out").String()) } if Bool(d.properties.Create_doc_stubs) { - metalavaFlags += " --doc-stubs " + android.PathForModuleOut(ctx, "stubsDir").String() + cmd.FlagWithArg("--doc-stubs ", stubsDir.String()) } else { - metalavaFlags += " --stubs " + android.PathForModuleOut(ctx, "stubsDir").String() + cmd.FlagWithArg("--stubs ", stubsDir.String()) } - return metalavaFlags } -func (d *Droidstubs) collectAnnotationsFlags(ctx android.ModuleContext, - implicits *android.Paths, implicitOutputs *android.WritablePaths) (string, string) { - var flags, mergeAnnoDirFlags string +func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { if Bool(d.properties.Annotations_enabled) { - flags += " --include-annotations" + cmd.Flag("--include-annotations") + validatingNullability := strings.Contains(d.Javadoc.args, "--validate-nullability-from-merged-stubs") || String(d.properties.Validate_nullability_from_list) != "" migratingNullability := String(d.properties.Previous_api) != "" + if !(migratingNullability || validatingNullability) { ctx.PropertyErrorf("previous_api", "has to be non-empty if annotations was enabled (unless validating nullability)") } + if migratingNullability { previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api)) - *implicits = append(*implicits, previousApi) - flags += " --migrate-nullness " + previousApi.String() + cmd.FlagWithInput("--migrate-nullness ", previousApi) } + if s := String(d.properties.Validate_nullability_from_list); s != "" { - flags += " --validate-nullability-from-list " + android.PathForModuleSrc(ctx, s).String() + cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s)) } + if validatingNullability { d.nullabilityWarningsFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_nullability_warnings.txt") - *implicitOutputs = append(*implicitOutputs, d.nullabilityWarningsFile) - flags += " --nullability-warnings-txt " + d.nullabilityWarningsFile.String() + cmd.FlagWithOutput("--nullability-warnings-txt ", d.nullabilityWarningsFile) } d.annotationsZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"_annotations.zip") - *implicitOutputs = append(*implicitOutputs, d.annotationsZip) - - flags += " --extract-annotations " + d.annotationsZip.String() + cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip) if len(d.properties.Merge_annotations_dirs) == 0 { ctx.PropertyErrorf("merge_annotations_dirs", "has to be non-empty if annotations was enabled!") } - ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) { - if t, ok := m.(*ExportedDroiddocDir); ok { - *implicits = append(*implicits, t.deps...) - mergeAnnoDirFlags += " --merge-qualifier-annotations " + t.dir.String() - } else { - ctx.PropertyErrorf("merge_annotations_dirs", - "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) - } - }) - flags += mergeAnnoDirFlags + + d.mergeAnnoDirFlags(ctx, cmd) + // TODO(tnorbye): find owners to fix these warnings when annotation was enabled. - flags += " --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction" + cmd.FlagWithArg("--hide ", "HiddenTypedefConstant"). + FlagWithArg("--hide ", "SuperfluousPrefix"). + FlagWithArg("--hide ", "AnnotationExtraction") } +} - return flags, mergeAnnoDirFlags +func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { + ctx.VisitDirectDepsWithTag(metalavaMergeAnnotationsDirTag, func(m android.Module) { + if t, ok := m.(*ExportedDroiddocDir); ok { + cmd.FlagWithArg("--merge-qualifier-annotations ", t.dir.String()).Implicits(t.deps) + } else { + ctx.PropertyErrorf("merge_annotations_dirs", + "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) + } + }) } -func (d *Droidstubs) collectInclusionAnnotationsFlags(ctx android.ModuleContext, - implicits *android.Paths, implicitOutputs *android.WritablePaths) string { - var flags string +func (d *Droidstubs) inclusionAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { ctx.VisitDirectDepsWithTag(metalavaMergeInclusionAnnotationsDirTag, func(m android.Module) { if t, ok := m.(*ExportedDroiddocDir); ok { - *implicits = append(*implicits, t.deps...) - flags += " --merge-inclusion-annotations " + t.dir.String() + cmd.FlagWithArg("--merge-inclusion-annotations ", t.dir.String()).Implicits(t.deps) } else { ctx.PropertyErrorf("merge_inclusion_annotations_dirs", "module %q is not a metalava merge-annotations dir", ctx.OtherModuleName(m)) } }) - - return flags } -func (d *Droidstubs) collectAPILevelsAnnotationsFlags(ctx android.ModuleContext, - implicits *android.Paths, implicitOutputs *android.WritablePaths) string { - var flags string +func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { if Bool(d.properties.Api_levels_annotations_enabled) { d.apiVersionsXml = android.PathForModuleOut(ctx, "api-versions.xml") - *implicitOutputs = append(*implicitOutputs, d.apiVersionsXml) if len(d.properties.Api_levels_annotations_dirs) == 0 { ctx.PropertyErrorf("api_levels_annotations_dirs", "has to be non-empty if api levels annotations was enabled!") } - flags = " --generate-api-levels " + d.apiVersionsXml.String() + " --apply-api-levels " + - d.apiVersionsXml.String() + " --current-version " + ctx.Config().PlatformSdkVersion() + - " --current-codename " + ctx.Config().PlatformSdkCodename() + " " + cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml) + cmd.FlagWithInput("--apply-api-levels ", d.apiVersionsXml) + cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion()) + cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename()) ctx.VisitDirectDepsWithTag(metalavaAPILevelsAnnotationsDirTag, func(m android.Module) { if t, ok := m.(*ExportedDroiddocDir); ok { - var androidJars android.Paths for _, dep := range t.deps { if strings.HasSuffix(dep.String(), "android.jar") { - androidJars = append(androidJars, dep) + cmd.Implicit(dep) } } - *implicits = append(*implicits, androidJars...) - flags += " --android-jar-pattern " + t.dir.String() + "/%/public/android.jar " + cmd.FlagWithArg("--android-jar-pattern ", t.dir.String()+"/%/public/android.jar") } else { ctx.PropertyErrorf("api_levels_annotations_dirs", "module %q is not a metalava api-levels-annotations dir", ctx.OtherModuleName(m)) @@ -1503,112 +1391,57 @@ func (d *Droidstubs) collectAPILevelsAnnotationsFlags(ctx android.ModuleContext, }) } - - return flags } -func (d *Droidstubs) collectApiToXmlFlags(ctx android.ModuleContext, implicits *android.Paths, - implicitOutputs *android.WritablePaths) string { - var flags string +func (d *Droidstubs) apiToXmlFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) { if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() { if d.apiFile.String() == "" { ctx.ModuleErrorf("API signature file has to be specified in Metalava when jdiff is enabled.") } d.apiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.xml") - *implicitOutputs = append(*implicitOutputs, d.apiXmlFile) - - flags = " --api-xml " + d.apiXmlFile.String() + cmd.FlagWithOutput("--api-xml ", d.apiXmlFile) if String(d.properties.Check_api.Last_released.Api_file) == "" { ctx.PropertyErrorf("check_api.last_released.api_file", "has to be non-empty if jdiff was enabled!") } - lastReleasedApi := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file), - "check_api.last_released.api_file") - *implicits = append(*implicits, lastReleasedApi) + lastReleasedApi := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file)) d.lastReleasedApiXmlFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_last_released_api.xml") - *implicitOutputs = append(*implicitOutputs, d.lastReleasedApiXmlFile) + cmd.FlagWithInput("--convert-to-jdiff ", lastReleasedApi).Output(d.lastReleasedApiXmlFile) + } +} + +func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion string, srcs android.Paths, + srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths) *android.RuleBuilderCommand { + cmd := rule.Command().BuiltTool(ctx, "metalava"). + Flag(config.JavacVmFlags). + FlagWithArg("-encoding ", "UTF-8"). + FlagWithArg("-source ", javaVersion). + FlagWithRspFileInputList("@", srcs). + FlagWithInput("@", srcJarList) - flags += " --convert-to-jdiff " + lastReleasedApi.String() + " " + - d.lastReleasedApiXmlFile.String() + if len(bootclasspath) > 0 { + cmd.FlagWithInputList("-bootclasspath ", bootclasspath.Paths(), ":") } - return flags -} + if len(classpath) > 0 { + cmd.FlagWithInputList("-classpath ", classpath.Paths(), ":") + } -func (d *Droidstubs) transformMetalava(ctx android.ModuleContext, implicits android.Paths, - implicitOutputs android.WritablePaths, javaVersion, - bootclasspathArgs, classpathArgs, sourcepathArgs, opts string) { - - ctx.Build(pctx, android.BuildParams{ - Rule: metalava, - Description: "Metalava", - Output: d.Javadoc.stubsSrcJar, - Inputs: d.Javadoc.srcFiles, - Implicits: implicits, - ImplicitOutputs: implicitOutputs, - Args: map[string]string{ - "outDir": android.PathForModuleOut(ctx, "out").String(), - "srcJarDir": android.PathForModuleOut(ctx, "srcjars").String(), - "stubsDir": android.PathForModuleOut(ctx, "stubsDir").String(), - "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), - "javaVersion": javaVersion, - "bootclasspathArgs": bootclasspathArgs, - "classpathArgs": classpathArgs, - "sourcepathArgs": sourcepathArgs, - "opts": opts, - }, - }) -} + if len(sourcepaths) > 0 { + cmd.FlagWithList("-sourcepath ", sourcepaths.Strings(), ":") + } else { + cmd.FlagWithArg("-sourcepath ", `""`) + } -func (d *Droidstubs) transformCheckApi(ctx android.ModuleContext, - apiFile, removedApiFile android.Path, implicits android.Paths, - javaVersion, bootclasspathArgs, classpathArgs, sourcepathArgs, opts, subdir, msg string, - output android.WritablePath) { - ctx.Build(pctx, android.BuildParams{ - Rule: metalavaApiCheck, - Description: "Metalava Check API", - Output: output, - Inputs: d.Javadoc.srcFiles, - Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile}, - implicits...), - Args: map[string]string{ - "srcJarDir": android.PathForModuleOut(ctx, subdir, "srcjars").String(), - "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), - "javaVersion": javaVersion, - "bootclasspathArgs": bootclasspathArgs, - "classpathArgs": classpathArgs, - "sourcepathArgs": sourcepathArgs, - "opts": opts, - "msg": msg, - }, - }) -} + cmd.Flag("--no-banner"). + Flag("--color"). + Flag("--quiet"). + Flag("--format=v2") -func (d *Droidstubs) transformJdiff(ctx android.ModuleContext, implicits android.Paths, - implicitOutputs android.WritablePaths, - bootclasspathArgs, classpathArgs, sourcepathArgs, opts string) { - ctx.Build(pctx, android.BuildParams{ - Rule: javadoc, - Description: "Jdiff", - Output: d.jdiffStubsSrcJar, - Inputs: d.Javadoc.srcFiles, - Implicits: implicits, - ImplicitOutputs: implicitOutputs, - Args: map[string]string{ - "outDir": android.PathForModuleOut(ctx, "jdiff-out").String(), - "srcJarDir": android.PathForModuleOut(ctx, "jdiff-srcjars").String(), - "stubsDir": android.PathForModuleOut(ctx, "jdiff-stubsDir").String(), - "srcJars": strings.Join(d.Javadoc.srcJars.Strings(), " "), - "opts": opts, - "bootclasspathArgs": bootclasspathArgs, - "classpathArgs": classpathArgs, - "sourcepathArgs": sourcepathArgs, - "docZip": d.jdiffDocZip.String(), - }, - }) + return cmd } func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1616,29 +1449,29 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), sdkContext(d)) - var implicits android.Paths - implicits = append(implicits, d.Javadoc.srcJars...) - implicits = append(implicits, d.Javadoc.argFiles...) + // Create rule for metalava - var implicitOutputs android.WritablePaths - for _, o := range d.Javadoc.properties.Out { - implicitOutputs = append(implicitOutputs, android.PathForModuleGen(ctx, o)) - } + d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"stubs.srcjar") - flags, err := d.initBuilderFlags(ctx, &implicits, deps) - metalavaCheckApiImplicits := implicits - jdiffImplicits := implicits + srcJarDir := android.PathForModuleOut(ctx, "srcjars") + stubsDir := android.PathForModuleOut(ctx, "stubsDir") - if err != nil { - return - } + rule := android.NewRuleBuilder() + + rule.Command().Text("rm -rf").Text(stubsDir.String()) + rule.Command().Text("mkdir -p").Text(stubsDir.String()) - flags.metalavaStubsFlags = d.collectStubsFlags(ctx, &implicitOutputs) - flags.metalavaAnnotationsFlags, flags.metalavaMergeAnnoDirFlags = - d.collectAnnotationsFlags(ctx, &implicits, &implicitOutputs) - flags.metalavaInclusionAnnotationsFlags = d.collectInclusionAnnotationsFlags(ctx, &implicits, &implicitOutputs) - flags.metalavaApiLevelsAnnotationsFlags = d.collectAPILevelsAnnotationsFlags(ctx, &implicits, &implicitOutputs) - flags.metalavaApiToXmlFlags = d.collectApiToXmlFlags(ctx, &implicits, &implicitOutputs) + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars) + + cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList, + deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths) + + d.stubsFlags(ctx, cmd, stubsDir) + + d.annotationsFlags(ctx, cmd) + d.inclusionAnnotationsFlags(ctx, cmd) + d.apiLevelsAnnotationsFlags(ctx, cmd) + d.apiToXmlFlags(ctx, cmd) if strings.Contains(d.Javadoc.args, "--generate-documentation") { // Currently Metalava have the ability to invoke Javadoc in a seperate process. @@ -1646,61 +1479,164 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { // "--generate-documentation" arg. This is not needed when Metalava removes this feature. d.Javadoc.args = d.Javadoc.args + " -nodocs " } - d.transformMetalava(ctx, implicits, implicitOutputs, javaVersion, - flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, - flags.metalavaStubsFlags+flags.metalavaAnnotationsFlags+flags.metalavaInclusionAnnotationsFlags+ - flags.metalavaApiLevelsAnnotationsFlags+flags.metalavaApiToXmlFlags+" "+d.Javadoc.args) + + cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles) + for _, o := range d.Javadoc.properties.Out { + cmd.ImplicitOutput(android.PathForModuleGen(ctx, o)) + } + + rule.Command(). + BuiltTool(ctx, "soong_zip"). + Flag("-write_if_changed"). + Flag("-jar"). + FlagWithOutput("-o ", d.Javadoc.stubsSrcJar). + FlagWithArg("-C ", stubsDir.String()). + FlagWithArg("-D ", stubsDir.String()) + rule.Restat() + + zipSyncCleanupCmd(rule, srcJarDir) + + rule.Build(pctx, ctx, "metalava", "metalava") + + // Create rule for apicheck if apiCheckEnabled(d.properties.Check_api.Current, "current") && !ctx.Config().IsPdkBuild() { - apiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Api_file), - "check_api.current.api_file") - removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Current.Removed_api_file), - "check_api.current_removed_api_file") + + if len(d.Javadoc.properties.Out) > 0 { + ctx.PropertyErrorf("out", "out property may not be combined with check_api") + } + + apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file)) + removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Removed_api_file)) + baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Current.Baseline_file) + updatedBaselineOutput := android.PathForModuleOut(ctx, "current_baseline.txt") d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp") - opts := " " + d.Javadoc.args + " --check-compatibility:api:current " + apiFile.String() + - " --check-compatibility:removed:current " + removedApiFile.String() + - flags.metalavaInclusionAnnotationsFlags + flags.metalavaMergeAnnoDirFlags + " " - - d.transformCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits, - javaVersion, flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, opts, "current-apicheck", - fmt.Sprintf(`\n******************************\n`+ - `You have tried to change the API from what has been previously approved.\n\n`+ - `To make these errors go away, you have two choices:\n`+ - ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+ - ` errors above.\n\n`+ - ` 2. You can update current.txt by executing the following command:\n`+ - ` make %s-update-current-api\n\n`+ - ` To submit the revised current.txt to the main Android repository,\n`+ - ` you will need approval.\n`+ - `******************************\n`, ctx.ModuleName()), - d.checkCurrentApiTimestamp) + + rule := android.NewRuleBuilder() + + rule.Command().Text("( true") + + srcJarDir := android.PathForModuleOut(ctx, "current-apicheck", "srcjars") + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars) + + cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList, + deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths) + + cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles). + FlagWithInput("--check-compatibility:api:current ", apiFile). + FlagWithInput("--check-compatibility:removed:current ", removedApiFile) + + d.inclusionAnnotationsFlags(ctx, cmd) + d.mergeAnnoDirFlags(ctx, cmd) + + if baselineFile.Valid() { + cmd.FlagWithInput("--baseline ", baselineFile.Path()) + cmd.FlagWithOutput("--update-baseline ", updatedBaselineOutput) + } + + zipSyncCleanupCmd(rule, srcJarDir) + + msg := fmt.Sprintf(`\n******************************\n`+ + `You have tried to change the API from what has been previously approved.\n\n`+ + `To make these errors go away, you have two choices:\n`+ + ` 1. You can add '@hide' javadoc comments to the methods, etc. listed in the\n`+ + ` errors above.\n\n`+ + ` 2. You can update current.txt by executing the following command:\n`+ + ` make %s-update-current-api\n\n`+ + ` To submit the revised current.txt to the main Android repository,\n`+ + ` you will need approval.\n`+ + `******************************\n`, ctx.ModuleName()) + + rule.Command(). + Text("touch").Output(d.checkCurrentApiTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "metalavaCurrentApiCheck", "metalava check current API") d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp") - transformUpdateApi(ctx, apiFile, removedApiFile, d.apiFile, d.removedApiFile, - d.updateCurrentApiTimestamp) + + // update API rule + rule = android.NewRuleBuilder() + + rule.Command().Text("( true") + + rule.Command(). + Text("cp").Flag("-f"). + Input(d.apiFile).Flag(apiFile.String()) + + rule.Command(). + Text("cp").Flag("-f"). + Input(d.removedApiFile).Flag(removedApiFile.String()) + + msg = "failed to update public API" + + rule.Command(). + Text("touch").Output(d.updateCurrentApiTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "metalavaCurrentApiUpdate", "update current API") } if apiCheckEnabled(d.properties.Check_api.Last_released, "last_released") && !ctx.Config().IsPdkBuild() { - apiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Api_file), - "check_api.last_released.api_file") - removedApiFile := ctx.ExpandSource(String(d.properties.Check_api.Last_released.Removed_api_file), - "check_api.last_released.removed_api_file") + + if len(d.Javadoc.properties.Out) > 0 { + ctx.PropertyErrorf("out", "out property may not be combined with check_api") + } + + apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file)) + removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file)) + baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file) + updatedBaselineOutput := android.PathForModuleOut(ctx, "last_released_baseline.txt") d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp") - opts := " " + d.Javadoc.args + " --check-compatibility:api:released " + apiFile.String() + - flags.metalavaInclusionAnnotationsFlags + " --check-compatibility:removed:released " + - removedApiFile.String() + flags.metalavaMergeAnnoDirFlags + " " - d.transformCheckApi(ctx, apiFile, removedApiFile, metalavaCheckApiImplicits, - javaVersion, flags.bootClasspathArgs, flags.classpathArgs, flags.sourcepathArgs, opts, "last-apicheck", - `\n******************************\n`+ - `You have tried to change the API from what has been previously released in\n`+ - `an SDK. Please fix the errors listed above.\n`+ - `******************************\n`, - d.checkLastReleasedApiTimestamp) + rule := android.NewRuleBuilder() + + rule.Command().Text("( true") + + srcJarDir := android.PathForModuleOut(ctx, "last-apicheck", "srcjars") + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars) + + cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList, + deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths) + + cmd.Flag(d.Javadoc.args).Implicits(d.Javadoc.argFiles). + FlagWithInput("--check-compatibility:api:released ", apiFile) + + d.inclusionAnnotationsFlags(ctx, cmd) + + cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile) + + d.mergeAnnoDirFlags(ctx, cmd) + + if baselineFile.Valid() { + cmd.FlagWithInput("--baseline ", baselineFile.Path()) + cmd.FlagWithOutput("--update-baseline ", updatedBaselineOutput) + } + + zipSyncCleanupCmd(rule, srcJarDir) + + msg := `\n******************************\n` + + `You have tried to change the API from what has been previously released in\n` + + `an SDK. Please fix the errors listed above.\n` + + `******************************\n` + rule.Command(). + Text("touch").Output(d.checkLastReleasedApiTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "metalavaLastApiCheck", "metalava check last API") } if String(d.properties.Check_nullability_warnings) != "" { @@ -1708,9 +1644,11 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { ctx.PropertyErrorf("check_nullability_warnings", "Cannot specify check_nullability_warnings unless validating nullability") } - checkNullabilityWarnings := ctx.ExpandSource(String(d.properties.Check_nullability_warnings), - "check_nullability_warnings") + + checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings)) + d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, "check_nullability_warnings.timestamp") + msg := fmt.Sprintf(`\n******************************\n`+ `The warnings encountered during nullability annotation validation did\n`+ `not match the checked in file of expected warnings. The diffs are shown\n`+ @@ -1720,20 +1658,32 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { ` cp %s %s\n`+ ` and submitting the updated file as part of your change.`, d.nullabilityWarningsFile, checkNullabilityWarnings) - ctx.Build(pctx, android.BuildParams{ - Rule: nullabilityWarningsCheck, - Description: "Nullability Warnings Check", - Output: d.checkNullabilityWarningsTimestamp, - Implicits: android.Paths{checkNullabilityWarnings, d.nullabilityWarningsFile}, - Args: map[string]string{ - "expected": checkNullabilityWarnings.String(), - "actual": d.nullabilityWarningsFile.String(), - "msg": msg, - }, - }) + + rule := android.NewRuleBuilder() + + rule.Command(). + Text("("). + Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile). + Text("&&"). + Text("touch").Output(d.checkNullabilityWarningsTimestamp). + Text(") || ("). + Text("echo").Flag("-e").Flag(`"` + msg + `"`). + Text("; exit 38"). + Text(")") + + rule.Build(pctx, ctx, "nullabilityWarningsCheck", "nullability warnings check") } if Bool(d.properties.Jdiff_enabled) && !ctx.Config().IsPdkBuild() { + if len(d.Javadoc.properties.Out) > 0 { + ctx.PropertyErrorf("out", "out property may not be combined with jdiff") + } + + outDir := android.PathForModuleOut(ctx, "jdiff-out") + srcJarDir := android.PathForModuleOut(ctx, "jdiff-srcjars") + stubsDir := android.PathForModuleOut(ctx, "jdiff-stubsDir") + + rule := android.NewRuleBuilder() // Please sync with android-api-council@ before making any changes for the name of jdiffDocZip below // since there's cron job downstream that fetch this .zip file periodically. @@ -1741,21 +1691,49 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) { d.jdiffDocZip = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-docs.zip") d.jdiffStubsSrcJar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"jdiff-stubs.srcjar") - var jdiffImplicitOutputs android.WritablePaths - jdiffImplicitOutputs = append(jdiffImplicitOutputs, d.jdiffDocZip) - jdiff := android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "jdiff.jar") - jdiffImplicits = append(jdiffImplicits, android.Paths{jdiff, d.apiXmlFile, d.lastReleasedApiXmlFile}...) - opts := " -source 1.8 -J-Xmx1600m -XDignore.symbol.file " + - "-doclet jdiff.JDiff -docletpath " + jdiff.String() + " -quiet " + - "-newapi " + strings.TrimSuffix(d.apiXmlFile.Base(), d.apiXmlFile.Ext()) + - " -newapidir " + filepath.Dir(d.apiXmlFile.String()) + - " -oldapi " + strings.TrimSuffix(d.lastReleasedApiXmlFile.Base(), d.lastReleasedApiXmlFile.Ext()) + - " -oldapidir " + filepath.Dir(d.lastReleasedApiXmlFile.String()) + rule.Command().Text("rm -rf").Text(outDir.String()).Text(stubsDir.String()) + rule.Command().Text("mkdir -p").Text(outDir.String()).Text(stubsDir.String()) + + srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars) - d.transformJdiff(ctx, jdiffImplicits, jdiffImplicitOutputs, flags.bootClasspathArgs, flags.classpathArgs, - flags.sourcepathArgs, opts) + cmd := javadocBootclasspathCmd(ctx, rule, d.Javadoc.srcFiles, outDir, srcJarDir, srcJarList, + deps.bootClasspath, deps.classpath, d.sourcepaths) + + cmd.Flag("-J-Xmx1600m"). + Flag("-XDignore.symbol.file"). + FlagWithArg("-doclet ", "jdiff.JDiff"). + FlagWithInput("-docletpath ", jdiff). + Flag("-quiet"). + FlagWithArg("-newapi ", strings.TrimSuffix(d.apiXmlFile.Base(), d.apiXmlFile.Ext())). + FlagWithArg("-newapidir ", filepath.Dir(d.apiXmlFile.String())). + Implicit(d.apiXmlFile). + FlagWithArg("-oldapi ", strings.TrimSuffix(d.lastReleasedApiXmlFile.Base(), d.lastReleasedApiXmlFile.Ext())). + FlagWithArg("-oldapidir ", filepath.Dir(d.lastReleasedApiXmlFile.String())). + Implicit(d.lastReleasedApiXmlFile) + + rule.Command(). + BuiltTool(ctx, "soong_zip"). + Flag("-write_if_changed"). + Flag("-d"). + FlagWithOutput("-o ", d.jdiffDocZip). + FlagWithArg("-C ", outDir.String()). + FlagWithArg("-D ", outDir.String()) + + rule.Command(). + BuiltTool(ctx, "soong_zip"). + Flag("-write_if_changed"). + Flag("-jar"). + FlagWithOutput("-o ", d.jdiffStubsSrcJar). + FlagWithArg("-C ", stubsDir.String()). + FlagWithArg("-D ", stubsDir.String()) + + rule.Restat() + + zipSyncCleanupCmd(rule, srcJarDir) + + rule.Build(pctx, ctx, "jdiff", "jdiff") } } @@ -1781,6 +1759,7 @@ type ExportedDroiddocDir struct { dir android.Path } +// droiddoc_exported_dir exports a directory of html templates or nullability annotations for use by doclava. func ExportedDroiddocDirFactory() android.Module { module := &ExportedDroiddocDir{} module.AddProperties(&module.properties) @@ -1829,3 +1808,25 @@ func StubsDefaultsFactory() android.Module { return module } + +func zipSyncCmd(ctx android.ModuleContext, rule *android.RuleBuilder, + srcJarDir android.ModuleOutPath, srcJars android.Paths) android.OutputPath { + + rule.Command().Text("rm -rf").Text(srcJarDir.String()) + rule.Command().Text("mkdir -p").Text(srcJarDir.String()) + srcJarList := srcJarDir.Join(ctx, "list") + + rule.Temporary(srcJarList) + + rule.Command().BuiltTool(ctx, "zipsync"). + FlagWithArg("-d ", srcJarDir.String()). + FlagWithOutput("-l ", srcJarList). + FlagWithArg("-f ", `"*.java"`). + Inputs(srcJars) + + return srcJarList +} + +func zipSyncCleanupCmd(rule *android.RuleBuilder, srcJarDir android.ModuleOutPath) { + rule.Command().Text("rm -rf").Text(srcJarDir.String()) +} diff --git a/java/gen.go b/java/gen.go index b1c028d12..69965ecec 100644 --- a/java/gen.go +++ b/java/gen.go @@ -15,6 +15,8 @@ package java import ( + "strings" + "github.com/google/blueprint" "android/soong/android" @@ -63,6 +65,10 @@ var ( func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path { javaFile := android.GenPathWithExt(ctx, "aidl", aidlFile, "java") depFile := javaFile.String() + ".d" + baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel()) + if baseDir != "" { + aidlFlags += " -I" + baseDir + } ctx.Build(pctx, android.BuildParams{ Rule: aidl, diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index cf9f49285..8379f5397 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -64,7 +64,7 @@ func (h *hiddenAPISingleton) GenerateBuildActions(ctx android.SingletonContext) stubFlagsRule(ctx) // These rules depend on files located in frameworks/base, skip them if running in a tree that doesn't have them. - if ctx.Config().FrameworksBaseDirExists(ctx) && !ctx.Config().UnbundledBuild() { + if ctx.Config().FrameworksBaseDirExists(ctx) { h.flags = flagsRule(ctx) h.metadata = metadataRule(ctx) } else { @@ -97,7 +97,7 @@ func stubFlagsRule(ctx android.SingletonContext) { // Add the android.test.base to the set of stubs only if the android.test.base module is on // the boot jars list as the runtime will only enforce hiddenapi access against modules on // that list. - if inList("android.test.base", ctx.Config().BootJars()) { + if inList("android.test.base", ctx.Config().BootJars()) && !ctx.Config().UnbundledBuildUsePrebuiltSdks() { publicStubModules = append(publicStubModules, "android.test.base.stubs") } @@ -152,6 +152,14 @@ func stubFlagsRule(ctx android.SingletonContext) { // Collect dex jar paths for modules that had hiddenapi encode called on them. if h, ok := module.(hiddenAPIIntf); ok { if jar := h.bootDexJar(); jar != nil { + // For a java lib included in an APEX, only take the one built for + // the platform variant, and skip the variants for APEXes. + // Otherwise, the hiddenapi tool will complain about duplicated classes + if a, ok := module.(android.ApexModule); ok { + if android.InAnyApex(module.Name()) && !a.IsForPlatform() { + return + } + } bootDexJars = append(bootDexJars, jar) } } diff --git a/java/java.go b/java/java.go index 7c84e766f..3b789f689 100644 --- a/java/java.go +++ b/java/java.go @@ -50,6 +50,21 @@ func init() { android.RegisterModuleType("dex_import", DexImportFactory) android.RegisterSingletonType("logtags", LogtagsSingleton) + android.RegisterSingletonType("kythe_java_extract", kytheExtractJavaFactory) +} + +func (j *Module) checkPlatformAPI(ctx android.ModuleContext) { + if sc, ok := ctx.Module().(sdkContext); ok { + usePlatformAPI := proptools.Bool(j.deviceProperties.Platform_apis) + if usePlatformAPI != (sc.sdkVersion() == "") { + if usePlatformAPI { + ctx.PropertyErrorf("platform_apis", "platform_apis must be false when sdk_version is not empty.") + } else { + ctx.PropertyErrorf("platform_apis", "platform_apis must be true when sdk_version is empty.") + } + } + + } } // TODO: @@ -178,8 +193,8 @@ type CompilerDeviceProperties struct { // list of module-specific flags that will be used for dex compiles Dxflags []string `android:"arch_variant"` - // if not blank, set to the version of the sdk to compile against. Defaults to compiling against the current - // sdk if platform_apis is not set. + // if not blank, set to the version of the sdk to compile against. + // Defaults to compiling against the current platform. Sdk_version *string // if not blank, set the minimum version of the sdk that the compiled artifacts will run against. @@ -190,7 +205,8 @@ type CompilerDeviceProperties struct { // Defaults to sdk_version if not set. Target_sdk_version *string - // if true, compile against the platform APIs instead of an SDK. + // It must be true only if sdk_version is empty. + // This field works in only android_app, otherwise nothing happens. Platform_apis *bool Aidl struct { @@ -267,6 +283,7 @@ func (me *CompilerDeviceProperties) EffectiveOptimizeEnabled() bool { type Module struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase properties CompilerProperties protoProperties android.ProtoProperties @@ -342,6 +359,9 @@ type Module struct { hiddenAPI dexpreopter + + // list of the xref extraction files + kytheFiles android.Paths } func (j *Module) OutputFiles(tag string) (android.Paths, error) { @@ -350,6 +370,8 @@ func (j *Module) OutputFiles(tag string) (android.Paths, error) { return append(android.Paths{j.outputFile}, j.extraOutputFiles...), nil case ".jar": return android.Paths{j.implementationAndResourcesJar}, nil + case ".proguard_map": + return android.Paths{j.proguardDictionary}, nil default: return nil, fmt.Errorf("unsupported module reference tag %q", tag) } @@ -382,6 +404,10 @@ type SrcDependency interface { CompiledSrcJars() android.Paths } +type xref interface { + XrefJavaFiles() android.Paths +} + func (j *Module) CompiledSrcs() android.Paths { return j.compiledJavaSrcs } @@ -390,6 +416,10 @@ func (j *Module) CompiledSrcJars() android.Paths { return j.compiledSrcJars } +func (j *Module) XrefJavaFiles() android.Paths { + return j.kytheFiles +} + var _ SrcDependency = (*Module)(nil) func InitJavaModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) { @@ -632,8 +662,7 @@ type deps struct { aidlIncludeDirs android.Paths srcs android.Paths srcJars android.Paths - systemModules android.Path - systemModulesDeps android.Paths + systemModules *systemModules aidlPreprocess android.OptionalPath kotlinStdlib android.Paths kotlinAnnotations android.Paths @@ -844,8 +873,7 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps { if sm.outputDir == nil || len(sm.outputDeps) == 0 { panic("Missing directory for system module dependency") } - deps.systemModules = sm.outputDir - deps.systemModulesDeps = sm.outputDeps + deps.systemModules = &systemModules{sm.outputDir, sm.outputDeps} } } }) @@ -973,10 +1001,7 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB } // systemModules - if deps.systemModules != nil { - flags.systemModules = append(flags.systemModules, deps.systemModules) - flags.systemModulesDeps = append(flags.systemModulesDeps, deps.systemModulesDeps...) - } + flags.systemModules = deps.systemModules // aidl flags. flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs) @@ -1143,6 +1168,12 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { TransformJavaToClasses(ctx, classes, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps) jars = append(jars, classes) } + if ctx.Config().EmitXrefRules() { + extractionFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".kzip") + emitXrefRule(ctx, extractionFile, uniqueSrcFiles, srcJars, flags, extraJarDeps, "xref") + j.kytheFiles = append(j.kytheFiles, extractionFile) + + } if ctx.Failed() { return } @@ -1322,11 +1353,9 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) { return } - if !ctx.Config().UnbundledBuild() { - // Hidden API CSV generation and dex encoding - dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile, - j.deviceProperties.UncompressDex) - } + // Hidden API CSV generation and dex encoding + dexOutputFile = j.hiddenAPI.hiddenAPI(ctx, dexOutputFile, j.implementationJarFile, + j.deviceProperties.UncompressDex) // merge dex jar with resources if necessary if j.resourceJar != nil { @@ -1557,7 +1586,8 @@ func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) { j.deviceProperties.UncompressDex = j.dexpreopter.uncompressedDex j.compile(ctx, nil) - if (Bool(j.properties.Installable) || ctx.Host()) && !android.DirectlyInAnyApex(ctx, ctx.ModuleName()) { + exclusivelyForApex := android.InAnyApex(ctx.ModuleName()) && !j.IsForPlatform() + if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex { j.installFile = ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"), ctx.ModuleName()+".jar", j.outputFile) } @@ -1588,6 +1618,7 @@ func LibraryFactory() android.Module { &module.Module.protoProperties) InitJavaModule(module, android.HostAndDeviceSupported) + android.InitApexModule(module) return module } @@ -1610,6 +1641,7 @@ func LibraryHostFactory() android.Module { module.Module.properties.Installable = proptools.BoolPtr(true) InitJavaModule(module, android.HostSupported) + android.InitApexModule(module) return module } @@ -1865,6 +1897,7 @@ type ImportProperties struct { type Import struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase prebuilt android.Prebuilt properties ImportProperties @@ -2021,6 +2054,7 @@ func ImportFactory() android.Module { android.InitPrebuiltModule(module, &module.properties.Jars) InitJavaModule(module, android.HostAndDeviceSupported) + android.InitApexModule(module) return module } @@ -2036,18 +2070,20 @@ func ImportFactoryHost() android.Module { android.InitPrebuiltModule(module, &module.properties.Jars) InitJavaModule(module, android.HostSupported) + android.InitApexModule(module) return module } // dex_import module type DexImportProperties struct { - Jars []string + Jars []string `android:"path"` } type DexImport struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase prebuilt android.Prebuilt properties DexImportProperties @@ -2070,10 +2106,6 @@ func (j *DexImport) Name() string { return j.prebuilt.Name(j.ModuleBase.Name()) } -func (j *DexImport) DepsMutator(ctx android.BottomUpMutatorContext) { - android.ExtractSourcesDeps(ctx, j.properties.Jars) -} - func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { if len(j.properties.Jars) != 1 { ctx.PropertyErrorf("jars", "exactly one jar must be provided") @@ -2094,14 +2126,14 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) { // use zip2zip to uncompress classes*.dex files rule.Command(). - Tool(ctx.Config().HostToolPath(ctx, "zip2zip")). + BuiltTool(ctx, "zip2zip"). FlagWithInput("-i ", inputJar). FlagWithOutput("-o ", temporary). FlagWithArg("-0 ", "'classes*.dex'") // use zipalign to align uncompressed classes*.dex files rule.Command(). - Tool(ctx.Config().HostToolPath(ctx, "zipalign")). + BuiltTool(ctx, "zipalign"). Flag("-f"). Text("4"). Input(temporary). @@ -2143,6 +2175,7 @@ func DexImportFactory() android.Module { android.InitPrebuiltModule(module, &module.properties.Jars) InitJavaModule(module, android.DeviceSupported) + android.InitApexModule(module) return module } @@ -2152,6 +2185,7 @@ func DexImportFactory() android.Module { type Defaults struct { android.ModuleBase android.DefaultsModuleBase + android.ApexModuleBase } // java_defaults provides a set of properties that can be inherited by other java or android modules. @@ -2210,10 +2244,34 @@ func DefaultsFactory(props ...interface{}) android.Module { ) android.InitDefaultsModule(module) - + android.InitApexModule(module) return module } +func kytheExtractJavaFactory() android.Singleton { + return &kytheExtractJavaSingleton{} +} + +type kytheExtractJavaSingleton struct { +} + +func (ks *kytheExtractJavaSingleton) GenerateBuildActions(ctx android.SingletonContext) { + var xrefTargets android.Paths + ctx.VisitAllModules(func(module android.Module) { + if javaModule, ok := module.(xref); ok { + xrefTargets = append(xrefTargets, javaModule.XrefJavaFiles()...) + } + }) + // TODO(asmundak): perhaps emit a rule to output a warning if there were no xrefTargets + if len(xrefTargets) > 0 { + ctx.Build(pctx, android.BuildParams{ + Rule: blueprint.Phony, + Output: android.PathForPhony(ctx, "xref_java"), + Inputs: xrefTargets, + }) + } +} + var Bool = proptools.Bool var BoolDefault = proptools.BoolDefault var String = proptools.String diff --git a/java/java_test.go b/java/java_test.go index 96ecdb689..17f3a218a 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -57,8 +57,7 @@ func testConfig(env map[string]string) android.Config { return TestConfig(buildDir, env) } -func testContext(config android.Config, bp string, - fs map[string][]byte) *android.TestContext { +func testContext(bp string, fs map[string][]byte) *android.TestContext { ctx := android.NewTestArchContext() ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(AndroidAppFactory)) @@ -193,6 +192,7 @@ func testContext(config android.Config, bp string, "bar-doc/a.java": nil, "bar-doc/b.java": nil, "bar-doc/IFoo.aidl": nil, + "bar-doc/IBar.aidl": nil, "bar-doc/known_oj_tags.txt": nil, "external/doclava/templates-sdk": nil, @@ -222,13 +222,36 @@ func run(t *testing.T, ctx *android.TestContext, config android.Config) { android.FailIfErrored(t, errs) } -func testJava(t *testing.T, bp string) *android.TestContext { +func testJavaError(t *testing.T, pattern string, bp string) { t.Helper() config := testConfig(nil) - ctx := testContext(config, bp, nil) + ctx := testContext(bp, nil) + + pathCtx := android.PathContextForTesting(config, nil) + setDexpreoptTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx)) + + ctx.Register() + _, errs := ctx.ParseBlueprintsFiles("Android.bp") + if len(errs) > 0 { + android.FailIfNoMatchingErrors(t, pattern, errs) + return + } + _, errs = ctx.PrepareBuildActions(config) + if len(errs) > 0 { + android.FailIfNoMatchingErrors(t, pattern, errs) + return + } + + t.Fatalf("missing expected error %q (0 errors are returned)", pattern) +} + +func testJava(t *testing.T, bp string) (*android.TestContext, android.Config) { + t.Helper() + config := testConfig(nil) + ctx := testContext(bp, nil) run(t, ctx, config) - return ctx + return ctx, config } func moduleToPath(name string) string { @@ -243,7 +266,7 @@ func moduleToPath(name string) string { } func TestSimple(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -287,7 +310,7 @@ func TestSimple(t *testing.T) { } func TestSdkVersion(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -313,7 +336,7 @@ func TestSdkVersion(t *testing.T) { } func TestArchSpecific(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -332,7 +355,7 @@ func TestArchSpecific(t *testing.T) { } func TestBinary(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library_host { name: "foo", srcs: ["a.java"], @@ -361,7 +384,7 @@ func TestBinary(t *testing.T) { } func TestPrebuilts(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -412,7 +435,7 @@ func TestPrebuilts(t *testing.T) { } func TestDefaults(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_defaults { name: "defaults", srcs: ["a.java"], @@ -558,7 +581,7 @@ func TestResources(t *testing.T) { for _, test := range table { t.Run(test.name, func(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: [ @@ -587,7 +610,7 @@ func TestResources(t *testing.T) { } func TestIncludeSrcs(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: [ @@ -650,7 +673,7 @@ func TestIncludeSrcs(t *testing.T) { } func TestGeneratedSources(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: [ @@ -683,7 +706,7 @@ func TestGeneratedSources(t *testing.T) { } func TestTurbine(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -732,7 +755,7 @@ func TestTurbine(t *testing.T) { } func TestSharding(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "bar", srcs: ["a.java","b.java","c.java"], @@ -750,16 +773,22 @@ func TestSharding(t *testing.T) { } func TestDroiddoc(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` droiddoc_template { name: "droiddoc-templates-sdk", path: ".", } + filegroup { + name: "bar-doc-aidl-srcs", + srcs: ["bar-doc/IBar.aidl"], + path: "bar-doc", + } droiddoc { name: "bar-doc", srcs: [ "bar-doc/*.java", "bar-doc/IFoo.aidl", + ":bar-doc-aidl-srcs", ], exclude_srcs: [ "bar-doc/b.java" @@ -777,23 +806,24 @@ func TestDroiddoc(t *testing.T) { } `) - stubsJar := filepath.Join(buildDir, ".intermediates", "bar-doc", "android_common", "bar-doc-stubs.srcjar") - barDoc := ctx.ModuleForTests("bar-doc", "android_common").Output("bar-doc-stubs.srcjar") - if stubsJar != barDoc.Output.String() { - t.Errorf("expected stubs Jar [%q], got %q", stubsJar, barDoc.Output.String()) - } inputs := ctx.ModuleForTests("bar-doc", "android_common").Rule("javadoc").Inputs var javaSrcs []string for _, i := range inputs { javaSrcs = append(javaSrcs, i.Base()) } - if len(javaSrcs) != 2 || javaSrcs[0] != "a.java" || javaSrcs[1] != "IFoo.java" { - t.Errorf("inputs of bar-doc must be []string{\"a.java\", \"IFoo.java\", but was %#v.", javaSrcs) + if len(javaSrcs) != 3 || javaSrcs[0] != "a.java" || javaSrcs[1] != "IFoo.java" || javaSrcs[2] != "IBar.java" { + t.Errorf("inputs of bar-doc must be []string{\"a.java\", \"IFoo.java\", \"IBar.java\", but was %#v.", javaSrcs) + } + + aidlRule := ctx.ModuleForTests("bar-doc", "android_common").Output(inputs[2].String()) + aidlFlags := aidlRule.Args["aidlFlags"] + if !strings.Contains(aidlFlags, "-Ibar-doc") { + t.Errorf("aidl flags for IBar.aidl should contain \"-Ibar-doc\", but was %q", aidlFlags) } } func TestJarGenrules(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -847,7 +877,7 @@ func TestJarGenrules(t *testing.T) { } func TestExcludeFileGroupInSrcs(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java", ":foo-srcs"], @@ -874,7 +904,7 @@ func TestExcludeFileGroupInSrcs(t *testing.T) { func TestJavaLibrary(t *testing.T) { config := testConfig(nil) - ctx := testContext(config, "", map[string][]byte{ + ctx := testContext("", map[string][]byte{ "libcore/Android.bp": []byte(` java_library { name: "core", @@ -886,7 +916,7 @@ func TestJavaLibrary(t *testing.T) { } func TestJavaSdkLibrary(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` droiddoc_template { name: "droiddoc-templates-sdk", path: ".", @@ -1057,7 +1087,7 @@ func TestPatchModule(t *testing.T) { t.Run("Java language level 8", func(t *testing.T) { // Test default javac -source 1.8 -target 1.8 - ctx := testJava(t, bp) + ctx, _ := testJava(t, bp) checkPatchModuleFlag(t, ctx, "foo", "") checkPatchModuleFlag(t, ctx, "bar", "") @@ -1067,7 +1097,7 @@ func TestPatchModule(t *testing.T) { t.Run("Java language level 9", func(t *testing.T) { // Test again with javac -source 9 -target 9 config := testConfig(map[string]string{"EXPERIMENTAL_JAVA_LANGUAGE_LEVEL_9": "true"}) - ctx := testContext(config, bp, nil) + ctx := testContext(bp, nil) run(t, ctx, config) checkPatchModuleFlag(t, ctx, "foo", "") diff --git a/java/kotlin_test.go b/java/kotlin_test.go index e0eb0c06d..5c6d45f45 100644 --- a/java/kotlin_test.go +++ b/java/kotlin_test.go @@ -22,7 +22,7 @@ import ( ) func TestKotlin(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java", "b.kt"], @@ -84,7 +84,7 @@ func TestKotlin(t *testing.T) { } func TestKapt(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java", "b.kt"], diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go new file mode 100644 index 000000000..792edf388 --- /dev/null +++ b/java/platform_compat_config.go @@ -0,0 +1,92 @@ +// 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" +) + +func init() { + android.RegisterModuleType("platform_compat_config", platformCompatConfigFactory) +} + +type platformCompatConfigProperties struct { + Src *string `android:"path"` + Prefix *string +} + +type platformCompatConfig struct { + android.ModuleBase + + properties platformCompatConfigProperties + installDirPath android.OutputPath + configFile android.OutputPath +} + +func (p *platformCompatConfig) GenerateAndroidBuildActions(ctx android.ModuleContext) { + rule := android.NewRuleBuilder() + + configFileName := String(p.properties.Prefix) + "_platform_compat_config.xml" + p.configFile = android.PathForModuleOut(ctx, configFileName).OutputPath + path := android.PathForModuleSrc(ctx, String(p.properties.Src)) + + // Use the empty config if the compat config file idoesn't exist (can happen if @ChangeId + // annotation is not used). + emptyConfig := `<?xml version="1.0" encoding="UTF-8" standalone="no"?><config/>` + configPath := `compat/compat_config.xml` + + rule.Command(). + Text(`unzip`). + Flag(`-l`). + Input(path). + Text(`| grep`). + Flag(`-q`). + Text(configPath). + Text(`; if [ "$?" = "0" ] ; then`). + Text(`unzip`). + Flag(`-qp`). + Input(path). + Text(configPath). + Text(`>`). + Output(p.configFile). + Text(`; else echo '`). + Text(emptyConfig). + Text(`' >`). + Output(p.configFile). + Text(`; fi`) + + p.installDirPath = android.PathForModuleInstall(ctx, "etc", "sysconfig") + rule.Build(pctx, ctx, configFileName, "Extract compat/compat_config.xml and install it") + +} + +func (p *platformCompatConfig) AndroidMkEntries() android.AndroidMkEntries { + return android.AndroidMkEntries{ + Class: "ETC", + OutputFile: android.OptionalPathForPath(p.configFile), + Include: "$(BUILD_PREBUILT)", + AddCustomEntries: func(name, prefix, moduleDir string, entries *android.AndroidMkEntries) { + entries.SetString("LOCAL_MODULE_PATH", "$(OUT_DIR)/"+p.installDirPath.RelPathString()) + entries.SetString("LOCAL_INSTALLED_MODULE_STEM", p.configFile.Base()) + }, + } +} + +func platformCompatConfigFactory() android.Module { + module := &platformCompatConfig{} + module.AddProperties(&module.properties) + android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst) + return module +} diff --git a/java/plugin_test.go b/java/plugin_test.go index d1aef2c19..c7913d3db 100644 --- a/java/plugin_test.go +++ b/java/plugin_test.go @@ -20,7 +20,7 @@ import ( ) func TestNoPlugin(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -44,7 +44,7 @@ func TestNoPlugin(t *testing.T) { } func TestPlugin(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], @@ -83,7 +83,7 @@ func TestPlugin(t *testing.T) { } func TestPluginGeneratesApi(t *testing.T) { - ctx := testJava(t, ` + ctx, _ := testJava(t, ` java_library { name: "foo", srcs: ["a.java"], diff --git a/java/proto.go b/java/proto.go index 37de1d283..0ec64997e 100644 --- a/java/proto.go +++ b/java/proto.go @@ -34,7 +34,7 @@ func genProto(ctx android.ModuleContext, protoFile android.Path, flags android.P // Proto generated java files have an unknown package name in the path, so package the entire output directory // into a srcjar. rule.Command(). - Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). + BuiltTool(ctx, "soong_zip"). Flag("-jar"). FlagWithOutput("-o ", srcJarFile). FlagWithArg("-C ", outDir.String()). diff --git a/java/sdk.go b/java/sdk.go index 7b79a49f2..d1e2ae4d1 100644 --- a/java/sdk.go +++ b/java/sdk.go @@ -296,7 +296,7 @@ func createSdkFrameworkAidl(ctx android.SingletonContext) { rule.Command(). Text("rm -f").Output(aidl) rule.Command(). - Tool(ctx.Config().HostToolPath(ctx, "sdkparcelables")). + BuiltTool(ctx, "sdkparcelables"). Input(jar). Output(aidl) diff --git a/java/sdk_library.go b/java/sdk_library.go index b4a3f296c..d38088d74 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -63,12 +63,6 @@ var ( javaSdkLibrariesLock sync.Mutex ) -// java_sdk_library is to make a Java library that implements optional platform APIs to apps. -// It is actually a wrapper of several modules: 1) stubs library that clients are linked against -// to, 2) droiddoc module that internally generates API stubs source files, 3) the real runtime -// shared library that implements the APIs, and 4) XML file for adding the runtime lib to the -// classpath at runtime if requested via <uses-library>. -// // TODO: these are big features that are currently missing // 1) disallowing linking to the runtime shared lib // 2) HTML generation @@ -155,16 +149,21 @@ var _ Dependency = (*SdkLibrary)(nil) var _ SdkLibraryDependency = (*SdkLibrary)(nil) func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { + useBuiltStubs := !ctx.Config().UnbundledBuildUsePrebuiltSdks() // Add dependencies to the stubs library - ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic)) + if useBuiltStubs { + ctx.AddVariationDependencies(nil, publicApiStubsTag, module.stubsName(apiScopePublic)) + } ctx.AddVariationDependencies(nil, publicApiFileTag, module.docsName(apiScopePublic)) sdkDep := decodeSdkDep(ctx, sdkContext(&module.Library)) if sdkDep.hasStandardLibs() { - ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem)) + if useBuiltStubs { + ctx.AddVariationDependencies(nil, systemApiStubsTag, module.stubsName(apiScopeSystem)) + ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest)) + } ctx.AddVariationDependencies(nil, systemApiFileTag, module.docsName(apiScopeSystem)) ctx.AddVariationDependencies(nil, testApiFileTag, module.docsName(apiScopeTest)) - ctx.AddVariationDependencies(nil, testApiStubsTag, module.stubsName(apiScopeTest)) } module.Library.deps(ctx) @@ -746,6 +745,11 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { module.Library.Module.deviceProperties.IsSDKLibrary = true } +// java_sdk_library is a special Java library that provides optional platform APIs to apps. +// In practice, it can be viewed as a combination of several modules: 1) stubs library that clients +// are linked against to, 2) droiddoc module that internally generates API stubs source files, +// 3) the real runtime shared library that implements the APIs, and 4) XML file for adding +// the runtime lib to the classpath at runtime if requested via <uses-library>. func SdkLibraryFactory() android.Module { module := &SdkLibrary{} module.InitSdkLibraryProperties() @@ -787,6 +791,7 @@ type sdkLibraryImport struct { var _ SdkLibraryDependency = (*sdkLibraryImport)(nil) +// java_sdk_library_import imports a prebuilt java_sdk_library. func sdkLibraryImportFactory() android.Module { module := &sdkLibraryImport{} diff --git a/java/sdk_test.go b/java/sdk_test.go index f82a4fba9..6be17eb88 100644 --- a/java/sdk_test.go +++ b/java/sdk_test.go @@ -282,7 +282,7 @@ func TestClasspath(t *testing.T) { if testcase.pdk { config.TestProductVariables.Pdk = proptools.BoolPtr(true) } - ctx := testContext(config, bp, nil) + ctx := testContext(bp, nil) run(t, ctx, config) checkClasspath(t, ctx) @@ -309,7 +309,7 @@ func TestClasspath(t *testing.T) { if testcase.pdk { config.TestProductVariables.Pdk = proptools.BoolPtr(true) } - ctx := testContext(config, bp, nil) + ctx := testContext(bp, nil) run(t, ctx, config) javac := ctx.ModuleForTests("foo", variant).Rule("javac") @@ -335,7 +335,7 @@ func TestClasspath(t *testing.T) { if testcase.pdk { config.TestProductVariables.Pdk = proptools.BoolPtr(true) } - ctx := testContext(config, bp, nil) + ctx := testContext(bp, nil) run(t, ctx, config) checkClasspath(t, ctx) diff --git a/java/support_libraries.go b/java/support_libraries.go index 5a72f41a9..af7c3c2a0 100644 --- a/java/support_libraries.go +++ b/java/support_libraries.go @@ -52,8 +52,6 @@ func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) { supportAars = append(supportAars, name) case *Library, *Import: supportJars = append(supportJars, name) - default: - ctx.ModuleErrorf(module, "unknown module type %t", module) } }) |