java_sdk_library does the apicheck by default
droiddoc now supports apicheck. java_sdk_library uses it to
automatically perform apichecks against the not-yet-release API and
the latest-released API.
A module type prebuilt_apis is added. It finds api txt files and creates
filegroup modules so that it can be referenced from java_sdk_library
across the module boundary.
Bug: 77575606
Test: m -j
Test: m -j checkapi
Test: m -j update-api
Change-Id: I0ba859972eac060296e1df2e71c4e047392d4877
diff --git a/java/sdk_library.go b/java/sdk_library.go
index ee6998c..ba121ab 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -67,10 +67,9 @@
// classpath at runtime if requested via <uses-library>.
//
// TODO: these are big features that are currently missing
-// 1) check for API consistency
-// 2) ensuring that apps have appropriate <uses-library> tag
-// 3) disallowing linking to the runtime shared lib
-// 4) HTML generation
+// 1) ensuring that apps have appropriate <uses-library> tag
+// 2) disallowing linking to the runtime shared lib
+// 3) HTML generation
func init() {
android.RegisterModuleType("java_sdk_library", sdkLibraryFactory)
@@ -260,21 +259,32 @@
return apiTagName
}
-// returns the path (relative to this module) to the API txt file. Files are located
-// ./<api_dir>/<api_level>.txt where <api_level> is either current, system-current, removed,
-// or system-removed.
-func (module *sdkLibrary) apiFilePath(apiLevel string, apiScope apiScope) string {
- apiDir := "api"
- apiFile := apiLevel
+func (module *sdkLibrary) latestApiFilegroupName(apiScope apiScope) string {
+ name := ":" + module.BaseModuleName() + ".api."
switch apiScope {
+ case apiScopePublic:
+ name = name + "public"
case apiScopeSystem:
- apiFile = "system-" + apiFile
+ name = name + "system"
case apiScopeTest:
- apiFile = "test-" + apiFile
+ name = name + "test"
}
- apiFile = apiFile + ".txt"
+ name = name + ".latest"
+ return name
+}
- return path.Join(apiDir, apiFile)
+func (module *sdkLibrary) latestRemovedApiFilegroupName(apiScope apiScope) string {
+ name := ":" + module.BaseModuleName() + "-removed.api."
+ switch apiScope {
+ case apiScopePublic:
+ name = name + "public"
+ case apiScopeSystem:
+ name = name + "system"
+ case apiScopeTest:
+ name = name + "test"
+ }
+ name = name + ".latest"
+ return name
}
// Creates a static java library that has API stubs
@@ -331,6 +341,10 @@
Api_tag_name *string
Api_filename *string
Removed_api_filename *string
+ Check_api struct {
+ Current ApiToCheck
+ Last_released ApiToCheck
+ }
}{}
props.Name = proptools.StringPtr(module.docsName(apiScope))
@@ -355,7 +369,6 @@
// List of APIs identified from the provided source files are created. They are later
// compared against to the not-yet-released (a.k.a current) list of APIs and to the
// last-released (a.k.a numbered) list of API.
- // TODO: If any incompatible change is detected, break the build
currentApiFileName := "current.txt"
removedApiFileName := "removed.txt"
switch apiScope {
@@ -368,12 +381,31 @@
}
currentApiFileName = path.Join("api", currentApiFileName)
removedApiFileName = path.Join("api", removedApiFileName)
+ // TODO(jiyong): remove these three props
props.Api_tag_name = proptools.StringPtr(module.apiTagName(apiScope))
- // Note: the exact names of these two are not important because they are always
- // referenced by the make variable $(INTERNAL_PLATFORM_<TAG_NAME>_API_FILE)
props.Api_filename = proptools.StringPtr(currentApiFileName)
props.Removed_api_filename = proptools.StringPtr(removedApiFileName)
+ // check against the not-yet-release API
+ props.Check_api.Current.Api_file = proptools.StringPtr(currentApiFileName)
+ props.Check_api.Current.Removed_api_file = proptools.StringPtr(removedApiFileName)
+ // any change is reported as error
+ props.Check_api.Current.Args = proptools.StringPtr("-error 2 -error 3 -error 4 -error 5 " +
+ "-error 6 -error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 " +
+ "-error 14 -error 15 -error 16 -error 17 -error 18 -error 19 -error 20 " +
+ "-error 21 -error 23 -error 24 -error 25 -error 26 -error 27")
+
+ // check against the latest released API
+ props.Check_api.Last_released.Api_file = proptools.StringPtr(
+ module.latestApiFilegroupName(apiScope))
+ props.Check_api.Last_released.Removed_api_file = proptools.StringPtr(
+ module.latestRemovedApiFilegroupName(apiScope))
+ // backward incompatible changes are reported as error
+ props.Check_api.Last_released.Args = proptools.StringPtr("-hide 2 -hide 3 -hide 4 -hide 5 " +
+ "-hide 6 -hide 24 -hide 25 -hide 26 -hide 27 " +
+ "-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 " +
+ "-error 15 -error 16 -error 17 -error 18")
+
// Include the part of the framework source. This is required for the case when
// API class is extending from the framework class. In that case, doclava needs
// to know whether the base class is hidden or not. Since that information is