summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
Diffstat (limited to 'java')
-rw-r--r--java/androidmk.go38
-rw-r--r--java/config/config.go1
-rw-r--r--java/droiddoc.go174
-rw-r--r--java/java_test.go1
-rw-r--r--java/proto.go4
-rw-r--r--java/sdk_library.go27
-rw-r--r--java/support_libraries.go66
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, " "))
+}