Revert "Remove create_stubs and checkapi from droiddoc"
This reverts commit 3a55c91f9de31fdb2a7bba2360ddba347c11112e.
Reason for revert: build failed. Guess this is the cause but needs to confirm. Creating a revert per instructions
Change-Id: I30f1c8cd63e5ab84dba5d21ed354a42695c24ec4
diff --git a/java/androidmk.go b/java/androidmk.go
index 9d5885f..2c02e5f 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -507,14 +507,53 @@
func (ddoc *Droiddoc) AndroidMkEntries() []android.AndroidMkEntries {
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(ddoc.Javadoc.docZip),
+ OutputFile: android.OptionalPathForPath(ddoc.stubsSrcJar),
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(entries *android.AndroidMkEntries) {
- if ddoc.Javadoc.docZip != nil {
+ if BoolDefault(ddoc.Javadoc.properties.Installable, true) && ddoc.Javadoc.docZip != nil {
entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", ddoc.Javadoc.docZip)
}
- entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !BoolDefault(ddoc.Javadoc.properties.Installable, true))
+ if ddoc.Javadoc.stubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", ddoc.Javadoc.stubsSrcJar)
+ }
+ },
+ },
+ ExtraFooters: []android.AndroidMkExtraFootersFunc{
+ func(w io.Writer, name, prefix, moduleDir string, entries *android.AndroidMkEntries) {
+ 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, "checkapi:",
+ 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())
+
+ fmt.Fprintln(w, ".PHONY: checkapi")
+ fmt.Fprintln(w, "checkapi:",
+ ddoc.checkLastReleasedApiTimestamp.String())
+
+ fmt.Fprintln(w, ".PHONY: droidcore")
+ fmt.Fprintln(w, "droidcore: checkapi")
+ }
},
},
}}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 5ccc306..4c5f66c 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -70,6 +70,10 @@
// or .aidl files.
Srcs []string `android:"path,arch_variant"`
+ // list of directories rooted at the Android.bp file that will
+ // be added to the search paths for finding source files when passing package names.
+ Local_sourcepaths []string
+
// list of source files that should not be used to build the Java module.
// This is most useful in the arch/multilib variants to remove non-common files
// filegroup or genrule can be included within this property.
@@ -171,6 +175,10 @@
// resources output directory under out/soong/.intermediates.
Resourcesoutdir *string
+ // if set to true, collect the values used by the Dev tools and
+ // write them in files packaged with the SDK. Defaults to false.
+ Write_sdk_values *bool
+
// index.html under current module will be copied to docs out dir, if not null.
Static_doc_index_redirect *string `android:"path"`
@@ -187,6 +195,22 @@
// the generated removed API filename by Doclava.
Removed_api_filename *string
+ // the generated removed Dex API filename by Doclava.
+ Removed_dex_api_filename *string
+
+ // if set to false, don't allow droiddoc to generate stubs source files. Defaults to false.
+ Create_stubs *bool
+
+ Check_api struct {
+ Last_released ApiToCheck
+
+ Current ApiToCheck
+
+ // do not perform API check against Last_released, in the case that both two specified API
+ // files by Last_released are modules which don't exist.
+ Ignore_missing_latest_api *bool `blueprint:"mutated"`
+ }
+
// if set to true, generate docs through Dokka instead of Doclava.
Dokka_enabled *bool
@@ -615,9 +639,10 @@
j.srcFiles = srcFiles.FilterOutByExt(".srcjar")
j.srcFiles = append(j.srcFiles, deps.srcs...)
- if len(j.srcFiles) > 0 {
- j.sourcepaths = android.PathsForModuleSrc(ctx, []string{"."})
+ if j.properties.Local_sourcepaths == nil && len(j.srcFiles) > 0 {
+ j.properties.Local_sourcepaths = append(j.properties.Local_sourcepaths, ".")
}
+ j.sourcepaths = android.PathsForModuleSrc(ctx, j.properties.Local_sourcepaths)
j.argFiles = android.PathsForModuleSrc(ctx, j.properties.Arg_files)
argFilesMap := map[string]string{}
@@ -723,7 +748,17 @@
type Droiddoc struct {
Javadoc
- properties DroiddocProperties
+ properties DroiddocProperties
+ apiFile android.WritablePath
+ privateApiFile android.WritablePath
+ removedApiFile android.WritablePath
+ removedDexApiFile android.WritablePath
+
+ checkCurrentApiTimestamp android.WritablePath
+ updateCurrentApiTimestamp android.WritablePath
+ checkLastReleasedApiTimestamp android.WritablePath
+
+ apiFilePath android.Path
}
// droiddoc converts .java source files to documentation using doclava or dokka.
@@ -748,18 +783,17 @@
return module
}
-func (d *Droiddoc) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
- case "", ".docs.zip":
- return android.Paths{d.Javadoc.docZip}, nil
- default:
- return nil, fmt.Errorf("unsupported module reference tag %q", tag)
- }
+func (d *Droiddoc) ApiFilePath() android.Path {
+ return d.apiFilePath
}
func (d *Droiddoc) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
+ if Bool(d.properties.Check_api.Ignore_missing_latest_api) {
+ ignoreMissingModules(ctx, &d.properties.Check_api.Last_released)
+ }
+
if String(d.properties.Custom_template) != "" {
ctx.AddDependency(ctx.Module(), droiddocTemplateTag, String(d.properties.Custom_template))
}
@@ -839,6 +873,41 @@
}
}
+func (d *Droiddoc) createStubs() bool {
+ return BoolDefault(d.properties.Create_stubs, false)
+}
+
+func (d *Droiddoc) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.WritablePath) {
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
+ apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
+ String(d.properties.Api_filename) != "" {
+
+ d.apiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_api.txt")
+ cmd.FlagWithOutput("-api ", d.apiFile)
+ d.apiFilePath = d.apiFile
+ }
+
+ if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
+ apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
+ String(d.properties.Removed_api_filename) != "" {
+ d.removedApiFile = android.PathForModuleOut(ctx, ctx.ModuleName()+"_removed.txt")
+ cmd.FlagWithOutput("-removedApi ", d.removedApiFile)
+ }
+
+ if String(d.properties.Removed_dex_api_filename) != "" {
+ d.removedDexApiFile = android.PathForModuleOut(ctx, String(d.properties.Removed_dex_api_filename))
+ cmd.FlagWithOutput("-removedDexApi ", d.removedDexApiFile)
+ }
+
+ if d.createStubs() {
+ cmd.FlagWithArg("-stubs ", stubsDir.String())
+ }
+
+ if Bool(d.properties.Write_sdk_values) {
+ cmd.FlagWithArg("-sdkvalues ", android.PathForModuleOut(ctx, "out").String())
+ }
+}
+
func (d *Droiddoc) postDoclavaCmds(ctx android.ModuleContext, rule *android.RuleBuilder) {
if String(d.properties.Static_doc_index_redirect) != "" {
staticDocIndexRedirect := android.PathForModuleSrc(ctx, String(d.properties.Static_doc_index_redirect))
@@ -941,15 +1010,22 @@
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")}
outDir := android.PathForModuleOut(ctx, "out")
srcJarDir := android.PathForModuleOut(ctx, "srcjars")
+ stubsDir := android.PathForModuleOut(ctx, "stubsDir")
rule := android.NewRuleBuilder()
+ 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
@@ -960,6 +1036,8 @@
deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths)
}
+ d.stubsFlags(ctx, cmd, stubsDir)
+
cmd.Flag(strings.Join(d.Javadoc.args, " ")).Implicits(d.Javadoc.argFiles)
if d.properties.Compat_config != nil {
@@ -989,11 +1067,120 @@
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(ctx, d.properties.Check_api.Current, "current") {
+ 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")
+
+ 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")
+
+ // 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(ctx, d.properties.Check_api.Last_released, "last_released") {
+ 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")
+
+ 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")
+ }
}
//
diff --git a/java/java_test.go b/java/java_test.go
index d75be18..0e93611 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1082,26 +1082,16 @@
srcs: ["bar-doc/IBar.aidl"],
path: "bar-doc",
}
- droidstubs {
- name: "bar-stubs",
- srcs: [
- "bar-doc/a.java",
- ],
- exclude_srcs: [
- "bar-doc/b.java"
- ],
- api_levels_annotations_dirs: [
- "droiddoc-templates-sdk",
- ],
- api_levels_annotations_enabled: true,
- }
droiddoc {
name: "bar-doc",
srcs: [
- ":bar-stubs",
+ "bar-doc/a.java",
"bar-doc/IFoo.aidl",
":bar-doc-aidl-srcs",
],
+ exclude_srcs: [
+ "bar-doc/b.java"
+ ],
custom_template: "droiddoc-templates-sdk",
hdf: [
"android.whichdoc offline",
@@ -1118,29 +1108,23 @@
"bar-doc/a.java": nil,
"bar-doc/b.java": nil,
})
- barStubs := ctx.ModuleForTests("bar-stubs", "android_common")
- barStubsOutputs, err := barStubs.Module().(*Droidstubs).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error %q retrieving \"bar-stubs\" output file", err)
- }
- if len(barStubsOutputs) != 1 {
- t.Errorf("Expected one output from \"bar-stubs\" got %s", barStubsOutputs)
+ barDocModule := ctx.ModuleForTests("bar-doc", "android_common")
+ barDoc := barDocModule.Rule("javadoc")
+ notExpected := " -stubs "
+ if strings.Contains(barDoc.RuleParams.Command, notExpected) {
+ t.Errorf("bar-doc command contains flag %q to create stubs, but should not", notExpected)
}
- barStubsOutput := barStubsOutputs[0]
- barDoc := ctx.ModuleForTests("bar-doc", "android_common")
- javaDoc := barDoc.Rule("javadoc")
- if g, w := javaDoc.Implicits.Strings(), barStubsOutput.String(); !inList(w, g) {
- t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
+ var javaSrcs []string
+ for _, i := range barDoc.Inputs {
+ javaSrcs = append(javaSrcs, i.Base())
+ }
+ if len(javaSrcs) != 1 || javaSrcs[0] != "a.java" {
+ t.Errorf("inputs of bar-doc must be []string{\"a.java\"}, but was %#v.", javaSrcs)
}
- expected := "-sourcepath " + buildDir + "/.intermediates/bar-doc/android_common/srcjars "
- if !strings.Contains(javaDoc.RuleParams.Command, expected) {
- t.Errorf("bar-doc command does not contain flag %q, but should\n%q", expected, javaDoc.RuleParams.Command)
- }
-
- aidl := barDoc.Rule("aidl")
- if g, w := javaDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) {
+ aidl := barDocModule.Rule("aidl")
+ if g, w := barDoc.Implicits.Strings(), aidl.Output.String(); !inList(w, g) {
t.Errorf("implicits of bar-doc must contain %q, but was %q.", w, g)
}
@@ -1160,26 +1144,16 @@
srcs: ["bar-doc/IBar.aidl"],
path: "bar-doc",
}
- droidstubs {
- name: "bar-stubs",
- srcs: [
- "bar-doc/a.java",
- ],
- exclude_srcs: [
- "bar-doc/b.java"
- ],
- api_levels_annotations_dirs: [
- "droiddoc-templates-sdk",
- ],
- api_levels_annotations_enabled: true,
- }
droiddoc {
name: "bar-doc",
srcs: [
- ":bar-stubs",
+ "bar-doc/a.java",
"bar-doc/IFoo.aidl",
":bar-doc-aidl-srcs",
],
+ exclude_srcs: [
+ "bar-doc/b.java"
+ ],
custom_template: "droiddoc-templates-sdk",
hdf: [
"android.whichdoc offline",