namespace.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473
  1. // Copyright 2017 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package android
  15. import (
  16. "errors"
  17. "fmt"
  18. "path/filepath"
  19. "sort"
  20. "strconv"
  21. "strings"
  22. "sync"
  23. "github.com/google/blueprint"
  24. )
  25. func init() {
  26. registerNamespaceBuildComponents(InitRegistrationContext)
  27. }
  28. func registerNamespaceBuildComponents(ctx RegistrationContext) {
  29. ctx.RegisterModuleType("soong_namespace", NamespaceFactory)
  30. }
  31. // threadsafe sorted list
  32. type sortedNamespaces struct {
  33. lock sync.Mutex
  34. items []*Namespace
  35. sorted bool
  36. }
  37. func (s *sortedNamespaces) add(namespace *Namespace) {
  38. s.lock.Lock()
  39. defer s.lock.Unlock()
  40. if s.sorted {
  41. panic("It is not supported to call sortedNamespaces.add() after sortedNamespaces.sortedItems()")
  42. }
  43. s.items = append(s.items, namespace)
  44. }
  45. func (s *sortedNamespaces) sortedItems() []*Namespace {
  46. s.lock.Lock()
  47. defer s.lock.Unlock()
  48. if !s.sorted {
  49. less := func(i int, j int) bool {
  50. return s.items[i].Path < s.items[j].Path
  51. }
  52. sort.Slice(s.items, less)
  53. s.sorted = true
  54. }
  55. return s.items
  56. }
  57. func (s *sortedNamespaces) index(namespace *Namespace) int {
  58. for i, candidate := range s.sortedItems() {
  59. if namespace == candidate {
  60. return i
  61. }
  62. }
  63. return -1
  64. }
  65. // A NameResolver implements blueprint.NameInterface, and implements the logic to
  66. // find a module from namespaces based on a query string.
  67. // A query string can be a module name or can be "//namespace_path:module_path"
  68. type NameResolver struct {
  69. rootNamespace *Namespace
  70. // id counter for atomic.AddInt32
  71. nextNamespaceId int32
  72. // All namespaces, without duplicates.
  73. sortedNamespaces sortedNamespaces
  74. // Map from dir to namespace. Will have duplicates if two dirs are part of the same namespace.
  75. namespacesByDir sync.Map // if generics were supported, this would be sync.Map[string]*Namespace
  76. // func telling whether to export a namespace to Kati
  77. namespaceExportFilter func(*Namespace) bool
  78. }
  79. // NameResolverConfig provides the subset of the Config interface needed by the
  80. // NewNameResolver function.
  81. type NameResolverConfig interface {
  82. // ExportedNamespaces is the list of namespaces that Soong must export to
  83. // make.
  84. ExportedNamespaces() []string
  85. }
  86. func NewNameResolver(config NameResolverConfig) *NameResolver {
  87. namespacePathsToExport := make(map[string]bool)
  88. for _, namespaceName := range config.ExportedNamespaces() {
  89. namespacePathsToExport[namespaceName] = true
  90. }
  91. namespacePathsToExport["."] = true // always export the root namespace
  92. namespaceExportFilter := func(namespace *Namespace) bool {
  93. return namespacePathsToExport[namespace.Path]
  94. }
  95. r := &NameResolver{
  96. namespacesByDir: sync.Map{},
  97. namespaceExportFilter: namespaceExportFilter,
  98. }
  99. r.rootNamespace = r.newNamespace(".")
  100. r.rootNamespace.visibleNamespaces = []*Namespace{r.rootNamespace}
  101. r.addNamespace(r.rootNamespace)
  102. return r
  103. }
  104. func (r *NameResolver) newNamespace(path string) *Namespace {
  105. namespace := NewNamespace(path)
  106. namespace.exportToKati = r.namespaceExportFilter(namespace)
  107. return namespace
  108. }
  109. func (r *NameResolver) addNewNamespaceForModule(module *NamespaceModule, path string) error {
  110. fileName := filepath.Base(path)
  111. if fileName != "Android.bp" {
  112. return errors.New("A namespace may only be declared in a file named Android.bp")
  113. }
  114. dir := filepath.Dir(path)
  115. namespace := r.newNamespace(dir)
  116. module.namespace = namespace
  117. module.resolver = r
  118. namespace.importedNamespaceNames = module.properties.Imports
  119. return r.addNamespace(namespace)
  120. }
  121. func (r *NameResolver) addNamespace(namespace *Namespace) (err error) {
  122. existingNamespace, exists := r.namespaceAt(namespace.Path)
  123. if exists {
  124. if existingNamespace.Path == namespace.Path {
  125. return fmt.Errorf("namespace %v already exists", namespace.Path)
  126. } else {
  127. // It would probably confuse readers if namespaces were declared anywhere but
  128. // the top of the file, so we forbid declaring namespaces after anything else.
  129. return fmt.Errorf("a namespace must be the first module in the file")
  130. }
  131. }
  132. r.sortedNamespaces.add(namespace)
  133. r.namespacesByDir.Store(namespace.Path, namespace)
  134. return nil
  135. }
  136. // non-recursive check for namespace
  137. func (r *NameResolver) namespaceAt(path string) (namespace *Namespace, found bool) {
  138. mapVal, found := r.namespacesByDir.Load(path)
  139. if !found {
  140. return nil, false
  141. }
  142. return mapVal.(*Namespace), true
  143. }
  144. // recursive search upward for a namespace
  145. func (r *NameResolver) findNamespace(path string) (namespace *Namespace) {
  146. namespace, found := r.namespaceAt(path)
  147. if found {
  148. return namespace
  149. }
  150. parentDir := filepath.Dir(path)
  151. if parentDir == path {
  152. return nil
  153. }
  154. namespace = r.findNamespace(parentDir)
  155. r.namespacesByDir.Store(path, namespace)
  156. return namespace
  157. }
  158. // A NamespacelessModule can never be looked up by name. It must still implement Name(), and the name
  159. // still has to be unique.
  160. type NamespacelessModule interface {
  161. Namespaceless()
  162. }
  163. func (r *NameResolver) NewModule(ctx blueprint.NamespaceContext, moduleGroup blueprint.ModuleGroup, module blueprint.Module) (namespace blueprint.Namespace, errs []error) {
  164. // if this module is a namespace, then save it to our list of namespaces
  165. newNamespace, ok := module.(*NamespaceModule)
  166. if ok {
  167. err := r.addNewNamespaceForModule(newNamespace, ctx.ModulePath())
  168. if err != nil {
  169. return nil, []error{err}
  170. }
  171. return nil, nil
  172. }
  173. if _, ok := module.(NamespacelessModule); ok {
  174. return nil, nil
  175. }
  176. // if this module is not a namespace, then save it into the appropriate namespace
  177. ns := r.findNamespaceFromCtx(ctx)
  178. _, errs = ns.moduleContainer.NewModule(ctx, moduleGroup, module)
  179. if len(errs) > 0 {
  180. return nil, errs
  181. }
  182. amod, ok := module.(Module)
  183. if ok {
  184. // inform the module whether its namespace is one that we want to export to Make
  185. amod.base().commonProperties.NamespaceExportedToMake = ns.exportToKati
  186. amod.base().commonProperties.DebugName = module.Name()
  187. }
  188. return ns, nil
  189. }
  190. func (r *NameResolver) NewSkippedModule(ctx blueprint.NamespaceContext, name string, skipInfo blueprint.SkippedModuleInfo) {
  191. r.rootNamespace.moduleContainer.NewSkippedModule(ctx, name, skipInfo)
  192. }
  193. func (r *NameResolver) AllModules() []blueprint.ModuleGroup {
  194. childLists := [][]blueprint.ModuleGroup{}
  195. totalCount := 0
  196. for _, namespace := range r.sortedNamespaces.sortedItems() {
  197. newModules := namespace.moduleContainer.AllModules()
  198. totalCount += len(newModules)
  199. childLists = append(childLists, newModules)
  200. }
  201. allModules := make([]blueprint.ModuleGroup, 0, totalCount)
  202. for _, childList := range childLists {
  203. allModules = append(allModules, childList...)
  204. }
  205. return allModules
  206. }
  207. func (r *NameResolver) SkippedModuleFromName(moduleName string, namespace blueprint.Namespace) (skipInfos []blueprint.SkippedModuleInfo, skipped bool) {
  208. return r.rootNamespace.moduleContainer.SkippedModuleFromName(moduleName, namespace)
  209. }
  210. // parses a fully-qualified path (like "//namespace_path:module_name") into a namespace name and a
  211. // module name
  212. func (r *NameResolver) parseFullyQualifiedName(name string) (namespaceName string, moduleName string, ok bool) {
  213. if !strings.HasPrefix(name, "//") {
  214. return "", "", false
  215. }
  216. name = strings.TrimPrefix(name, "//")
  217. components := strings.Split(name, ":")
  218. if len(components) != 2 {
  219. return "", "", false
  220. }
  221. return components[0], components[1], true
  222. }
  223. func (r *NameResolver) getNamespacesToSearchForModule(sourceNamespace blueprint.Namespace) (searchOrder []*Namespace) {
  224. ns, ok := sourceNamespace.(*Namespace)
  225. if !ok || ns.visibleNamespaces == nil {
  226. // When handling dependencies before namespaceMutator, assume they are non-Soong Blueprint modules and give
  227. // access to all namespaces.
  228. return r.sortedNamespaces.sortedItems()
  229. }
  230. return ns.visibleNamespaces
  231. }
  232. func (r *NameResolver) ModuleFromName(name string, namespace blueprint.Namespace) (group blueprint.ModuleGroup, found bool) {
  233. // handle fully qualified references like "//namespace_path:module_name"
  234. nsName, moduleName, isAbs := r.parseFullyQualifiedName(name)
  235. if isAbs {
  236. namespace, found := r.namespaceAt(nsName)
  237. if !found {
  238. return blueprint.ModuleGroup{}, false
  239. }
  240. container := namespace.moduleContainer
  241. return container.ModuleFromName(moduleName, nil)
  242. }
  243. for _, candidate := range r.getNamespacesToSearchForModule(namespace) {
  244. group, found = candidate.moduleContainer.ModuleFromName(name, nil)
  245. if found {
  246. return group, true
  247. }
  248. }
  249. return blueprint.ModuleGroup{}, false
  250. }
  251. func (r *NameResolver) Rename(oldName string, newName string, namespace blueprint.Namespace) []error {
  252. return namespace.(*Namespace).moduleContainer.Rename(oldName, newName, namespace)
  253. }
  254. // resolve each element of namespace.importedNamespaceNames and put the result in namespace.visibleNamespaces
  255. func (r *NameResolver) FindNamespaceImports(namespace *Namespace) (err error) {
  256. namespace.visibleNamespaces = make([]*Namespace, 0, 2+len(namespace.importedNamespaceNames))
  257. // search itself first
  258. namespace.visibleNamespaces = append(namespace.visibleNamespaces, namespace)
  259. // search its imports next
  260. for _, name := range namespace.importedNamespaceNames {
  261. imp, ok := r.namespaceAt(name)
  262. if !ok {
  263. return fmt.Errorf("namespace %v does not exist; Some necessary modules may have been skipped by Soong. Check if PRODUCT_SOURCE_ROOT_DIRS is pruning necessary Android.bp files.", name)
  264. }
  265. namespace.visibleNamespaces = append(namespace.visibleNamespaces, imp)
  266. }
  267. // search the root namespace last
  268. namespace.visibleNamespaces = append(namespace.visibleNamespaces, r.rootNamespace)
  269. return nil
  270. }
  271. func (r *NameResolver) chooseId(namespace *Namespace) {
  272. id := r.sortedNamespaces.index(namespace)
  273. if id < 0 {
  274. panic(fmt.Sprintf("Namespace not found: %v\n", namespace.id))
  275. }
  276. namespace.id = strconv.Itoa(id)
  277. }
  278. func (r *NameResolver) MissingDependencyError(depender string, dependerNamespace blueprint.Namespace, depName string, guess []string) (err error) {
  279. text := fmt.Sprintf("%q depends on undefined module %q.", depender, depName)
  280. _, _, isAbs := r.parseFullyQualifiedName(depName)
  281. if isAbs {
  282. // if the user gave a fully-qualified name, we don't need to look for other
  283. // modules that they might have been referring to
  284. return fmt.Errorf(text)
  285. }
  286. // determine which namespaces the module can be found in
  287. foundInNamespaces := []string{}
  288. skippedDepErrors := []error{}
  289. for _, namespace := range r.sortedNamespaces.sortedItems() {
  290. _, found := namespace.moduleContainer.ModuleFromName(depName, nil)
  291. if found {
  292. foundInNamespaces = append(foundInNamespaces, namespace.Path)
  293. }
  294. _, skipped := namespace.moduleContainer.SkippedModuleFromName(depName, nil)
  295. if skipped {
  296. skippedDepErrors = append(skippedDepErrors, namespace.moduleContainer.MissingDependencyError(depender, dependerNamespace, depName, nil))
  297. }
  298. }
  299. if len(foundInNamespaces) > 0 {
  300. // determine which namespaces are visible to dependerNamespace
  301. dependerNs := dependerNamespace.(*Namespace)
  302. searched := r.getNamespacesToSearchForModule(dependerNs)
  303. importedNames := []string{}
  304. for _, ns := range searched {
  305. importedNames = append(importedNames, ns.Path)
  306. }
  307. text += fmt.Sprintf("\nModule %q is defined in namespace %q which can read these %v namespaces: %q", depender, dependerNs.Path, len(importedNames), importedNames)
  308. text += fmt.Sprintf("\nModule %q can be found in these namespaces: %q", depName, foundInNamespaces)
  309. }
  310. for _, err := range skippedDepErrors {
  311. text += fmt.Sprintf("\n%s", err.Error())
  312. }
  313. if len(guess) > 0 {
  314. text += fmt.Sprintf("\nOr did you mean %q?", guess)
  315. }
  316. return fmt.Errorf(text)
  317. }
  318. func (r *NameResolver) GetNamespace(ctx blueprint.NamespaceContext) blueprint.Namespace {
  319. return r.findNamespaceFromCtx(ctx)
  320. }
  321. func (r *NameResolver) findNamespaceFromCtx(ctx blueprint.NamespaceContext) *Namespace {
  322. return r.findNamespace(filepath.Dir(ctx.ModulePath()))
  323. }
  324. func (r *NameResolver) UniqueName(ctx blueprint.NamespaceContext, name string) (unique string) {
  325. prefix := r.findNamespaceFromCtx(ctx).id
  326. if prefix != "" {
  327. prefix = prefix + "-"
  328. }
  329. return prefix + name
  330. }
  331. var _ blueprint.NameInterface = (*NameResolver)(nil)
  332. type Namespace struct {
  333. blueprint.NamespaceMarker
  334. Path string
  335. // names of namespaces listed as imports by this namespace
  336. importedNamespaceNames []string
  337. // all namespaces that should be searched when a module in this namespace declares a dependency
  338. visibleNamespaces []*Namespace
  339. id string
  340. exportToKati bool
  341. moduleContainer blueprint.NameInterface
  342. }
  343. func NewNamespace(path string) *Namespace {
  344. return &Namespace{Path: path, moduleContainer: blueprint.NewSimpleNameInterface()}
  345. }
  346. var _ blueprint.Namespace = (*Namespace)(nil)
  347. type namespaceProperties struct {
  348. // a list of namespaces that contain modules that will be referenced
  349. // by modules in this namespace.
  350. Imports []string `android:"path"`
  351. }
  352. type NamespaceModule struct {
  353. ModuleBase
  354. namespace *Namespace
  355. resolver *NameResolver
  356. properties namespaceProperties
  357. }
  358. func (n *NamespaceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
  359. }
  360. func (n *NamespaceModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
  361. }
  362. func (n *NamespaceModule) Name() (name string) {
  363. return *n.nameProperties.Name
  364. }
  365. // soong_namespace provides a scope to modules in an Android.bp file to prevent
  366. // module name conflicts with other defined modules in different Android.bp
  367. // files. Once soong_namespace has been defined in an Android.bp file, the
  368. // namespacing is applied to all modules that follow the soong_namespace in
  369. // the current Android.bp file, as well as modules defined in Android.bp files
  370. // in subdirectories. An Android.bp file in a subdirectory can define its own
  371. // soong_namespace which is applied to all its modules and as well as modules
  372. // defined in subdirectories Android.bp files. Modules in a soong_namespace are
  373. // visible to Make by listing the namespace path in PRODUCT_SOONG_NAMESPACES
  374. // make variable in a makefile.
  375. func NamespaceFactory() Module {
  376. module := &NamespaceModule{}
  377. name := "soong_namespace"
  378. module.nameProperties.Name = &name
  379. module.AddProperties(&module.properties)
  380. return module
  381. }
  382. func RegisterNamespaceMutator(ctx RegisterMutatorsContext) {
  383. ctx.BottomUp("namespace_deps", namespaceMutator).Parallel()
  384. }
  385. func namespaceMutator(ctx BottomUpMutatorContext) {
  386. module, ok := ctx.Module().(*NamespaceModule)
  387. if ok {
  388. err := module.resolver.FindNamespaceImports(module.namespace)
  389. if err != nil {
  390. ctx.ModuleErrorf(err.Error())
  391. }
  392. module.resolver.chooseId(module.namespace)
  393. }
  394. }