diff options
Diffstat (limited to 'java/prebuilt_apis.go')
-rw-r--r-- | java/prebuilt_apis.go | 148 |
1 files changed, 103 insertions, 45 deletions
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go index bcc6cc0cf..c33e6c229 100644 --- a/java/prebuilt_apis.go +++ b/java/prebuilt_apis.go @@ -15,12 +15,14 @@ package java import ( - "sort" + "fmt" + "strconv" "strings" "github.com/google/blueprint/proptools" "android/soong/android" + "android/soong/genrule" ) func init() { @@ -35,6 +37,12 @@ type prebuiltApisProperties struct { // list of api version directories Api_dirs []string + // The next API directory can optionally point to a directory where + // files incompatibility-tracking files are stored for the current + // "in progress" API. Each module present in one of the api_dirs will have + // a <module>-incompatibilities.api.<scope>.latest module created. + Next_api_dir *string + // The sdk_version of java_import modules generated based on jar files. // Defaults to "current" Imports_sdk_version *string @@ -98,28 +106,50 @@ func createImport(mctx android.LoadHookContext, module, scope, apiver, path, sdk mctx.CreateModule(ImportFactory, &props) } -func createFilegroup(mctx android.LoadHookContext, module string, scope string, apiver string, path string) { - fgName := module + ".api." + scope + "." + apiver - filegroupProps := struct { +func createApiModule(mctx android.LoadHookContext, name string, path string) { + genruleProps := struct { Name *string Srcs []string + Out []string + Cmd *string + }{} + genruleProps.Name = proptools.StringPtr(name) + genruleProps.Srcs = []string{path} + genruleProps.Out = []string{name} + genruleProps.Cmd = proptools.StringPtr("cp $(in) $(out)") + mctx.CreateModule(genrule.GenRuleFactory, &genruleProps) +} + +func createEmptyFile(mctx android.LoadHookContext, name string) { + props := struct { + Name *string + Cmd *string + Out []string }{} - filegroupProps.Name = proptools.StringPtr(fgName) - filegroupProps.Srcs = []string{path} - mctx.CreateModule(android.FileGroupFactory, &filegroupProps) + props.Name = proptools.StringPtr(name) + props.Out = []string{name} + props.Cmd = proptools.StringPtr("touch $(genDir)/" + name) + mctx.CreateModule(genrule.GenRuleFactory, &props) } func getPrebuiltFiles(mctx android.LoadHookContext, p *prebuiltApis, name string) []string { - mydir := mctx.ModuleDir() + "/" var files []string for _, apiver := range p.properties.Api_dirs { - for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} { - vfiles, err := mctx.GlobWithDeps(mydir+apiver+"/"+scope+"/"+name, nil) - if err != nil { - mctx.ModuleErrorf("failed to glob %s files under %q: %s", name, mydir+apiver+"/"+scope, err) - } - files = append(files, vfiles...) + files = append(files, getPrebuiltFilesInSubdir(mctx, apiver, name)...) + } + return files +} + +func getPrebuiltFilesInSubdir(mctx android.LoadHookContext, subdir string, name string) []string { + var files []string + dir := mctx.ModuleDir() + "/" + subdir + for _, scope := range []string{"public", "system", "test", "core", "module-lib", "system-server"} { + glob := fmt.Sprintf("%s/%s/%s", dir, scope, name) + vfiles, err := mctx.GlobWithDeps(glob, nil) + if err != nil { + mctx.ModuleErrorf("failed to glob %s files under %q: %s", name, dir+"/"+scope, err) } + files = append(files, vfiles...) } return files } @@ -148,7 +178,7 @@ func createSystemModules(mctx android.LoadHookContext, apiver string) { props.Name = proptools.StringPtr(prebuiltApiModuleName(mctx, "system_modules", "public", apiver)) props.Libs = append(props.Libs, prebuiltApiModuleName(mctx, "core-for-system-modules", "public", apiver)) - mctx.CreateModule(SystemModulesFactory, &props) + mctx.CreateModule(systemModulesImportFactory, &props) } func prebuiltSdkSystemModules(mctx android.LoadHookContext, p *prebuiltApis) { @@ -173,41 +203,69 @@ func prebuiltApiFiles(mctx android.LoadHookContext, p *prebuiltApis) { // construct a map to find out the latest api file path // for each (<module>, <scope>) pair. type latestApiInfo struct { - module string - scope string - apiver string - path string + module string + scope string + version int + path string } - m := make(map[string]latestApiInfo) + // Create modules for all (<module>, <scope, <version>) triplets, + // and a "latest" module variant for each (<module>, <scope>) pair + apiModuleName := func(module, scope, version string) string { + return module + ".api." + scope + "." + version + } + m := make(map[string]latestApiInfo) for _, f := range files { - // create a filegroup for each api txt file localPath := strings.TrimPrefix(f, mydir) module, apiver, scope := parseApiFilePath(mctx, localPath) - createFilegroup(mctx, module, scope, apiver, localPath) - - // find the latest apiver - key := module + "." + scope - info, ok := m[key] - if !ok { - m[key] = latestApiInfo{module, scope, apiver, localPath} - } else if len(apiver) > len(info.apiver) || (len(apiver) == len(info.apiver) && - strings.Compare(apiver, info.apiver) > 0) { - info.apiver = apiver - info.path = localPath - m[key] = info + createApiModule(mctx, apiModuleName(module, scope, apiver), localPath) + + version, err := strconv.Atoi(apiver) + if err != nil { + mctx.ModuleErrorf("Found finalized API files in non-numeric dir %v", apiver) + return + } + + // Track latest version of each module/scope, except for incompatibilities + if !strings.HasSuffix(module, "incompatibilities") { + key := module + "." + scope + info, ok := m[key] + if !ok { + m[key] = latestApiInfo{module, scope, version, localPath} + } else if version > info.version { + info.version = version + info.path = localPath + m[key] = info + } } } - // create filegroups for the latest version of (<module>, <scope>) pairs - // sort the keys in order to make build.ninja stable - keys := make([]string, 0, len(m)) - for k := range m { - keys = append(keys, k) - } - sort.Strings(keys) - for _, k := range keys { + + // Sort the keys in order to make build.ninja stable + for _, k := range android.SortedStringKeys(m) { info := m[k] - createFilegroup(mctx, info.module, info.scope, "latest", info.path) + name := apiModuleName(info.module, info.scope, "latest") + createApiModule(mctx, name, info.path) + } + + // Create incompatibilities tracking files for all modules, if we have a "next" api. + incompatibilities := make(map[string]bool) + if nextApiDir := String(p.properties.Next_api_dir); nextApiDir != "" { + files := getPrebuiltFilesInSubdir(mctx, nextApiDir, "api/*incompatibilities.txt") + for _, f := range files { + localPath := strings.TrimPrefix(f, mydir) + filename, _, scope := parseApiFilePath(mctx, localPath) + referencedModule := strings.TrimSuffix(filename, "-incompatibilities") + + createApiModule(mctx, apiModuleName(referencedModule+"-incompatibilities", scope, "latest"), localPath) + + incompatibilities[referencedModule+"."+scope] = true + } + } + // Create empty incompatibilities files for remaining modules + for _, k := range android.SortedStringKeys(m) { + if _, ok := incompatibilities[k]; !ok { + createEmptyFile(mctx, apiModuleName(m[k].module+"-incompatibilities", m[k].scope, "latest")) + } } } @@ -219,10 +277,10 @@ func createPrebuiltApiModules(mctx android.LoadHookContext) { } } -// prebuilt_apis is a meta-module that generates filegroup modules for all -// API txt files found under the directory where the Android.bp is located. +// prebuilt_apis is a meta-module that generates modules for all API txt files +// found under the directory where the Android.bp is located. // Specifically, an API file located at ./<ver>/<scope>/api/<module>.txt -// generates a filegroup module named <module>-api.<scope>.<ver>. +// generates a module named <module>-api.<scope>.<ver>. // // It also creates <module>-api.<scope>.latest for the latest <ver>. // |