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