Apicheck Support in Soong

didn't remove the props: api_filename, removed_api_filename yet since
these two currently are used by java_sdk_library.

Bug: b/78034256
Test: m clean && m checkapi

Change-Id: Iebd014ef227487717b5b3819c80d630c34559983
This commit is contained in:
Nan Zhang
2018-05-04 18:49:16 -07:00
parent ea144bf779
commit 61819cef14
4 changed files with 200 additions and 14 deletions

View File

@@ -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"}