xref: /aosp_15_r20/build/soong/android/namespace.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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