diff options
Diffstat (limited to 'java')
| -rw-r--r-- | java/androidmk.go | 38 | ||||
| -rw-r--r-- | java/config/config.go | 1 | ||||
| -rw-r--r-- | java/droiddoc.go | 174 | ||||
| -rw-r--r-- | java/java_test.go | 1 | ||||
| -rw-r--r-- | java/proto.go | 4 | ||||
| -rw-r--r-- | java/sdk_library.go | 27 | ||||
| -rw-r--r-- | java/support_libraries.go | 66 |
7 files changed, 290 insertions, 21 deletions
diff --git a/java/androidmk.go b/java/androidmk.go index b168f2c7c..5a4a082b4 100644 --- a/java/androidmk.go +++ b/java/androidmk.go @@ -286,26 +286,52 @@ func (ddoc *Droiddoc) AndroidMk() android.AndroidMkData { if ddoc.Javadoc.stubsSrcJar != nil { fmt.Fprintln(w, "LOCAL_DROIDDOC_STUBS_SRCJAR := ", ddoc.Javadoc.stubsSrcJar.String()) } + if ddoc.checkCurrentApiTimestamp != nil { + fmt.Fprintln(w, ".PHONY:", ddoc.Name()+"-check-current-api") + fmt.Fprintln(w, ddoc.Name()+"-check-current-api:", + ddoc.checkCurrentApiTimestamp.String()) + + fmt.Fprintln(w, ".PHONY: checkapi") + fmt.Fprintln(w, "check-api:", + ddoc.checkCurrentApiTimestamp.String()) + + fmt.Fprintln(w, ".PHONY: droidcore") + fmt.Fprintln(w, "droidcore: checkapi") + } + if ddoc.updateCurrentApiTimestamp != nil { + fmt.Fprintln(w, ".PHONY:", ddoc.Name(), "-update-current-api") + fmt.Fprintln(w, ddoc.Name()+"-update-current-api:", + ddoc.updateCurrentApiTimestamp.String()) + + fmt.Fprintln(w, ".PHONY: update-api") + fmt.Fprintln(w, "update-api:", + ddoc.updateCurrentApiTimestamp.String()) + } + if ddoc.checkLastReleasedApiTimestamp != nil { + fmt.Fprintln(w, ".PHONY:", ddoc.Name()+"-check-last-released-api") + fmt.Fprintln(w, ddoc.Name()+"-check-last-released-api:", + ddoc.checkLastReleasedApiTimestamp.String()) + } apiFilePrefix := "INTERNAL_PLATFORM_" if String(ddoc.properties.Api_tag_name) != "" { apiFilePrefix += String(ddoc.properties.Api_tag_name) + "_" } - if String(ddoc.properties.Api_filename) != "" { + if ddoc.apiFile != nil { fmt.Fprintln(w, apiFilePrefix+"API_FILE := ", ddoc.apiFile.String()) } - if String(ddoc.properties.Private_api_filename) != "" { + if ddoc.privateApiFile != nil { fmt.Fprintln(w, apiFilePrefix+"PRIVATE_API_FILE := ", ddoc.privateApiFile.String()) } - if String(ddoc.properties.Private_dex_api_filename) != "" { + if ddoc.privateDexApiFile != nil { fmt.Fprintln(w, apiFilePrefix+"PRIVATE_DEX_API_FILE := ", ddoc.privateDexApiFile.String()) } - if String(ddoc.properties.Removed_api_filename) != "" { + if ddoc.removedApiFile != nil { fmt.Fprintln(w, apiFilePrefix+"REMOVED_API_FILE := ", ddoc.removedApiFile.String()) } - if String(ddoc.properties.Removed_dex_api_filename) != "" { + if ddoc.removedDexApiFile != nil { fmt.Fprintln(w, apiFilePrefix+"REMOVED_DEX_API_FILE := ", ddoc.removedDexApiFile.String()) } - if String(ddoc.properties.Exact_api_filename) != "" { + if ddoc.exactApiFile != nil { fmt.Fprintln(w, apiFilePrefix+"EXACT_API_FILE := ", ddoc.exactApiFile.String()) } }, diff --git a/java/config/config.go b/java/config/config.go index 6633f792b..d44315c5c 100644 --- a/java/config/config.go +++ b/java/config/config.go @@ -90,6 +90,7 @@ func init() { pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips") pctx.HostBinToolVariable("Zip2ZipCmd", "zip2zip") pctx.HostBinToolVariable("ZipSyncCmd", "zipsync") + pctx.HostBinToolVariable("ApiCheckCmd", "apicheck") pctx.VariableFunc("DxCmd", func(ctx android.PackageVarContext) string { config := ctx.Config() if config.IsEnvFalse("USE_D8") { diff --git a/java/droiddoc.go b/java/droiddoc.go index 07042a115..202f22bc8 100644 --- a/java/droiddoc.go +++ b/java/droiddoc.go @@ -45,6 +45,24 @@ var ( }, "outDir", "srcJarDir", "stubsDir", "srcJars", "opts", "bootclasspathArgs", "classpathArgs", "sourcepath", "docZip") + + apiCheck = pctx.AndroidStaticRule("apiCheck", + blueprint.RuleParams{ + Command: `( ${config.ApiCheckCmd} -JXmx1024m -J"classpath $classpath" $opts ` + + `$apiFile $apiFileToCheck $removedApiFile $removedApiFileToCheck ` + + `&& touch $out ) || (echo $msg ; exit 38)`, + CommandDeps: []string{ + "${config.ApiCheckCmd}", + }, + }, + "classpath", "opts", "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck", "msg") + + updateApi = pctx.AndroidStaticRule("updateApi", + blueprint.RuleParams{ + Command: `( ( cp -f $apiFileToCheck $apiFile && cp -f $removedApiFileToCheck $removedApiFile ) ` + + `&& touch $out ) || (echo failed to update public API ; exit 38)`, + }, + "apiFile", "apiFileToCheck", "removedApiFile", "removedApiFileToCheck") ) func init() { @@ -94,6 +112,14 @@ type JavadocProperties struct { Sdk_version *string `android:"arch_variant"` } +type ApiToCheck struct { + Api_file *string + + Removed_api_file *string + + Args *string +} + type DroiddocProperties struct { // directory relative to top of the source tree that contains doc templates files. Custom_template *string @@ -157,6 +183,12 @@ type DroiddocProperties struct { // if set to false, don't allow droiddoc to generate stubs source files. Defaults to true. Create_stubs *bool + + Check_api struct { + Last_released ApiToCheck + + Current ApiToCheck + } } type Javadoc struct { @@ -189,6 +221,10 @@ type Droiddoc struct { removedApiFile android.WritablePath removedDexApiFile android.WritablePath exactApiFile android.WritablePath + + checkCurrentApiTimestamp android.WritablePath + updateCurrentApiTimestamp android.WritablePath + checkLastReleasedApiTimestamp android.WritablePath } func InitDroiddocModule(module android.DefaultableModule, hod android.HostOrDeviceSupported) { @@ -420,6 +456,32 @@ func (j *Javadoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { }) } +func (d *Droiddoc) checkCurrentApi() bool { + if String(d.properties.Check_api.Current.Api_file) != "" && + String(d.properties.Check_api.Current.Removed_api_file) != "" { + return true + } else if String(d.properties.Check_api.Current.Api_file) != "" { + panic("check_api.current.removed_api_file: has to be non empty!") + } else if String(d.properties.Check_api.Current.Removed_api_file) != "" { + panic("check_api.current.api_file: has to be non empty!") + } + + return false +} + +func (d *Droiddoc) checkLastReleasedApi() bool { + if String(d.properties.Check_api.Last_released.Api_file) != "" && + String(d.properties.Check_api.Last_released.Removed_api_file) != "" { + return true + } else if String(d.properties.Check_api.Last_released.Api_file) != "" { + panic("check_api.last_released.removed_api_file: has to be non empty!") + } else if String(d.properties.Check_api.Last_released.Removed_api_file) != "" { + panic("check_api.last_released.api_file: has to be non empty!") + } + + return false +} + func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) { d.Javadoc.addDeps(ctx) @@ -435,6 +497,16 @@ func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) { // knowntags may contain filegroup or genrule. android.ExtractSourcesDeps(ctx, d.properties.Knowntags) + + if d.checkCurrentApi() { + android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Api_file) + android.ExtractSourceDeps(ctx, d.properties.Check_api.Current.Removed_api_file) + } + + if d.checkLastReleasedApi() { + android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Api_file) + android.ExtractSourceDeps(ctx, d.properties.Check_api.Last_released.Removed_api_file) + } } func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -547,12 +619,19 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { } var implicitOutputs android.WritablePaths - if String(d.properties.Api_filename) != "" { - d.apiFile = android.PathForModuleOut(ctx, String(d.properties.Api_filename)) + + if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Api_filename) != "" { + d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt") args = args + " -api " + d.apiFile.String() implicitOutputs = append(implicitOutputs, d.apiFile) } + if d.checkCurrentApi() || d.checkLastReleasedApi() || String(d.properties.Removed_api_filename) != "" { + d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt") + args = args + " -removedApi " + d.removedApiFile.String() + implicitOutputs = append(implicitOutputs, d.removedApiFile) + } + if String(d.properties.Private_api_filename) != "" { d.privateApiFile = android.PathForModuleOut(ctx, String(d.properties.Private_api_filename)) args = args + " -privateApi " + d.privateApiFile.String() @@ -565,12 +644,6 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { implicitOutputs = append(implicitOutputs, d.privateDexApiFile) } - if String(d.properties.Removed_api_filename) != "" { - d.removedApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_api_filename)) - args = args + " -removedApi " + d.removedApiFile.String() - implicitOutputs = append(implicitOutputs, d.removedApiFile) - } - if String(d.properties.Removed_dex_api_filename) != "" { d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename)) args = args + " -removedDexApi " + d.removedDexApiFile.String() @@ -624,6 +697,91 @@ func (d *Droiddoc) GenerateAndroidBuildActions(ctx android.ModuleContext) { "docZip": d.Javadoc.docZip.String(), }, }) + + java8Home := ctx.Config().Getenv("ANDROID_JAVA8_HOME") + + checkApiClasspath := classpath{jsilver, doclava, android.PathForSource(ctx, java8Home, "lib/tools.jar")} + + if d.checkCurrentApi() && !ctx.Config().IsPdkBuild() { + d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "check_current_api.timestamp") + + 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") + + ctx.Build(pctx, android.BuildParams{ + Rule: apiCheck, + Description: "Current API check", + Output: d.checkCurrentApiTimestamp, + Inputs: nil, + Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile}, + checkApiClasspath...), + Args: map[string]string{ + "classpath": checkApiClasspath.FormJavaClassPath(""), + "opts": String(d.properties.Check_api.Current.Args), + "apiFile": apiFile.String(), + "apiFileToCheck": d.apiFile.String(), + "removedApiFile": removedApiFile.String(), + "removedApiFileToCheck": d.removedApiFile.String(), + "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:`+ + ` make %s-update-current-api\n\n`+ + ` To submit the revised current.txt to the main Android repository,`+ + ` you will need approval.\n`+ + `******************************\n`, ctx.ModuleName()), + }, + }) + + d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "update_current_api.timestamp") + + ctx.Build(pctx, android.BuildParams{ + Rule: updateApi, + Description: "update current API", + Output: d.updateCurrentApiTimestamp, + Implicits: append(android.Paths{}, apiFile, removedApiFile, d.apiFile, d.removedApiFile), + Args: map[string]string{ + "apiFile": apiFile.String(), + "apiFileToCheck": d.apiFile.String(), + "removedApiFile": removedApiFile.String(), + "removedApiFileToCheck": d.removedApiFile.String(), + }, + }) + } + + if d.checkLastReleasedApi() && !ctx.Config().IsPdkBuild() { + d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "check_last_released_api.timestamp") + + 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") + + ctx.Build(pctx, android.BuildParams{ + Rule: apiCheck, + Description: "Last Released API check", + Output: d.checkLastReleasedApiTimestamp, + Inputs: nil, + Implicits: append(android.Paths{apiFile, removedApiFile, d.apiFile, d.removedApiFile}, + checkApiClasspath...), + Args: map[string]string{ + "classpath": checkApiClasspath.FormJavaClassPath(""), + "opts": String(d.properties.Check_api.Last_released.Args), + "apiFile": apiFile.String(), + "apiFileToCheck": d.apiFile.String(), + "removedApiFile": removedApiFile.String(), + "removedApiFileToCheck": d.removedApiFile.String(), + "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`, + }, + }) + } } var droiddocTemplateTag = dependencyTag{name: "droiddoc-template"} diff --git a/java/java_test.go b/java/java_test.go index ea524962f..4a0229eb0 100644 --- a/java/java_test.go +++ b/java/java_test.go @@ -175,6 +175,7 @@ func testContext(config android.Config, bp string, "jdk8/jre/lib/jce.jar": nil, "jdk8/jre/lib/rt.jar": nil, + "jdk8/lib/tools.jar": nil, "bar-doc/a.java": nil, "bar-doc/b.java": nil, diff --git a/java/proto.go b/java/proto.go index cfd733ab7..3ec2e8a6b 100644 --- a/java/proto.go +++ b/java/proto.go @@ -30,12 +30,14 @@ var ( proto = pctx.AndroidStaticRule("protoc", blueprint.RuleParams{ Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` + - `$protocCmd $protoOut=$protoOutParams:$out.tmp -I $protoBase $protoFlags $in && ` + + `$protocCmd $protoOut=$protoOutParams:$out.tmp --dependency_out=$out.d -I $protoBase $protoFlags $in && ` + `${config.SoongZipCmd} -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`, CommandDeps: []string{ "$protocCmd", "${config.SoongZipCmd}", }, + Depfile: "${out}.d", + Deps: blueprint.DepsGCC, }, "protoBase", "protoFlags", "protoOut", "protoOutParams") ) diff --git a/java/sdk_library.go b/java/sdk_library.go index 703401cf1..ee6998c39 100644 --- a/java/sdk_library.go +++ b/java/sdk_library.go @@ -68,10 +68,9 @@ var ( // // TODO: these are big features that are currently missing // 1) check for API consistency -// 2) install stubs libs as the dist artifacts -// 3) ensuring that apps have appropriate <uses-library> tag -// 4) disallowing linking to the runtime shared lib -// 5) HTML generation +// 2) ensuring that apps have appropriate <uses-library> tag +// 3) disallowing linking to the runtime shared lib +// 4) HTML generation func init() { android.RegisterModuleType("java_sdk_library", sdkLibraryFactory) @@ -155,15 +154,31 @@ func (module *sdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) } func (module *sdkLibrary) AndroidMk() android.AndroidMkData { - // Create a phony module that installs the impl library, for the case when this lib is - // in PRODUCT_PACKAGES. return android.AndroidMkData{ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { + // Create a phony module that installs the impl library, for the case when this lib is + // in PRODUCT_PACKAGES. fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)") fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir) fmt.Fprintln(w, "LOCAL_MODULE :=", name) fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES := "+module.implName()) fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)") + // Create dist rules to install the stubs libs to the dist dir + if len(module.publicApiStubsPath) == 1 { + fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+ + module.publicApiStubsPath.Strings()[0]+ + ":"+path.Join("apistubs", "public", module.BaseModuleName()+".jar")+")") + } + if len(module.systemApiStubsPath) == 1 { + fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+ + module.systemApiStubsPath.Strings()[0]+ + ":"+path.Join("apistubs", "system", module.BaseModuleName()+".jar")+")") + } + if len(module.testApiStubsPath) == 1 { + fmt.Fprintln(w, "$(call dist-for-goals,sdk win_sdk,"+ + module.testApiStubsPath.Strings()[0]+ + ":"+path.Join("apistubs", "test", module.BaseModuleName()+".jar")+")") + } }, } } diff --git a/java/support_libraries.go b/java/support_libraries.go new file mode 100644 index 000000000..320afae19 --- /dev/null +++ b/java/support_libraries.go @@ -0,0 +1,66 @@ +// Copyright 2018 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 ( + "sort" + "strings" + + "android/soong/android" +) + +func init() { + android.RegisterMakeVarsProvider(pctx, supportLibrariesMakeVarsProvider) +} + +func supportLibrariesMakeVarsProvider(ctx android.MakeVarsContext) { + var supportAars, supportJars []string + + sctx := ctx.SingletonContext() + sctx.VisitAllModules(func(module android.Module) { + dir := sctx.ModuleDir(module) + switch { + case strings.HasPrefix(dir, "prebuilts/sdk/current/extras"), + dir == "prebuilts/sdk/current/androidx", + dir == "prebuilts/sdk/current/car", + dir == "prebuilts/sdk/current/optional", + dir == "prebuilts/sdk/current/support": + // Support library + default: + // Not a support library + return + } + + name := sctx.ModuleName(module) + if strings.HasSuffix(name, "-nodeps") { + return + } + + switch module.(type) { + case *AndroidLibrary, *AARImport: + supportAars = append(supportAars, name) + case *Library, *Import: + supportJars = append(supportJars, name) + default: + sctx.ModuleErrorf(module, "unknown module type %t", module) + } + }) + + sort.Strings(supportAars) + sort.Strings(supportJars) + + ctx.Strict("SUPPORT_LIBRARIES_AARS", strings.Join(supportAars, " ")) + ctx.Strict("SUPPORT_LIBRARIES_JARS", strings.Join(supportJars, " ")) +} |