1// Copyright 2014 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
15package blueprint
16
17import (
18	"bufio"
19	"bytes"
20	"cmp"
21	"context"
22	"encoding/json"
23	"errors"
24	"fmt"
25	"hash/fnv"
26	"io"
27	"io/ioutil"
28	"maps"
29	"os"
30	"path/filepath"
31	"reflect"
32	"runtime"
33	"runtime/pprof"
34	"slices"
35	"sort"
36	"strings"
37	"sync"
38	"sync/atomic"
39	"text/scanner"
40	"text/template"
41	"unsafe"
42
43	"github.com/google/blueprint/metrics"
44	"github.com/google/blueprint/parser"
45	"github.com/google/blueprint/pathtools"
46	"github.com/google/blueprint/proptools"
47)
48
49var ErrBuildActionsNotReady = errors.New("build actions are not ready")
50
51const maxErrors = 10
52const MockModuleListFile = "bplist"
53
54const OutFilePermissions = 0666
55
56// A Context contains all the state needed to parse a set of Blueprints files
57// and generate a Ninja file.  The process of generating a Ninja file proceeds
58// through a series of four phases.  Each phase corresponds with a some methods
59// on the Context object
60//
61//	      Phase                            Methods
62//	   ------------      -------------------------------------------
63//	1. Registration         RegisterModuleType, RegisterSingletonType
64//
65//	2. Parse                    ParseBlueprintsFiles, Parse
66//
67//	3. Generate            ResolveDependencies, PrepareBuildActions
68//
69//	4. Write                           WriteBuildFile
70//
71// The registration phase prepares the context to process Blueprints files
72// containing various types of modules.  The parse phase reads in one or more
73// Blueprints files and validates their contents against the module types that
74// have been registered.  The generate phase then analyzes the parsed Blueprints
75// contents to create an internal representation for the build actions that must
76// be performed.  This phase also performs validation of the module dependencies
77// and property values defined in the parsed Blueprints files.  Finally, the
78// write phase generates the Ninja manifest text based on the generated build
79// actions.
80type Context struct {
81	context.Context
82
83	// Used for metrics-related event logging.
84	EventHandler *metrics.EventHandler
85
86	BeforePrepareBuildActionsHook func() error
87
88	moduleFactories     map[string]ModuleFactory
89	nameInterface       NameInterface
90	moduleGroups        []*moduleGroup
91	moduleInfo          map[Module]*moduleInfo
92	modulesSorted       []*moduleInfo
93	singletonInfo       []*singletonInfo
94	mutatorInfo         []*mutatorInfo
95	variantMutatorNames []string
96
97	transitionMutators []*transitionMutatorImpl
98
99	depsModified uint32 // positive if a mutator modified the dependencies
100
101	dependenciesReady bool // set to true on a successful ResolveDependencies
102	buildActionsReady bool // set to true on a successful PrepareBuildActions
103
104	// set by SetIgnoreUnknownModuleTypes
105	ignoreUnknownModuleTypes bool
106
107	// set by SetAllowMissingDependencies
108	allowMissingDependencies bool
109
110	verifyProvidersAreUnchanged bool
111
112	// set during PrepareBuildActions
113	nameTracker     *nameTracker
114	liveGlobals     *liveTracker
115	globalVariables map[Variable]*ninjaString
116	globalPools     map[Pool]*poolDef
117	globalRules     map[Rule]*ruleDef
118
119	// set during PrepareBuildActions
120	outDir             *ninjaString // The builddir special Ninja variable
121	requiredNinjaMajor int          // For the ninja_required_version variable
122	requiredNinjaMinor int          // For the ninja_required_version variable
123	requiredNinjaMicro int          // For the ninja_required_version variable
124
125	subninjas []string
126
127	// set lazily by sortedModuleGroups
128	cachedSortedModuleGroups []*moduleGroup
129	// cache deps modified to determine whether cachedSortedModuleGroups needs to be recalculated
130	cachedDepsModified bool
131
132	globs    map[globKey]pathtools.GlobResult
133	globLock sync.Mutex
134
135	srcDir         string
136	fs             pathtools.FileSystem
137	moduleListFile string
138
139	// Mutators indexed by the ID of the provider associated with them.  Not all mutators will
140	// have providers, and not all providers will have a mutator, or if they do the mutator may
141	// not be registered in this Context.
142	providerMutators []*mutatorInfo
143
144	// The currently running mutator
145	startedMutator *mutatorInfo
146	// True for any mutators that have already run over all modules
147	finishedMutators map[*mutatorInfo]bool
148
149	// If true, RunBlueprint will skip cloning modules at the end of RunBlueprint.
150	// Cloning modules intentionally invalidates some Module values after
151	// mutators run (to ensure that mutators don't set such Module values in a way
152	// which ruins the integrity of the graph). However, keeping Module values
153	// changed by mutators may be a desirable outcome (such as for tooling or tests).
154	SkipCloneModulesAfterMutators bool
155
156	// String values that can be used to gate build graph traversal
157	includeTags *IncludeTags
158
159	sourceRootDirs *SourceRootDirs
160}
161
162// A container for String keys. The keys can be used to gate build graph traversal
163type SourceRootDirs struct {
164	dirs []string
165}
166
167func (dirs *SourceRootDirs) Add(names ...string) {
168	dirs.dirs = append(dirs.dirs, names...)
169}
170
171func (dirs *SourceRootDirs) SourceRootDirAllowed(path string) (bool, string) {
172	sort.Slice(dirs.dirs, func(i, j int) bool {
173		return len(dirs.dirs[i]) < len(dirs.dirs[j])
174	})
175	last := len(dirs.dirs)
176	for i := range dirs.dirs {
177		// iterate from longest paths (most specific)
178		prefix := dirs.dirs[last-i-1]
179		disallowedPrefix := false
180		if len(prefix) >= 1 && prefix[0] == '-' {
181			prefix = prefix[1:]
182			disallowedPrefix = true
183		}
184		if strings.HasPrefix(path, prefix) {
185			if disallowedPrefix {
186				return false, prefix
187			} else {
188				return true, prefix
189			}
190		}
191	}
192	return true, ""
193}
194
195func (c *Context) AddSourceRootDirs(dirs ...string) {
196	c.sourceRootDirs.Add(dirs...)
197}
198
199// A container for String keys. The keys can be used to gate build graph traversal
200type IncludeTags map[string]bool
201
202func (tags *IncludeTags) Add(names ...string) {
203	for _, name := range names {
204		(*tags)[name] = true
205	}
206}
207
208func (tags *IncludeTags) Contains(tag string) bool {
209	_, exists := (*tags)[tag]
210	return exists
211}
212
213func (c *Context) AddIncludeTags(names ...string) {
214	c.includeTags.Add(names...)
215}
216
217func (c *Context) ContainsIncludeTag(name string) bool {
218	return c.includeTags.Contains(name)
219}
220
221// An Error describes a problem that was encountered that is related to a
222// particular location in a Blueprints file.
223type BlueprintError struct {
224	Err error            // the error that occurred
225	Pos scanner.Position // the relevant Blueprints file location
226}
227
228// A ModuleError describes a problem that was encountered that is related to a
229// particular module in a Blueprints file
230type ModuleError struct {
231	BlueprintError
232	module *moduleInfo
233}
234
235// A PropertyError describes a problem that was encountered that is related to a
236// particular property in a Blueprints file
237type PropertyError struct {
238	ModuleError
239	property string
240}
241
242func (e *BlueprintError) Error() string {
243	return fmt.Sprintf("%s: %s", e.Pos, e.Err)
244}
245
246func (e *ModuleError) Error() string {
247	return fmt.Sprintf("%s: %s: %s", e.Pos, e.module, e.Err)
248}
249
250func (e *PropertyError) Error() string {
251	return fmt.Sprintf("%s: %s: %s: %s", e.Pos, e.module, e.property, e.Err)
252}
253
254type localBuildActions struct {
255	variables []*localVariable
256	rules     []*localRule
257	buildDefs []*buildDef
258}
259
260type moduleAlias struct {
261	variant variant
262	target  *moduleInfo
263}
264
265func (m *moduleAlias) alias() *moduleAlias              { return m }
266func (m *moduleAlias) module() *moduleInfo              { return nil }
267func (m *moduleAlias) moduleOrAliasTarget() *moduleInfo { return m.target }
268func (m *moduleAlias) moduleOrAliasVariant() variant    { return m.variant }
269
270func (m *moduleInfo) alias() *moduleAlias              { return nil }
271func (m *moduleInfo) module() *moduleInfo              { return m }
272func (m *moduleInfo) moduleOrAliasTarget() *moduleInfo { return m }
273func (m *moduleInfo) moduleOrAliasVariant() variant    { return m.variant }
274
275type moduleOrAlias interface {
276	alias() *moduleAlias
277	module() *moduleInfo
278	moduleOrAliasTarget() *moduleInfo
279	moduleOrAliasVariant() variant
280}
281
282type modulesOrAliases []moduleOrAlias
283
284func (l modulesOrAliases) firstModule() *moduleInfo {
285	for _, moduleOrAlias := range l {
286		if m := moduleOrAlias.module(); m != nil {
287			return m
288		}
289	}
290	panic(fmt.Errorf("no first module!"))
291}
292
293func (l modulesOrAliases) lastModule() *moduleInfo {
294	for i := range l {
295		if m := l[len(l)-1-i].module(); m != nil {
296			return m
297		}
298	}
299	panic(fmt.Errorf("no last module!"))
300}
301
302type moduleGroup struct {
303	name      string
304	ninjaName string
305
306	modules modulesOrAliases
307
308	namespace Namespace
309}
310
311func (group *moduleGroup) moduleOrAliasByVariantName(name string) moduleOrAlias {
312	for _, module := range group.modules {
313		if module.moduleOrAliasVariant().name == name {
314			return module
315		}
316	}
317	return nil
318}
319
320func (group *moduleGroup) moduleByVariantName(name string) *moduleInfo {
321	return group.moduleOrAliasByVariantName(name).module()
322}
323
324type moduleInfo struct {
325	// set during Parse
326	typeName          string
327	factory           ModuleFactory
328	relBlueprintsFile string
329	pos               scanner.Position
330	propertyPos       map[string]scanner.Position
331	createdBy         *moduleInfo
332
333	variant variant
334
335	logicModule Module
336	group       *moduleGroup
337	properties  []interface{}
338
339	// set during ResolveDependencies
340	missingDeps   []string
341	newDirectDeps []depInfo
342
343	// set during updateDependencies
344	reverseDeps []*moduleInfo
345	forwardDeps []*moduleInfo
346	directDeps  []depInfo
347
348	// used by parallelVisit
349	waitingCount int
350
351	// set during each runMutator
352	splitModules           modulesOrAliases
353	obsoletedByNewVariants bool
354
355	// Used by TransitionMutator implementations
356	transitionVariations     []string
357	currentTransitionMutator string
358	requiredVariationsLock   sync.Mutex
359
360	// outgoingTransitionCache stores the final variation for each dependency, indexed by the source variation
361	// index in transitionVariations and then by the index of the dependency in directDeps
362	outgoingTransitionCache [][]string
363
364	// set during PrepareBuildActions
365	actionDefs localBuildActions
366
367	providers                  []interface{}
368	providerInitialValueHashes []uint64
369
370	startedMutator  *mutatorInfo
371	finishedMutator *mutatorInfo
372
373	startedGenerateBuildActions  bool
374	finishedGenerateBuildActions bool
375}
376
377type variant struct {
378	name                 string
379	variations           variationMap
380	dependencyVariations variationMap
381}
382
383type depInfo struct {
384	module *moduleInfo
385	tag    DependencyTag
386}
387
388func (module *moduleInfo) Name() string {
389	// If this is called from a LoadHook (which is run before the module has been registered)
390	// then group will not be set and so the name is retrieved from logicModule.Name().
391	// Usually, using that method is not safe as it does not track renames (group.name does).
392	// However, when called from LoadHook it is safe as there is no way to rename a module
393	// until after the LoadHook has run and the module has been registered.
394	if module.group != nil {
395		return module.group.name
396	} else {
397		return module.logicModule.Name()
398	}
399}
400
401func (module *moduleInfo) String() string {
402	s := fmt.Sprintf("module %q", module.Name())
403	if module.variant.name != "" {
404		s += fmt.Sprintf(" variant %q", module.variant.name)
405	}
406	if module.createdBy != nil {
407		s += fmt.Sprintf(" (created by %s)", module.createdBy)
408	}
409
410	return s
411}
412
413func (module *moduleInfo) namespace() Namespace {
414	return module.group.namespace
415}
416
417// A Variation is a way that a variant of a module differs from other variants of the same module.
418// For example, two variants of the same module might have Variation{"arch","arm"} and
419// Variation{"arch","arm64"}
420type Variation struct {
421	// Mutator is the axis on which this variation applies, i.e. "arch" or "link"
422	Mutator string
423	// Variation is the name of the variation on the axis, i.e. "arm" or "arm64" for arch, or
424	// "shared" or "static" for link.
425	Variation string
426}
427
428// A variationMap stores a map of Mutator to Variation to specify a variant of a module.
429type variationMap map[string]string
430
431func (vm variationMap) clone() variationMap {
432	return maps.Clone(vm)
433}
434
435// Compare this variationMap to another one.  Returns true if the every entry in this map
436// exists and has the same value in the other map.
437func (vm variationMap) subsetOf(other variationMap) bool {
438	for k, v1 := range vm {
439		if v2, ok := other[k]; !ok || v1 != v2 {
440			return false
441		}
442	}
443	return true
444}
445
446func (vm variationMap) equal(other variationMap) bool {
447	return maps.Equal(vm, other)
448}
449
450type singletonInfo struct {
451	// set during RegisterSingletonType
452	factory   SingletonFactory
453	singleton Singleton
454	name      string
455	parallel  bool
456
457	// set during PrepareBuildActions
458	actionDefs localBuildActions
459}
460
461type mutatorInfo struct {
462	// set during RegisterMutator
463	topDownMutator    TopDownMutator
464	bottomUpMutator   BottomUpMutator
465	name              string
466	parallel          bool
467	transitionMutator *transitionMutatorImpl
468}
469
470func newContext() *Context {
471	eventHandler := metrics.EventHandler{}
472	return &Context{
473		Context:                     context.Background(),
474		EventHandler:                &eventHandler,
475		moduleFactories:             make(map[string]ModuleFactory),
476		nameInterface:               NewSimpleNameInterface(),
477		moduleInfo:                  make(map[Module]*moduleInfo),
478		globs:                       make(map[globKey]pathtools.GlobResult),
479		fs:                          pathtools.OsFs,
480		finishedMutators:            make(map[*mutatorInfo]bool),
481		includeTags:                 &IncludeTags{},
482		sourceRootDirs:              &SourceRootDirs{},
483		outDir:                      nil,
484		requiredNinjaMajor:          1,
485		requiredNinjaMinor:          7,
486		requiredNinjaMicro:          0,
487		verifyProvidersAreUnchanged: true,
488	}
489}
490
491// NewContext creates a new Context object.  The created context initially has
492// no module or singleton factories registered, so the RegisterModuleFactory and
493// RegisterSingletonFactory methods must be called before it can do anything
494// useful.
495func NewContext() *Context {
496	ctx := newContext()
497
498	ctx.RegisterBottomUpMutator("blueprint_deps", blueprintDepsMutator)
499
500	return ctx
501}
502
503// A ModuleFactory function creates a new Module object.  See the
504// Context.RegisterModuleType method for details about how a registered
505// ModuleFactory is used by a Context.
506type ModuleFactory func() (m Module, propertyStructs []interface{})
507
508// RegisterModuleType associates a module type name (which can appear in a
509// Blueprints file) with a Module factory function.  When the given module type
510// name is encountered in a Blueprints file during parsing, the Module factory
511// is invoked to instantiate a new Module object to handle the build action
512// generation for the module.  If a Mutator splits a module into multiple variants,
513// the factory is invoked again to create a new Module for each variant.
514//
515// The module type names given here must be unique for the context.  The factory
516// function should be a named function so that its package and name can be
517// included in the generated Ninja file for debugging purposes.
518//
519// The factory function returns two values.  The first is the newly created
520// Module object.  The second is a slice of pointers to that Module object's
521// properties structs.  Each properties struct is examined when parsing a module
522// definition of this type in a Blueprints file.  Exported fields of the
523// properties structs are automatically set to the property values specified in
524// the Blueprints file.  The properties struct field names determine the name of
525// the Blueprints file properties that are used - the Blueprints property name
526// matches that of the properties struct field name with the first letter
527// converted to lower-case.
528//
529// The fields of the properties struct must be either []string, a string, or
530// bool. The Context will panic if a Module gets instantiated with a properties
531// struct containing a field that is not one these supported types.
532//
533// Any properties that appear in the Blueprints files that are not built-in
534// module properties (such as "name" and "deps") and do not have a corresponding
535// field in the returned module properties struct result in an error during the
536// Context's parse phase.
537//
538// As an example, the follow code:
539//
540//	type myModule struct {
541//	    properties struct {
542//	        Foo string
543//	        Bar []string
544//	    }
545//	}
546//
547//	func NewMyModule() (blueprint.Module, []interface{}) {
548//	    module := new(myModule)
549//	    properties := &module.properties
550//	    return module, []interface{}{properties}
551//	}
552//
553//	func main() {
554//	    ctx := blueprint.NewContext()
555//	    ctx.RegisterModuleType("my_module", NewMyModule)
556//	    // ...
557//	}
558//
559// would support parsing a module defined in a Blueprints file as follows:
560//
561//	my_module {
562//	    name: "myName",
563//	    foo:  "my foo string",
564//	    bar:  ["my", "bar", "strings"],
565//	}
566//
567// The factory function may be called from multiple goroutines.  Any accesses
568// to global variables must be synchronized.
569func (c *Context) RegisterModuleType(name string, factory ModuleFactory) {
570	if _, present := c.moduleFactories[name]; present {
571		panic(fmt.Errorf("module type %q is already registered", name))
572	}
573	c.moduleFactories[name] = factory
574}
575
576// A SingletonFactory function creates a new Singleton object.  See the
577// Context.RegisterSingletonType method for details about how a registered
578// SingletonFactory is used by a Context.
579type SingletonFactory func() Singleton
580
581// RegisterSingletonType registers a singleton type that will be invoked to
582// generate build actions.  Each registered singleton type is instantiated
583// and invoked exactly once as part of the generate phase.
584//
585// Those singletons registered with parallel=true are run in parallel, after
586// which the other registered singletons are run in registration order.
587//
588// The singleton type names given here must be unique for the context.  The
589// factory function should be a named function so that its package and name can
590// be included in the generated Ninja file for debugging purposes.
591func (c *Context) RegisterSingletonType(name string, factory SingletonFactory, parallel bool) {
592	for _, s := range c.singletonInfo {
593		if s.name == name {
594			panic(fmt.Errorf("singleton %q is already registered", name))
595		}
596	}
597
598	c.singletonInfo = append(c.singletonInfo, &singletonInfo{
599		factory:   factory,
600		singleton: factory(),
601		name:      name,
602		parallel:  parallel,
603	})
604}
605
606func (c *Context) SetNameInterface(i NameInterface) {
607	c.nameInterface = i
608}
609
610func (c *Context) SetSrcDir(path string) {
611	c.srcDir = path
612	c.fs = pathtools.NewOsFs(path)
613}
614
615func (c *Context) SrcDir() string {
616	return c.srcDir
617}
618
619func singletonPkgPath(singleton Singleton) string {
620	typ := reflect.TypeOf(singleton)
621	for typ.Kind() == reflect.Ptr {
622		typ = typ.Elem()
623	}
624	return typ.PkgPath()
625}
626
627func singletonTypeName(singleton Singleton) string {
628	typ := reflect.TypeOf(singleton)
629	for typ.Kind() == reflect.Ptr {
630		typ = typ.Elem()
631	}
632	return typ.PkgPath() + "." + typ.Name()
633}
634
635// RegisterTopDownMutator registers a mutator that will be invoked to propagate dependency info
636// top-down between Modules.  Each registered mutator is invoked in registration order (mixing
637// TopDownMutators and BottomUpMutators) once per Module, and the invocation on any module will
638// have returned before it is in invoked on any of its dependencies.
639//
640// The mutator type names given here must be unique to all top down mutators in
641// the Context.
642//
643// Returns a MutatorHandle, on which Parallel can be called to set the mutator to visit modules in
644// parallel while maintaining ordering.
645func (c *Context) RegisterTopDownMutator(name string, mutator TopDownMutator) MutatorHandle {
646	for _, m := range c.mutatorInfo {
647		if m.name == name && m.topDownMutator != nil {
648			panic(fmt.Errorf("mutator %q is already registered", name))
649		}
650	}
651
652	info := &mutatorInfo{
653		topDownMutator: mutator,
654		name:           name,
655	}
656
657	c.mutatorInfo = append(c.mutatorInfo, info)
658
659	return info
660}
661
662// RegisterBottomUpMutator registers a mutator that will be invoked to split Modules into variants.
663// Each registered mutator is invoked in registration order (mixing TopDownMutators and
664// BottomUpMutators) once per Module, will not be invoked on a module until the invocations on all
665// of the modules dependencies have returned.
666//
667// The mutator type names given here must be unique to all bottom up or early
668// mutators in the Context.
669//
670// Returns a MutatorHandle, on which Parallel can be called to set the mutator to visit modules in
671// parallel while maintaining ordering.
672func (c *Context) RegisterBottomUpMutator(name string, mutator BottomUpMutator) MutatorHandle {
673	for _, m := range c.variantMutatorNames {
674		if m == name {
675			panic(fmt.Errorf("mutator %q is already registered", name))
676		}
677	}
678
679	info := &mutatorInfo{
680		bottomUpMutator: mutator,
681		name:            name,
682	}
683	c.mutatorInfo = append(c.mutatorInfo, info)
684
685	c.variantMutatorNames = append(c.variantMutatorNames, name)
686
687	return info
688}
689
690type MutatorHandle interface {
691	// Set the mutator to visit modules in parallel while maintaining ordering.  Calling any
692	// method on the mutator context is thread-safe, but the mutator must handle synchronization
693	// for any modifications to global state or any modules outside the one it was invoked on.
694	Parallel() MutatorHandle
695
696	setTransitionMutator(impl *transitionMutatorImpl) MutatorHandle
697}
698
699func (mutator *mutatorInfo) Parallel() MutatorHandle {
700	mutator.parallel = true
701	return mutator
702}
703
704func (mutator *mutatorInfo) setTransitionMutator(impl *transitionMutatorImpl) MutatorHandle {
705	mutator.transitionMutator = impl
706	return mutator
707}
708
709// SetIgnoreUnknownModuleTypes sets the behavior of the context in the case
710// where it encounters an unknown module type while parsing Blueprints files. By
711// default, the context will report unknown module types as an error.  If this
712// method is called with ignoreUnknownModuleTypes set to true then the context
713// will silently ignore unknown module types.
714//
715// This method should generally not be used.  It exists to facilitate the
716// bootstrapping process.
717func (c *Context) SetIgnoreUnknownModuleTypes(ignoreUnknownModuleTypes bool) {
718	c.ignoreUnknownModuleTypes = ignoreUnknownModuleTypes
719}
720
721// SetAllowMissingDependencies changes the behavior of Blueprint to ignore
722// unresolved dependencies.  If the module's GenerateBuildActions calls
723// ModuleContext.GetMissingDependencies Blueprint will not emit any errors
724// for missing dependencies.
725func (c *Context) SetAllowMissingDependencies(allowMissingDependencies bool) {
726	c.allowMissingDependencies = allowMissingDependencies
727}
728
729// SetVerifyProvidersAreUnchanged makes blueprint hash all providers immediately
730// after SetProvider() is called, and then hash them again after the build finished.
731// If the hashes change, it's an error. Providers are supposed to be immutable, but
732// we don't have any more direct way to enforce that in go.
733func (c *Context) SetVerifyProvidersAreUnchanged(verifyProvidersAreUnchanged bool) {
734	c.verifyProvidersAreUnchanged = verifyProvidersAreUnchanged
735}
736
737func (c *Context) GetVerifyProvidersAreUnchanged() bool {
738	return c.verifyProvidersAreUnchanged
739}
740
741func (c *Context) SetModuleListFile(listFile string) {
742	c.moduleListFile = listFile
743}
744
745func (c *Context) ListModulePaths(baseDir string) (paths []string, err error) {
746	reader, err := c.fs.Open(c.moduleListFile)
747	if err != nil {
748		return nil, err
749	}
750	defer reader.Close()
751	bytes, err := ioutil.ReadAll(reader)
752	if err != nil {
753		return nil, err
754	}
755	text := string(bytes)
756
757	text = strings.Trim(text, "\n")
758	lines := strings.Split(text, "\n")
759	for i := range lines {
760		lines[i] = filepath.Join(baseDir, lines[i])
761	}
762
763	return lines, nil
764}
765
766// a fileParseContext tells the status of parsing a particular file
767type fileParseContext struct {
768	// name of file
769	fileName string
770
771	// scope to use when resolving variables
772	Scope *parser.Scope
773
774	// pointer to the one in the parent directory
775	parent *fileParseContext
776
777	// is closed once FileHandler has completed for this file
778	doneVisiting chan struct{}
779}
780
781// ParseBlueprintsFiles parses a set of Blueprints files starting with the file
782// at rootFile.  When it encounters a Blueprints file with a set of subdirs
783// listed it recursively parses any Blueprints files found in those
784// subdirectories.
785//
786// If no errors are encountered while parsing the files, the list of paths on
787// which the future output will depend is returned.  This list will include both
788// Blueprints file paths as well as directory paths for cases where wildcard
789// subdirs are found.
790func (c *Context) ParseBlueprintsFiles(rootFile string,
791	config interface{}) (deps []string, errs []error) {
792
793	baseDir := filepath.Dir(rootFile)
794	pathsToParse, err := c.ListModulePaths(baseDir)
795	if err != nil {
796		return nil, []error{err}
797	}
798	return c.ParseFileList(baseDir, pathsToParse, config)
799}
800
801type shouldVisitFileInfo struct {
802	shouldVisitFile bool
803	skippedModules  []string
804	reasonForSkip   string
805	errs            []error
806}
807
808// Returns a boolean for whether this file should be analyzed
809// Evaluates to true if the file either
810// 1. does not contain a blueprint_package_includes
811// 2. contains a blueprint_package_includes and all requested tags are set
812// This should be processed before adding any modules to the build graph
813func shouldVisitFile(c *Context, file *parser.File) shouldVisitFileInfo {
814	skippedModules := []string{}
815	for _, def := range file.Defs {
816		switch def := def.(type) {
817		case *parser.Module:
818			skippedModules = append(skippedModules, def.Name())
819		}
820	}
821
822	shouldVisit, invalidatingPrefix := c.sourceRootDirs.SourceRootDirAllowed(file.Name)
823	if !shouldVisit {
824		return shouldVisitFileInfo{
825			shouldVisitFile: shouldVisit,
826			skippedModules:  skippedModules,
827			reasonForSkip: fmt.Sprintf(
828				"%q is a descendant of %q, and that path prefix was not included in PRODUCT_SOURCE_ROOT_DIRS",
829				file.Name,
830				invalidatingPrefix,
831			),
832		}
833	}
834	return shouldVisitFileInfo{shouldVisitFile: true}
835}
836
837func (c *Context) ParseFileList(rootDir string, filePaths []string,
838	config interface{}) (deps []string, errs []error) {
839
840	if len(filePaths) < 1 {
841		return nil, []error{fmt.Errorf("no paths provided to parse")}
842	}
843
844	c.dependenciesReady = false
845
846	type newModuleInfo struct {
847		*moduleInfo
848		deps  []string
849		added chan<- struct{}
850	}
851
852	type newSkipInfo struct {
853		shouldVisitFileInfo
854		file string
855	}
856
857	moduleCh := make(chan newModuleInfo)
858	errsCh := make(chan []error)
859	doneCh := make(chan struct{})
860	skipCh := make(chan newSkipInfo)
861	var numErrs uint32
862	var numGoroutines int32
863
864	// handler must be reentrant
865	handleOneFile := func(file *parser.File) {
866		if atomic.LoadUint32(&numErrs) > maxErrors {
867			return
868		}
869
870		addedCh := make(chan struct{})
871
872		var scopedModuleFactories map[string]ModuleFactory
873
874		var addModule func(module *moduleInfo) []error
875		addModule = func(module *moduleInfo) []error {
876			// Run any load hooks immediately before it is sent to the moduleCh and is
877			// registered by name. This allows load hooks to set and/or modify any aspect
878			// of the module (including names) using information that is not available when
879			// the module factory is called.
880			newModules, newDeps, errs := runAndRemoveLoadHooks(c, config, module, &scopedModuleFactories)
881			if len(errs) > 0 {
882				return errs
883			}
884
885			moduleCh <- newModuleInfo{module, newDeps, addedCh}
886			<-addedCh
887			for _, n := range newModules {
888				errs = addModule(n)
889				if len(errs) > 0 {
890					return errs
891				}
892			}
893			return nil
894		}
895		shouldVisitInfo := shouldVisitFile(c, file)
896		errs := shouldVisitInfo.errs
897		if len(errs) > 0 {
898			atomic.AddUint32(&numErrs, uint32(len(errs)))
899			errsCh <- errs
900		}
901		if !shouldVisitInfo.shouldVisitFile {
902			skipCh <- newSkipInfo{
903				file:                file.Name,
904				shouldVisitFileInfo: shouldVisitInfo,
905			}
906			// TODO: Write a file that lists the skipped bp files
907			return
908		}
909
910		for _, def := range file.Defs {
911			switch def := def.(type) {
912			case *parser.Module:
913				module, errs := processModuleDef(def, file.Name, c.moduleFactories, scopedModuleFactories, c.ignoreUnknownModuleTypes)
914				if len(errs) == 0 && module != nil {
915					errs = addModule(module)
916				}
917
918				if len(errs) > 0 {
919					atomic.AddUint32(&numErrs, uint32(len(errs)))
920					errsCh <- errs
921				}
922
923			case *parser.Assignment:
924				// Already handled via Scope object
925			default:
926				panic("unknown definition type")
927			}
928
929		}
930	}
931
932	atomic.AddInt32(&numGoroutines, 1)
933	go func() {
934		var errs []error
935		deps, errs = c.WalkBlueprintsFiles(rootDir, filePaths, handleOneFile)
936		if len(errs) > 0 {
937			errsCh <- errs
938		}
939		doneCh <- struct{}{}
940	}()
941
942	var hookDeps []string
943loop:
944	for {
945		select {
946		case newErrs := <-errsCh:
947			errs = append(errs, newErrs...)
948		case module := <-moduleCh:
949			newErrs := c.addModule(module.moduleInfo)
950			hookDeps = append(hookDeps, module.deps...)
951			if module.added != nil {
952				module.added <- struct{}{}
953			}
954			if len(newErrs) > 0 {
955				errs = append(errs, newErrs...)
956			}
957		case <-doneCh:
958			n := atomic.AddInt32(&numGoroutines, -1)
959			if n == 0 {
960				break loop
961			}
962		case skipped := <-skipCh:
963			nctx := newNamespaceContextFromFilename(skipped.file)
964			for _, name := range skipped.skippedModules {
965				c.nameInterface.NewSkippedModule(nctx, name, SkippedModuleInfo{
966					filename: skipped.file,
967					reason:   skipped.reasonForSkip,
968				})
969			}
970		}
971	}
972
973	deps = append(deps, hookDeps...)
974	return deps, errs
975}
976
977type FileHandler func(*parser.File)
978
979// WalkBlueprintsFiles walks a set of Blueprints files starting with the given filepaths,
980// calling the given file handler on each
981//
982// When WalkBlueprintsFiles encounters a Blueprints file with a set of subdirs listed,
983// it recursively parses any Blueprints files found in those subdirectories.
984//
985// If any of the file paths is an ancestor directory of any other of file path, the ancestor
986// will be parsed and visited first.
987//
988// the file handler will be called from a goroutine, so it must be reentrant.
989//
990// If no errors are encountered while parsing the files, the list of paths on
991// which the future output will depend is returned.  This list will include both
992// Blueprints file paths as well as directory paths for cases where wildcard
993// subdirs are found.
994//
995// visitor will be called asynchronously, and will only be called once visitor for each
996// ancestor directory has completed.
997//
998// WalkBlueprintsFiles will not return until all calls to visitor have returned.
999func (c *Context) WalkBlueprintsFiles(rootDir string, filePaths []string,
1000	visitor FileHandler) (deps []string, errs []error) {
1001
1002	// make a mapping from ancestors to their descendants to facilitate parsing ancestors first
1003	descendantsMap, err := findBlueprintDescendants(filePaths)
1004	if err != nil {
1005		panic(err.Error())
1006	}
1007	blueprintsSet := make(map[string]bool)
1008
1009	// Channels to receive data back from openAndParse goroutines
1010	blueprintsCh := make(chan fileParseContext)
1011	errsCh := make(chan []error)
1012	depsCh := make(chan string)
1013
1014	// Channel to notify main loop that a openAndParse goroutine has finished
1015	doneParsingCh := make(chan fileParseContext)
1016
1017	// Number of outstanding goroutines to wait for
1018	activeCount := 0
1019	var pending []fileParseContext
1020	tooManyErrors := false
1021
1022	// Limit concurrent calls to parseBlueprintFiles to 200
1023	// Darwin has a default limit of 256 open files
1024	maxActiveCount := 200
1025
1026	// count the number of pending calls to visitor()
1027	visitorWaitGroup := sync.WaitGroup{}
1028
1029	startParseBlueprintsFile := func(blueprint fileParseContext) {
1030		if blueprintsSet[blueprint.fileName] {
1031			return
1032		}
1033		blueprintsSet[blueprint.fileName] = true
1034		activeCount++
1035		deps = append(deps, blueprint.fileName)
1036		visitorWaitGroup.Add(1)
1037		go func() {
1038			file, blueprints, deps, errs := c.openAndParse(blueprint.fileName, blueprint.Scope, rootDir,
1039				&blueprint)
1040			if len(errs) > 0 {
1041				errsCh <- errs
1042			}
1043			for _, blueprint := range blueprints {
1044				blueprintsCh <- blueprint
1045			}
1046			for _, dep := range deps {
1047				depsCh <- dep
1048			}
1049			doneParsingCh <- blueprint
1050
1051			if blueprint.parent != nil && blueprint.parent.doneVisiting != nil {
1052				// wait for visitor() of parent to complete
1053				<-blueprint.parent.doneVisiting
1054			}
1055
1056			if len(errs) == 0 {
1057				// process this file
1058				visitor(file)
1059			}
1060			if blueprint.doneVisiting != nil {
1061				close(blueprint.doneVisiting)
1062			}
1063			visitorWaitGroup.Done()
1064		}()
1065	}
1066
1067	foundParseableBlueprint := func(blueprint fileParseContext) {
1068		if activeCount >= maxActiveCount {
1069			pending = append(pending, blueprint)
1070		} else {
1071			startParseBlueprintsFile(blueprint)
1072		}
1073	}
1074
1075	startParseDescendants := func(blueprint fileParseContext) {
1076		descendants, hasDescendants := descendantsMap[blueprint.fileName]
1077		if hasDescendants {
1078			for _, descendant := range descendants {
1079				foundParseableBlueprint(fileParseContext{descendant, parser.NewScope(blueprint.Scope), &blueprint, make(chan struct{})})
1080			}
1081		}
1082	}
1083
1084	// begin parsing any files that have no ancestors
1085	startParseDescendants(fileParseContext{"", parser.NewScope(nil), nil, nil})
1086
1087loop:
1088	for {
1089		if len(errs) > maxErrors {
1090			tooManyErrors = true
1091		}
1092
1093		select {
1094		case newErrs := <-errsCh:
1095			errs = append(errs, newErrs...)
1096		case dep := <-depsCh:
1097			deps = append(deps, dep)
1098		case blueprint := <-blueprintsCh:
1099			if tooManyErrors {
1100				continue
1101			}
1102			foundParseableBlueprint(blueprint)
1103		case blueprint := <-doneParsingCh:
1104			activeCount--
1105			if !tooManyErrors {
1106				startParseDescendants(blueprint)
1107			}
1108			if activeCount < maxActiveCount && len(pending) > 0 {
1109				// start to process the next one from the queue
1110				next := pending[len(pending)-1]
1111				pending = pending[:len(pending)-1]
1112				startParseBlueprintsFile(next)
1113			}
1114			if activeCount == 0 {
1115				break loop
1116			}
1117		}
1118	}
1119
1120	sort.Strings(deps)
1121
1122	// wait for every visitor() to complete
1123	visitorWaitGroup.Wait()
1124
1125	return
1126}
1127
1128// MockFileSystem causes the Context to replace all reads with accesses to the provided map of
1129// filenames to contents stored as a byte slice.
1130func (c *Context) MockFileSystem(files map[string][]byte) {
1131	// look for a module list file
1132	_, ok := files[MockModuleListFile]
1133	if !ok {
1134		// no module list file specified; find every file named Blueprints
1135		pathsToParse := []string{}
1136		for candidate := range files {
1137			if filepath.Base(candidate) == "Android.bp" {
1138				pathsToParse = append(pathsToParse, candidate)
1139			}
1140		}
1141		if len(pathsToParse) < 1 {
1142			panic(fmt.Sprintf("No Blueprints files found in mock filesystem: %v\n", files))
1143		}
1144		// put the list of Blueprints files into a list file
1145		files[MockModuleListFile] = []byte(strings.Join(pathsToParse, "\n"))
1146	}
1147	c.SetModuleListFile(MockModuleListFile)
1148
1149	// mock the filesystem
1150	c.fs = pathtools.MockFs(files)
1151}
1152
1153func (c *Context) SetFs(fs pathtools.FileSystem) {
1154	c.fs = fs
1155}
1156
1157// openAndParse opens and parses a single Blueprints file, and returns the results
1158func (c *Context) openAndParse(filename string, scope *parser.Scope, rootDir string,
1159	parent *fileParseContext) (file *parser.File,
1160	subBlueprints []fileParseContext, deps []string, errs []error) {
1161
1162	f, err := c.fs.Open(filename)
1163	if err != nil {
1164		// couldn't open the file; see if we can provide a clearer error than "could not open file"
1165		stats, statErr := c.fs.Lstat(filename)
1166		if statErr == nil {
1167			isSymlink := stats.Mode()&os.ModeSymlink != 0
1168			if isSymlink {
1169				err = fmt.Errorf("could not open symlink %v : %v", filename, err)
1170				target, readlinkErr := os.Readlink(filename)
1171				if readlinkErr == nil {
1172					_, targetStatsErr := c.fs.Lstat(target)
1173					if targetStatsErr != nil {
1174						err = fmt.Errorf("could not open symlink %v; its target (%v) cannot be opened", filename, target)
1175					}
1176				}
1177			} else {
1178				err = fmt.Errorf("%v exists but could not be opened: %v", filename, err)
1179			}
1180		}
1181		return nil, nil, nil, []error{err}
1182	}
1183
1184	func() {
1185		defer func() {
1186			err = f.Close()
1187			if err != nil {
1188				errs = append(errs, err)
1189			}
1190		}()
1191		file, subBlueprints, errs = c.parseOne(rootDir, filename, f, scope, parent)
1192	}()
1193
1194	if len(errs) > 0 {
1195		return nil, nil, nil, errs
1196	}
1197
1198	for _, b := range subBlueprints {
1199		deps = append(deps, b.fileName)
1200	}
1201
1202	return file, subBlueprints, deps, nil
1203}
1204
1205// parseOne parses a single Blueprints file from the given reader, creating Module
1206// objects for each of the module definitions encountered.  If the Blueprints
1207// file contains an assignment to the "subdirs" variable, then the
1208// subdirectories listed are searched for Blueprints files returned in the
1209// subBlueprints return value.  If the Blueprints file contains an assignment
1210// to the "build" variable, then the file listed are returned in the
1211// subBlueprints return value.
1212//
1213// rootDir specifies the path to the root directory of the source tree, while
1214// filename specifies the path to the Blueprints file.  These paths are used for
1215// error reporting and for determining the module's directory.
1216func (c *Context) parseOne(rootDir, filename string, reader io.Reader,
1217	scope *parser.Scope, parent *fileParseContext) (file *parser.File, subBlueprints []fileParseContext, errs []error) {
1218
1219	relBlueprintsFile, err := filepath.Rel(rootDir, filename)
1220	if err != nil {
1221		return nil, nil, []error{err}
1222	}
1223
1224	scope.Remove("subdirs")
1225	scope.Remove("optional_subdirs")
1226	scope.Remove("build")
1227	file, errs = parser.ParseAndEval(filename, reader, scope)
1228	if len(errs) > 0 {
1229		for i, err := range errs {
1230			if parseErr, ok := err.(*parser.ParseError); ok {
1231				err = &BlueprintError{
1232					Err: parseErr.Err,
1233					Pos: parseErr.Pos,
1234				}
1235				errs[i] = err
1236			}
1237		}
1238
1239		// If there were any parse errors don't bother trying to interpret the
1240		// result.
1241		return nil, nil, errs
1242	}
1243	file.Name = relBlueprintsFile
1244
1245	build, buildPos, err := getLocalStringListFromScope(scope, "build")
1246	if err != nil {
1247		errs = append(errs, err)
1248	}
1249	for _, buildEntry := range build {
1250		if strings.Contains(buildEntry, "/") {
1251			errs = append(errs, &BlueprintError{
1252				Err: fmt.Errorf("illegal value %v. The '/' character is not permitted", buildEntry),
1253				Pos: buildPos,
1254			})
1255		}
1256	}
1257
1258	if err != nil {
1259		errs = append(errs, err)
1260	}
1261
1262	var blueprints []string
1263
1264	newBlueprints, newErrs := c.findBuildBlueprints(filepath.Dir(filename), build, buildPos)
1265	blueprints = append(blueprints, newBlueprints...)
1266	errs = append(errs, newErrs...)
1267
1268	subBlueprintsAndScope := make([]fileParseContext, len(blueprints))
1269	for i, b := range blueprints {
1270		subBlueprintsAndScope[i] = fileParseContext{b, parser.NewScope(scope), parent, make(chan struct{})}
1271	}
1272	return file, subBlueprintsAndScope, errs
1273}
1274
1275func (c *Context) findBuildBlueprints(dir string, build []string,
1276	buildPos scanner.Position) ([]string, []error) {
1277
1278	var blueprints []string
1279	var errs []error
1280
1281	for _, file := range build {
1282		pattern := filepath.Join(dir, file)
1283		var matches []string
1284		var err error
1285
1286		matches, err = c.glob(pattern, nil)
1287
1288		if err != nil {
1289			errs = append(errs, &BlueprintError{
1290				Err: fmt.Errorf("%q: %s", pattern, err.Error()),
1291				Pos: buildPos,
1292			})
1293			continue
1294		}
1295
1296		if len(matches) == 0 {
1297			errs = append(errs, &BlueprintError{
1298				Err: fmt.Errorf("%q: not found", pattern),
1299				Pos: buildPos,
1300			})
1301		}
1302
1303		for _, foundBlueprints := range matches {
1304			if strings.HasSuffix(foundBlueprints, "/") {
1305				errs = append(errs, &BlueprintError{
1306					Err: fmt.Errorf("%q: is a directory", foundBlueprints),
1307					Pos: buildPos,
1308				})
1309			}
1310			blueprints = append(blueprints, foundBlueprints)
1311		}
1312	}
1313
1314	return blueprints, errs
1315}
1316
1317func (c *Context) findSubdirBlueprints(dir string, subdirs []string, subdirsPos scanner.Position,
1318	subBlueprintsName string, optional bool) ([]string, []error) {
1319
1320	var blueprints []string
1321	var errs []error
1322
1323	for _, subdir := range subdirs {
1324		pattern := filepath.Join(dir, subdir, subBlueprintsName)
1325		var matches []string
1326		var err error
1327
1328		matches, err = c.glob(pattern, nil)
1329
1330		if err != nil {
1331			errs = append(errs, &BlueprintError{
1332				Err: fmt.Errorf("%q: %s", pattern, err.Error()),
1333				Pos: subdirsPos,
1334			})
1335			continue
1336		}
1337
1338		if len(matches) == 0 && !optional {
1339			errs = append(errs, &BlueprintError{
1340				Err: fmt.Errorf("%q: not found", pattern),
1341				Pos: subdirsPos,
1342			})
1343		}
1344
1345		for _, subBlueprints := range matches {
1346			if strings.HasSuffix(subBlueprints, "/") {
1347				errs = append(errs, &BlueprintError{
1348					Err: fmt.Errorf("%q: is a directory", subBlueprints),
1349					Pos: subdirsPos,
1350				})
1351			}
1352			blueprints = append(blueprints, subBlueprints)
1353		}
1354	}
1355
1356	return blueprints, errs
1357}
1358
1359func getLocalStringListFromScope(scope *parser.Scope, v string) ([]string, scanner.Position, error) {
1360	if assignment, local := scope.Get(v); assignment == nil || !local {
1361		return nil, scanner.Position{}, nil
1362	} else {
1363		switch value := assignment.Value.Eval().(type) {
1364		case *parser.List:
1365			ret := make([]string, 0, len(value.Values))
1366
1367			for _, listValue := range value.Values {
1368				s, ok := listValue.(*parser.String)
1369				if !ok {
1370					// The parser should not produce this.
1371					panic("non-string value found in list")
1372				}
1373
1374				ret = append(ret, s.Value)
1375			}
1376
1377			return ret, assignment.EqualsPos, nil
1378		case *parser.Bool, *parser.String:
1379			return nil, scanner.Position{}, &BlueprintError{
1380				Err: fmt.Errorf("%q must be a list of strings", v),
1381				Pos: assignment.EqualsPos,
1382			}
1383		default:
1384			panic(fmt.Errorf("unknown value type: %d", assignment.Value.Type()))
1385		}
1386	}
1387}
1388
1389func getStringFromScope(scope *parser.Scope, v string) (string, scanner.Position, error) {
1390	if assignment, _ := scope.Get(v); assignment == nil {
1391		return "", scanner.Position{}, nil
1392	} else {
1393		switch value := assignment.Value.Eval().(type) {
1394		case *parser.String:
1395			return value.Value, assignment.EqualsPos, nil
1396		case *parser.Bool, *parser.List:
1397			return "", scanner.Position{}, &BlueprintError{
1398				Err: fmt.Errorf("%q must be a string", v),
1399				Pos: assignment.EqualsPos,
1400			}
1401		default:
1402			panic(fmt.Errorf("unknown value type: %d", assignment.Value.Type()))
1403		}
1404	}
1405}
1406
1407// Clones a build logic module by calling the factory method for its module type, and then cloning
1408// property values.  Any values stored in the module object that are not stored in properties
1409// structs will be lost.
1410func (c *Context) cloneLogicModule(origModule *moduleInfo) (Module, []interface{}) {
1411	newLogicModule, newProperties := origModule.factory()
1412
1413	if len(newProperties) != len(origModule.properties) {
1414		panic("mismatched properties array length in " + origModule.Name())
1415	}
1416
1417	for i := range newProperties {
1418		dst := reflect.ValueOf(newProperties[i])
1419		src := reflect.ValueOf(origModule.properties[i])
1420
1421		proptools.CopyProperties(dst, src)
1422	}
1423
1424	return newLogicModule, newProperties
1425}
1426
1427func newVariant(module *moduleInfo, mutatorName string, variationName string,
1428	local bool) variant {
1429
1430	newVariantName := module.variant.name
1431	if variationName != "" {
1432		if newVariantName == "" {
1433			newVariantName = variationName
1434		} else {
1435			newVariantName += "_" + variationName
1436		}
1437	}
1438
1439	newVariations := module.variant.variations.clone()
1440	if newVariations == nil {
1441		newVariations = make(variationMap)
1442	}
1443	newVariations[mutatorName] = variationName
1444
1445	newDependencyVariations := module.variant.dependencyVariations.clone()
1446	if !local {
1447		if newDependencyVariations == nil {
1448			newDependencyVariations = make(variationMap)
1449		}
1450		newDependencyVariations[mutatorName] = variationName
1451	}
1452
1453	return variant{newVariantName, newVariations, newDependencyVariations}
1454}
1455
1456func (c *Context) createVariations(origModule *moduleInfo, mutator *mutatorInfo,
1457	depChooser depChooser, variationNames []string, local bool) (modulesOrAliases, []error) {
1458
1459	if len(variationNames) == 0 {
1460		panic(fmt.Errorf("mutator %q passed zero-length variation list for module %q",
1461			mutator.name, origModule.Name()))
1462	}
1463
1464	var newModules modulesOrAliases
1465
1466	var errs []error
1467
1468	for i, variationName := range variationNames {
1469		var newLogicModule Module
1470		var newProperties []interface{}
1471
1472		if i == 0 && mutator.transitionMutator == nil {
1473			// Reuse the existing module for the first new variant
1474			// This both saves creating a new module, and causes the insertion in c.moduleInfo below
1475			// with logicModule as the key to replace the original entry in c.moduleInfo
1476			newLogicModule, newProperties = origModule.logicModule, origModule.properties
1477		} else {
1478			newLogicModule, newProperties = c.cloneLogicModule(origModule)
1479		}
1480
1481		m := *origModule
1482		newModule := &m
1483		newModule.directDeps = slices.Clone(origModule.directDeps)
1484		newModule.reverseDeps = nil
1485		newModule.forwardDeps = nil
1486		newModule.logicModule = newLogicModule
1487		newModule.variant = newVariant(origModule, mutator.name, variationName, local)
1488		newModule.properties = newProperties
1489		newModule.providers = slices.Clone(origModule.providers)
1490		newModule.providerInitialValueHashes = slices.Clone(origModule.providerInitialValueHashes)
1491
1492		newModules = append(newModules, newModule)
1493
1494		newErrs := c.convertDepsToVariation(newModule, i, depChooser)
1495		if len(newErrs) > 0 {
1496			errs = append(errs, newErrs...)
1497		}
1498	}
1499
1500	// Mark original variant as invalid.  Modules that depend on this module will still
1501	// depend on origModule, but we'll fix it when the mutator is called on them.
1502	origModule.obsoletedByNewVariants = true
1503	origModule.splitModules = newModules
1504
1505	atomic.AddUint32(&c.depsModified, 1)
1506
1507	return newModules, errs
1508}
1509
1510type depChooser func(source *moduleInfo, variationIndex, depIndex int, dep depInfo) (*moduleInfo, string)
1511
1512func chooseDep(candidates modulesOrAliases, mutatorName, variationName string, defaultVariationName *string) (*moduleInfo, string) {
1513	for _, m := range candidates {
1514		if m.moduleOrAliasVariant().variations[mutatorName] == variationName {
1515			return m.moduleOrAliasTarget(), ""
1516		}
1517	}
1518
1519	if defaultVariationName != nil {
1520		// give it a second chance; match with defaultVariationName
1521		for _, m := range candidates {
1522			if m.moduleOrAliasVariant().variations[mutatorName] == *defaultVariationName {
1523				return m.moduleOrAliasTarget(), ""
1524			}
1525		}
1526	}
1527
1528	return nil, variationName
1529}
1530
1531func chooseDepByIndexes(mutatorName string, variations [][]string) depChooser {
1532	return func(source *moduleInfo, variationIndex, depIndex int, dep depInfo) (*moduleInfo, string) {
1533		desiredVariation := variations[variationIndex][depIndex]
1534		return chooseDep(dep.module.splitModules, mutatorName, desiredVariation, nil)
1535	}
1536}
1537
1538func chooseDepExplicit(mutatorName string,
1539	variationName string, defaultVariationName *string) depChooser {
1540	return func(source *moduleInfo, variationIndex, depIndex int, dep depInfo) (*moduleInfo, string) {
1541		return chooseDep(dep.module.splitModules, mutatorName, variationName, defaultVariationName)
1542	}
1543}
1544
1545func chooseDepInherit(mutatorName string, defaultVariationName *string) depChooser {
1546	return func(source *moduleInfo, variationIndex, depIndex int, dep depInfo) (*moduleInfo, string) {
1547		sourceVariation := source.variant.variations[mutatorName]
1548		return chooseDep(dep.module.splitModules, mutatorName, sourceVariation, defaultVariationName)
1549	}
1550}
1551
1552func (c *Context) convertDepsToVariation(module *moduleInfo, variationIndex int, depChooser depChooser) (errs []error) {
1553	for i, dep := range module.directDeps {
1554		if dep.module.obsoletedByNewVariants {
1555			newDep, missingVariation := depChooser(module, variationIndex, i, dep)
1556			if newDep == nil {
1557				errs = append(errs, &BlueprintError{
1558					Err: fmt.Errorf("failed to find variation %q for module %q needed by %q",
1559						missingVariation, dep.module.Name(), module.Name()),
1560					Pos: module.pos,
1561				})
1562				continue
1563			}
1564			module.directDeps[i].module = newDep
1565		}
1566	}
1567
1568	return errs
1569}
1570
1571func (c *Context) prettyPrintVariant(variations variationMap) string {
1572	names := make([]string, 0, len(variations))
1573	for _, m := range c.variantMutatorNames {
1574		if v, ok := variations[m]; ok {
1575			names = append(names, m+":"+v)
1576		}
1577	}
1578
1579	return strings.Join(names, ",")
1580}
1581
1582func (c *Context) prettyPrintGroupVariants(group *moduleGroup) string {
1583	var variants []string
1584	for _, moduleOrAlias := range group.modules {
1585		if mod := moduleOrAlias.module(); mod != nil {
1586			variants = append(variants, c.prettyPrintVariant(mod.variant.variations))
1587		} else if alias := moduleOrAlias.alias(); alias != nil {
1588			variants = append(variants, c.prettyPrintVariant(alias.variant.variations)+
1589				" (alias to "+c.prettyPrintVariant(alias.target.variant.variations)+")")
1590		}
1591	}
1592	return strings.Join(variants, "\n  ")
1593}
1594
1595func newModule(factory ModuleFactory) *moduleInfo {
1596	logicModule, properties := factory()
1597
1598	return &moduleInfo{
1599		logicModule: logicModule,
1600		factory:     factory,
1601		properties:  properties,
1602	}
1603}
1604
1605func processModuleDef(moduleDef *parser.Module,
1606	relBlueprintsFile string, moduleFactories, scopedModuleFactories map[string]ModuleFactory, ignoreUnknownModuleTypes bool) (*moduleInfo, []error) {
1607
1608	factory, ok := moduleFactories[moduleDef.Type]
1609	if !ok && scopedModuleFactories != nil {
1610		factory, ok = scopedModuleFactories[moduleDef.Type]
1611	}
1612	if !ok {
1613		if ignoreUnknownModuleTypes {
1614			return nil, nil
1615		}
1616
1617		return nil, []error{
1618			&BlueprintError{
1619				Err: fmt.Errorf("unrecognized module type %q", moduleDef.Type),
1620				Pos: moduleDef.TypePos,
1621			},
1622		}
1623	}
1624
1625	module := newModule(factory)
1626	module.typeName = moduleDef.Type
1627
1628	module.relBlueprintsFile = relBlueprintsFile
1629
1630	propertyMap, errs := proptools.UnpackProperties(moduleDef.Properties, module.properties...)
1631	if len(errs) > 0 {
1632		for i, err := range errs {
1633			if unpackErr, ok := err.(*proptools.UnpackError); ok {
1634				err = &BlueprintError{
1635					Err: unpackErr.Err,
1636					Pos: unpackErr.Pos,
1637				}
1638				errs[i] = err
1639			}
1640		}
1641		return nil, errs
1642	}
1643
1644	module.pos = moduleDef.TypePos
1645	module.propertyPos = make(map[string]scanner.Position)
1646	for name, propertyDef := range propertyMap {
1647		module.propertyPos[name] = propertyDef.ColonPos
1648	}
1649
1650	return module, nil
1651}
1652
1653func (c *Context) addModule(module *moduleInfo) []error {
1654	name := module.logicModule.Name()
1655	if name == "" {
1656		return []error{
1657			&BlueprintError{
1658				Err: fmt.Errorf("property 'name' is missing from a module"),
1659				Pos: module.pos,
1660			},
1661		}
1662	}
1663	c.moduleInfo[module.logicModule] = module
1664
1665	group := &moduleGroup{
1666		name:    name,
1667		modules: modulesOrAliases{module},
1668	}
1669	module.group = group
1670	namespace, errs := c.nameInterface.NewModule(
1671		newNamespaceContext(module),
1672		ModuleGroup{moduleGroup: group},
1673		module.logicModule)
1674	if len(errs) > 0 {
1675		for i := range errs {
1676			errs[i] = &BlueprintError{Err: errs[i], Pos: module.pos}
1677		}
1678		return errs
1679	}
1680	group.namespace = namespace
1681
1682	c.moduleGroups = append(c.moduleGroups, group)
1683
1684	return nil
1685}
1686
1687// ResolveDependencies checks that the dependencies specified by all of the
1688// modules defined in the parsed Blueprints files are valid.  This means that
1689// the modules depended upon are defined and that no circular dependencies
1690// exist.
1691func (c *Context) ResolveDependencies(config interface{}) (deps []string, errs []error) {
1692	c.BeginEvent("resolve_deps")
1693	defer c.EndEvent("resolve_deps")
1694	return c.resolveDependencies(c.Context, config)
1695}
1696
1697func (c *Context) resolveDependencies(ctx context.Context, config interface{}) (deps []string, errs []error) {
1698	pprof.Do(ctx, pprof.Labels("blueprint", "ResolveDependencies"), func(ctx context.Context) {
1699		c.initProviders()
1700
1701		c.liveGlobals = newLiveTracker(c, config)
1702
1703		errs = c.updateDependencies()
1704		if len(errs) > 0 {
1705			return
1706		}
1707
1708		deps, errs = c.runMutators(ctx, config)
1709		if len(errs) > 0 {
1710			return
1711		}
1712
1713		c.BeginEvent("clone_modules")
1714		if !c.SkipCloneModulesAfterMutators {
1715			c.cloneModules()
1716		}
1717		defer c.EndEvent("clone_modules")
1718
1719		c.clearTransitionMutatorInputVariants()
1720
1721		c.dependenciesReady = true
1722	})
1723
1724	if len(errs) > 0 {
1725		return nil, errs
1726	}
1727
1728	return deps, nil
1729}
1730
1731// Default dependencies handling.  If the module implements the (deprecated)
1732// DynamicDependerModule interface then this set consists of the union of those
1733// module names returned by its DynamicDependencies method and those added by calling
1734// AddDependencies or AddVariationDependencies on DynamicDependencyModuleContext.
1735func blueprintDepsMutator(ctx BottomUpMutatorContext) {
1736	if dynamicDepender, ok := ctx.Module().(DynamicDependerModule); ok {
1737		func() {
1738			defer func() {
1739				if r := recover(); r != nil {
1740					ctx.error(newPanicErrorf(r, "DynamicDependencies for %s", ctx.moduleInfo()))
1741				}
1742			}()
1743			dynamicDeps := dynamicDepender.DynamicDependencies(ctx)
1744
1745			if ctx.Failed() {
1746				return
1747			}
1748
1749			ctx.AddDependency(ctx.Module(), nil, dynamicDeps...)
1750		}()
1751	}
1752}
1753
1754// findExactVariantOrSingle searches the moduleGroup for a module with the same variant as module,
1755// and returns the matching module, or nil if one is not found.  A group with exactly one module
1756// is always considered matching.
1757func (c *Context) findExactVariantOrSingle(module *moduleInfo, config any, possible *moduleGroup, reverse bool) *moduleInfo {
1758	found, _ := c.findVariant(module, config, possible, nil, false, reverse)
1759	if found == nil {
1760		for _, moduleOrAlias := range possible.modules {
1761			if m := moduleOrAlias.module(); m != nil {
1762				if found != nil {
1763					// more than one possible match, give up
1764					return nil
1765				}
1766				found = m
1767			}
1768		}
1769	}
1770	return found
1771}
1772
1773func (c *Context) addDependency(module *moduleInfo, config any, tag DependencyTag, depName string) (*moduleInfo, []error) {
1774	if _, ok := tag.(BaseDependencyTag); ok {
1775		panic("BaseDependencyTag is not allowed to be used directly!")
1776	}
1777
1778	if depName == module.Name() {
1779		return nil, []error{&BlueprintError{
1780			Err: fmt.Errorf("%q depends on itself", depName),
1781			Pos: module.pos,
1782		}}
1783	}
1784
1785	possibleDeps := c.moduleGroupFromName(depName, module.namespace())
1786	if possibleDeps == nil {
1787		return nil, c.discoveredMissingDependencies(module, depName, nil)
1788	}
1789
1790	if m := c.findExactVariantOrSingle(module, config, possibleDeps, false); m != nil {
1791		module.newDirectDeps = append(module.newDirectDeps, depInfo{m, tag})
1792		atomic.AddUint32(&c.depsModified, 1)
1793		return m, nil
1794	}
1795
1796	if c.allowMissingDependencies {
1797		// Allow missing variants.
1798		return nil, c.discoveredMissingDependencies(module, depName, module.variant.dependencyVariations)
1799	}
1800
1801	return nil, []error{&BlueprintError{
1802		Err: fmt.Errorf("dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1803			depName, module.Name(),
1804			c.prettyPrintVariant(module.variant.dependencyVariations),
1805			c.prettyPrintGroupVariants(possibleDeps)),
1806		Pos: module.pos,
1807	}}
1808}
1809
1810func (c *Context) findReverseDependency(module *moduleInfo, config any, destName string) (*moduleInfo, []error) {
1811	if destName == module.Name() {
1812		return nil, []error{&BlueprintError{
1813			Err: fmt.Errorf("%q depends on itself", destName),
1814			Pos: module.pos,
1815		}}
1816	}
1817
1818	possibleDeps := c.moduleGroupFromName(destName, module.namespace())
1819	if possibleDeps == nil {
1820		return nil, []error{&BlueprintError{
1821			Err: fmt.Errorf("%q has a reverse dependency on undefined module %q",
1822				module.Name(), destName),
1823			Pos: module.pos,
1824		}}
1825	}
1826
1827	if m := c.findExactVariantOrSingle(module, config, possibleDeps, true); m != nil {
1828		return m, nil
1829	}
1830
1831	if c.allowMissingDependencies {
1832		// Allow missing variants.
1833		return module, c.discoveredMissingDependencies(module, destName, module.variant.dependencyVariations)
1834	}
1835
1836	return nil, []error{&BlueprintError{
1837		Err: fmt.Errorf("reverse dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1838			destName, module.Name(),
1839			c.prettyPrintVariant(module.variant.dependencyVariations),
1840			c.prettyPrintGroupVariants(possibleDeps)),
1841		Pos: module.pos,
1842	}}
1843}
1844
1845// applyTransitions takes a variationMap being used to add a dependency on a module in a moduleGroup
1846// and applies the OutgoingTransition and IncomingTransition methods of each completed TransitionMutator to
1847// modify the requested variation.  It finds a variant that existed before the TransitionMutator ran that is
1848// a subset of the requested variant to use as the module context for IncomingTransition.
1849func (c *Context) applyTransitions(config any, module *moduleInfo, group *moduleGroup, variant variationMap,
1850	requestedVariations []Variation) variationMap {
1851	for _, transitionMutator := range c.transitionMutators {
1852		// Apply the outgoing transition if it was not explicitly requested.
1853		explicitlyRequested := slices.ContainsFunc(requestedVariations, func(variation Variation) bool {
1854			return variation.Mutator == transitionMutator.name
1855		})
1856		sourceVariation := variant[transitionMutator.name]
1857		outgoingVariation := sourceVariation
1858		if !explicitlyRequested {
1859			ctx := &outgoingTransitionContextImpl{
1860				transitionContextImpl{context: c, source: module, dep: nil, depTag: nil, config: config},
1861			}
1862			outgoingVariation = transitionMutator.mutator.OutgoingTransition(ctx, sourceVariation)
1863		}
1864
1865		// Find an appropriate module to use as the context for the IncomingTransition.
1866		appliedIncomingTransition := false
1867		for _, inputVariant := range transitionMutator.inputVariants[group] {
1868			if inputVariant.variant.variations.subsetOf(variant) {
1869				// Apply the incoming transition.
1870				ctx := &incomingTransitionContextImpl{
1871					transitionContextImpl{context: c, source: nil, dep: inputVariant,
1872						depTag: nil, config: config},
1873				}
1874
1875				finalVariation := transitionMutator.mutator.IncomingTransition(ctx, outgoingVariation)
1876				if variant == nil {
1877					variant = make(variationMap)
1878				}
1879				variant[transitionMutator.name] = finalVariation
1880				appliedIncomingTransition = true
1881				break
1882			}
1883		}
1884		if !appliedIncomingTransition && !explicitlyRequested {
1885			// The transition mutator didn't apply anything to the target variant, remove the variation unless it
1886			// was explicitly requested when adding the dependency.
1887			delete(variant, transitionMutator.name)
1888		}
1889	}
1890
1891	return variant
1892}
1893
1894func (c *Context) findVariant(module *moduleInfo, config any,
1895	possibleDeps *moduleGroup, requestedVariations []Variation, far bool, reverse bool) (*moduleInfo, variationMap) {
1896
1897	// We can't just append variant.Variant to module.dependencyVariant.variantName and
1898	// compare the strings because the result won't be in mutator registration order.
1899	// Create a new map instead, and then deep compare the maps.
1900	var newVariant variationMap
1901	if !far {
1902		if !reverse {
1903			// For forward dependency, ignore local variants by matching against
1904			// dependencyVariant which doesn't have the local variants
1905			newVariant = module.variant.dependencyVariations.clone()
1906		} else {
1907			// For reverse dependency, use all the variants
1908			newVariant = module.variant.variations.clone()
1909		}
1910	}
1911	for _, v := range requestedVariations {
1912		if newVariant == nil {
1913			newVariant = make(variationMap)
1914		}
1915		newVariant[v.Mutator] = v.Variation
1916	}
1917
1918	newVariant = c.applyTransitions(config, module, possibleDeps, newVariant, requestedVariations)
1919
1920	check := func(variant variationMap) bool {
1921		if far {
1922			return newVariant.subsetOf(variant)
1923		} else {
1924			return variant.equal(newVariant)
1925		}
1926	}
1927
1928	var foundDep *moduleInfo
1929	for _, m := range possibleDeps.modules {
1930		if check(m.moduleOrAliasVariant().variations) {
1931			foundDep = m.moduleOrAliasTarget()
1932			break
1933		}
1934	}
1935
1936	return foundDep, newVariant
1937}
1938
1939func (c *Context) addVariationDependency(module *moduleInfo, config any, variations []Variation,
1940	tag DependencyTag, depName string, far bool) (*moduleInfo, []error) {
1941	if _, ok := tag.(BaseDependencyTag); ok {
1942		panic("BaseDependencyTag is not allowed to be used directly!")
1943	}
1944
1945	possibleDeps := c.moduleGroupFromName(depName, module.namespace())
1946	if possibleDeps == nil {
1947		return nil, c.discoveredMissingDependencies(module, depName, nil)
1948	}
1949
1950	foundDep, newVariant := c.findVariant(module, config, possibleDeps, variations, far, false)
1951
1952	if foundDep == nil {
1953		if c.allowMissingDependencies {
1954			// Allow missing variants.
1955			return nil, c.discoveredMissingDependencies(module, depName, newVariant)
1956		}
1957		return nil, []error{&BlueprintError{
1958			Err: fmt.Errorf("dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1959				depName, module.Name(),
1960				c.prettyPrintVariant(newVariant),
1961				c.prettyPrintGroupVariants(possibleDeps)),
1962			Pos: module.pos,
1963		}}
1964	}
1965
1966	if module == foundDep {
1967		return nil, []error{&BlueprintError{
1968			Err: fmt.Errorf("%q depends on itself", depName),
1969			Pos: module.pos,
1970		}}
1971	}
1972	// AddVariationDependency allows adding a dependency on itself, but only if
1973	// that module is earlier in the module list than this one, since we always
1974	// run GenerateBuildActions in order for the variants of a module
1975	if foundDep.group == module.group && beforeInModuleList(module, foundDep, module.group.modules) {
1976		return nil, []error{&BlueprintError{
1977			Err: fmt.Errorf("%q depends on later version of itself", depName),
1978			Pos: module.pos,
1979		}}
1980	}
1981	module.newDirectDeps = append(module.newDirectDeps, depInfo{foundDep, tag})
1982	atomic.AddUint32(&c.depsModified, 1)
1983	return foundDep, nil
1984}
1985
1986func (c *Context) addInterVariantDependency(origModule *moduleInfo, tag DependencyTag,
1987	from, to Module) *moduleInfo {
1988	if _, ok := tag.(BaseDependencyTag); ok {
1989		panic("BaseDependencyTag is not allowed to be used directly!")
1990	}
1991
1992	var fromInfo, toInfo *moduleInfo
1993	for _, moduleOrAlias := range origModule.splitModules {
1994		if m := moduleOrAlias.module(); m != nil {
1995			if m.logicModule == from {
1996				fromInfo = m
1997			}
1998			if m.logicModule == to {
1999				toInfo = m
2000				if fromInfo != nil {
2001					panic(fmt.Errorf("%q depends on later version of itself", origModule.Name()))
2002				}
2003			}
2004		}
2005	}
2006
2007	if fromInfo == nil || toInfo == nil {
2008		panic(fmt.Errorf("AddInterVariantDependency called for module %q on invalid variant",
2009			origModule.Name()))
2010	}
2011
2012	fromInfo.newDirectDeps = append(fromInfo.newDirectDeps, depInfo{toInfo, tag})
2013	atomic.AddUint32(&c.depsModified, 1)
2014	return toInfo
2015}
2016
2017// findBlueprintDescendants returns a map linking parent Blueprint files to child Blueprints files
2018// For example, if paths = []string{"a/b/c/Android.bp", "a/Android.bp"},
2019// then descendants = {"":[]string{"a/Android.bp"}, "a/Android.bp":[]string{"a/b/c/Android.bp"}}
2020func findBlueprintDescendants(paths []string) (descendants map[string][]string, err error) {
2021	// make mapping from dir path to file path
2022	filesByDir := make(map[string]string, len(paths))
2023	for _, path := range paths {
2024		dir := filepath.Dir(path)
2025		_, alreadyFound := filesByDir[dir]
2026		if alreadyFound {
2027			return nil, fmt.Errorf("Found two Blueprint files in directory %v : %v and %v", dir, filesByDir[dir], path)
2028		}
2029		filesByDir[dir] = path
2030	}
2031
2032	findAncestor := func(childFile string) (ancestor string) {
2033		prevAncestorDir := filepath.Dir(childFile)
2034		for {
2035			ancestorDir := filepath.Dir(prevAncestorDir)
2036			if ancestorDir == prevAncestorDir {
2037				// reached the root dir without any matches; assign this as a descendant of ""
2038				return ""
2039			}
2040
2041			ancestorFile, ancestorExists := filesByDir[ancestorDir]
2042			if ancestorExists {
2043				return ancestorFile
2044			}
2045			prevAncestorDir = ancestorDir
2046		}
2047	}
2048	// generate the descendants map
2049	descendants = make(map[string][]string, len(filesByDir))
2050	for _, childFile := range filesByDir {
2051		ancestorFile := findAncestor(childFile)
2052		descendants[ancestorFile] = append(descendants[ancestorFile], childFile)
2053	}
2054	return descendants, nil
2055}
2056
2057type visitOrderer interface {
2058	// returns the number of modules that this module needs to wait for
2059	waitCount(module *moduleInfo) int
2060	// returns the list of modules that are waiting for this module
2061	propagate(module *moduleInfo) []*moduleInfo
2062	// visit modules in order
2063	visit(modules []*moduleInfo, visit func(*moduleInfo, chan<- pauseSpec) bool)
2064}
2065
2066type unorderedVisitorImpl struct{}
2067
2068func (unorderedVisitorImpl) waitCount(module *moduleInfo) int {
2069	return 0
2070}
2071
2072func (unorderedVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
2073	return nil
2074}
2075
2076func (unorderedVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo, chan<- pauseSpec) bool) {
2077	for _, module := range modules {
2078		if visit(module, nil) {
2079			return
2080		}
2081	}
2082}
2083
2084type bottomUpVisitorImpl struct{}
2085
2086func (bottomUpVisitorImpl) waitCount(module *moduleInfo) int {
2087	return len(module.forwardDeps)
2088}
2089
2090func (bottomUpVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
2091	return module.reverseDeps
2092}
2093
2094func (bottomUpVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo, chan<- pauseSpec) bool) {
2095	for _, module := range modules {
2096		if visit(module, nil) {
2097			return
2098		}
2099	}
2100}
2101
2102type topDownVisitorImpl struct{}
2103
2104func (topDownVisitorImpl) waitCount(module *moduleInfo) int {
2105	return len(module.reverseDeps)
2106}
2107
2108func (topDownVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
2109	return module.forwardDeps
2110}
2111
2112func (topDownVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo, chan<- pauseSpec) bool) {
2113	for i := 0; i < len(modules); i++ {
2114		module := modules[len(modules)-1-i]
2115		if visit(module, nil) {
2116			return
2117		}
2118	}
2119}
2120
2121var (
2122	bottomUpVisitor bottomUpVisitorImpl
2123	topDownVisitor  topDownVisitorImpl
2124)
2125
2126// pauseSpec describes a pause that a module needs to occur until another module has been visited,
2127// at which point the unpause channel will be closed.
2128type pauseSpec struct {
2129	paused  *moduleInfo
2130	until   *moduleInfo
2131	unpause unpause
2132}
2133
2134type unpause chan struct{}
2135
2136const parallelVisitLimit = 1000
2137
2138// Calls visit on each module, guaranteeing that visit is not called on a module until visit on all
2139// of its dependencies has finished.  A visit function can write a pauseSpec to the pause channel
2140// to wait for another dependency to be visited.  If a visit function returns true to cancel
2141// while another visitor is paused, the paused visitor will never be resumed and its goroutine
2142// will stay paused forever.
2143func parallelVisit(modules []*moduleInfo, order visitOrderer, limit int,
2144	visit func(module *moduleInfo, pause chan<- pauseSpec) bool) []error {
2145
2146	doneCh := make(chan *moduleInfo)
2147	cancelCh := make(chan bool)
2148	pauseCh := make(chan pauseSpec)
2149	cancel := false
2150
2151	var backlog []*moduleInfo      // Visitors that are ready to start but backlogged due to limit.
2152	var unpauseBacklog []pauseSpec // Visitors that are ready to unpause but backlogged due to limit.
2153
2154	active := 0  // Number of visitors running, not counting paused visitors.
2155	visited := 0 // Number of finished visitors.
2156
2157	pauseMap := make(map[*moduleInfo][]pauseSpec)
2158
2159	for _, module := range modules {
2160		module.waitingCount = order.waitCount(module)
2161	}
2162
2163	// Call the visitor on a module if there are fewer active visitors than the parallelism
2164	// limit, otherwise add it to the backlog.
2165	startOrBacklog := func(module *moduleInfo) {
2166		if active < limit {
2167			active++
2168			go func() {
2169				ret := visit(module, pauseCh)
2170				if ret {
2171					cancelCh <- true
2172				}
2173				doneCh <- module
2174			}()
2175		} else {
2176			backlog = append(backlog, module)
2177		}
2178	}
2179
2180	// Unpause the already-started but paused  visitor on a module if there are fewer active
2181	// visitors than the parallelism limit, otherwise add it to the backlog.
2182	unpauseOrBacklog := func(pauseSpec pauseSpec) {
2183		if active < limit {
2184			active++
2185			close(pauseSpec.unpause)
2186		} else {
2187			unpauseBacklog = append(unpauseBacklog, pauseSpec)
2188		}
2189	}
2190
2191	// Start any modules in the backlog up to the parallelism limit.  Unpause paused modules first
2192	// since they may already be holding resources.
2193	unpauseOrStartFromBacklog := func() {
2194		for active < limit && len(unpauseBacklog) > 0 {
2195			unpause := unpauseBacklog[0]
2196			unpauseBacklog = unpauseBacklog[1:]
2197			unpauseOrBacklog(unpause)
2198		}
2199		for active < limit && len(backlog) > 0 {
2200			toVisit := backlog[0]
2201			backlog = backlog[1:]
2202			startOrBacklog(toVisit)
2203		}
2204	}
2205
2206	toVisit := len(modules)
2207
2208	// Start or backlog any modules that are not waiting for any other modules.
2209	for _, module := range modules {
2210		if module.waitingCount == 0 {
2211			startOrBacklog(module)
2212		}
2213	}
2214
2215	for active > 0 {
2216		select {
2217		case <-cancelCh:
2218			cancel = true
2219			backlog = nil
2220		case doneModule := <-doneCh:
2221			active--
2222			if !cancel {
2223				// Mark this module as done.
2224				doneModule.waitingCount = -1
2225				visited++
2226
2227				// Unpause or backlog any modules that were waiting for this one.
2228				if unpauses, ok := pauseMap[doneModule]; ok {
2229					delete(pauseMap, doneModule)
2230					for _, unpause := range unpauses {
2231						unpauseOrBacklog(unpause)
2232					}
2233				}
2234
2235				// Start any backlogged modules up to limit.
2236				unpauseOrStartFromBacklog()
2237
2238				// Decrement waitingCount on the next modules in the tree based
2239				// on propagation order, and start or backlog them if they are
2240				// ready to start.
2241				for _, module := range order.propagate(doneModule) {
2242					module.waitingCount--
2243					if module.waitingCount == 0 {
2244						startOrBacklog(module)
2245					}
2246				}
2247			}
2248		case pauseSpec := <-pauseCh:
2249			if pauseSpec.until.waitingCount == -1 {
2250				// Module being paused for is already finished, resume immediately.
2251				close(pauseSpec.unpause)
2252			} else {
2253				// Register for unpausing.
2254				pauseMap[pauseSpec.until] = append(pauseMap[pauseSpec.until], pauseSpec)
2255
2256				// Don't count paused visitors as active so that this can't deadlock
2257				// if 1000 visitors are paused simultaneously.
2258				active--
2259				unpauseOrStartFromBacklog()
2260			}
2261		}
2262	}
2263
2264	if !cancel {
2265		// Invariant check: no backlogged modules, these weren't waiting on anything except
2266		// the parallelism limit so they should have run.
2267		if len(backlog) > 0 {
2268			panic(fmt.Errorf("parallelVisit finished with %d backlogged visitors", len(backlog)))
2269		}
2270
2271		// Invariant check: no backlogged paused modules, these weren't waiting on anything
2272		// except the parallelism limit so they should have run.
2273		if len(unpauseBacklog) > 0 {
2274			panic(fmt.Errorf("parallelVisit finished with %d backlogged unpaused visitors", len(unpauseBacklog)))
2275		}
2276
2277		if len(pauseMap) > 0 {
2278			// Probably a deadlock due to a newly added dependency cycle. Start from each module in
2279			// the order of the input modules list and perform a depth-first search for the module
2280			// it is paused on, ignoring modules that are marked as done.  Note this traverses from
2281			// modules to the modules that would have been unblocked when that module finished, i.e
2282			// the reverse of the visitOrderer.
2283
2284			// In order to reduce duplicated work, once a module has been checked and determined
2285			// not to be part of a cycle add it and everything that depends on it to the checked
2286			// map.
2287			checked := make(map[*moduleInfo]struct{})
2288
2289			var check func(module, end *moduleInfo) []*moduleInfo
2290			check = func(module, end *moduleInfo) []*moduleInfo {
2291				if module.waitingCount == -1 {
2292					// This module was finished, it can't be part of a loop.
2293					return nil
2294				}
2295				if module == end {
2296					// This module is the end of the loop, start rolling up the cycle.
2297					return []*moduleInfo{module}
2298				}
2299
2300				if _, alreadyChecked := checked[module]; alreadyChecked {
2301					return nil
2302				}
2303
2304				for _, dep := range order.propagate(module) {
2305					cycle := check(dep, end)
2306					if cycle != nil {
2307						return append([]*moduleInfo{module}, cycle...)
2308					}
2309				}
2310				for _, depPauseSpec := range pauseMap[module] {
2311					cycle := check(depPauseSpec.paused, end)
2312					if cycle != nil {
2313						return append([]*moduleInfo{module}, cycle...)
2314					}
2315				}
2316
2317				checked[module] = struct{}{}
2318				return nil
2319			}
2320
2321			// Iterate over the modules list instead of pauseMap to provide deterministic ordering.
2322			for _, module := range modules {
2323				for _, pauseSpec := range pauseMap[module] {
2324					cycle := check(pauseSpec.paused, pauseSpec.until)
2325					if len(cycle) > 0 {
2326						return cycleError(cycle)
2327					}
2328				}
2329			}
2330		}
2331
2332		// Invariant check: if there was no deadlock and no cancellation every module
2333		// should have been visited.
2334		if visited != toVisit {
2335			panic(fmt.Errorf("parallelVisit ran %d visitors, expected %d", visited, toVisit))
2336		}
2337
2338		// Invariant check: if there was no deadlock and no cancellation  every module
2339		// should have been visited, so there is nothing left to be paused on.
2340		if len(pauseMap) > 0 {
2341			panic(fmt.Errorf("parallelVisit finished with %d paused visitors", len(pauseMap)))
2342		}
2343	}
2344
2345	return nil
2346}
2347
2348func cycleError(cycle []*moduleInfo) (errs []error) {
2349	// The cycle list is in reverse order because all the 'check' calls append
2350	// their own module to the list.
2351	errs = append(errs, &BlueprintError{
2352		Err: fmt.Errorf("encountered dependency cycle:"),
2353		Pos: cycle[len(cycle)-1].pos,
2354	})
2355
2356	// Iterate backwards through the cycle list.
2357	curModule := cycle[0]
2358	for i := len(cycle) - 1; i >= 0; i-- {
2359		nextModule := cycle[i]
2360		errs = append(errs, &BlueprintError{
2361			Err: fmt.Errorf("    %s depends on %s",
2362				curModule, nextModule),
2363			Pos: curModule.pos,
2364		})
2365		curModule = nextModule
2366	}
2367
2368	return errs
2369}
2370
2371// updateDependencies recursively walks the module dependency graph and updates
2372// additional fields based on the dependencies.  It builds a sorted list of modules
2373// such that dependencies of a module always appear first, and populates reverse
2374// dependency links and counts of total dependencies.  It also reports errors when
2375// it encounters dependency cycles.  This should be called after resolveDependencies,
2376// as well as after any mutator pass has called addDependency
2377func (c *Context) updateDependencies() (errs []error) {
2378	c.cachedDepsModified = true
2379	visited := make(map[*moduleInfo]bool)  // modules that were already checked
2380	checking := make(map[*moduleInfo]bool) // modules actively being checked
2381
2382	sorted := make([]*moduleInfo, 0, len(c.moduleInfo))
2383
2384	var check func(group *moduleInfo) []*moduleInfo
2385
2386	check = func(module *moduleInfo) []*moduleInfo {
2387		visited[module] = true
2388		checking[module] = true
2389		defer delete(checking, module)
2390
2391		// Reset the forward and reverse deps without reducing their capacity to avoid reallocation.
2392		module.reverseDeps = module.reverseDeps[:0]
2393		module.forwardDeps = module.forwardDeps[:0]
2394
2395		// Add an implicit dependency ordering on all earlier modules in the same module group
2396		for _, dep := range module.group.modules {
2397			if dep == module {
2398				break
2399			}
2400			if depModule := dep.module(); depModule != nil {
2401				module.forwardDeps = append(module.forwardDeps, depModule)
2402			}
2403		}
2404
2405	outer:
2406		for _, dep := range module.directDeps {
2407			// use a loop to check for duplicates, average number of directDeps measured to be 9.5.
2408			for _, exists := range module.forwardDeps {
2409				if dep.module == exists {
2410					continue outer
2411				}
2412			}
2413			module.forwardDeps = append(module.forwardDeps, dep.module)
2414		}
2415
2416		for _, dep := range module.forwardDeps {
2417			if checking[dep] {
2418				// This is a cycle.
2419				return []*moduleInfo{dep, module}
2420			}
2421
2422			if !visited[dep] {
2423				cycle := check(dep)
2424				if cycle != nil {
2425					if cycle[0] == module {
2426						// We are the "start" of the cycle, so we're responsible
2427						// for generating the errors.
2428						errs = append(errs, cycleError(cycle)...)
2429
2430						// We can continue processing this module's children to
2431						// find more cycles.  Since all the modules that were
2432						// part of the found cycle were marked as visited we
2433						// won't run into that cycle again.
2434					} else {
2435						// We're not the "start" of the cycle, so we just append
2436						// our module to the list and return it.
2437						return append(cycle, module)
2438					}
2439				}
2440			}
2441
2442			dep.reverseDeps = append(dep.reverseDeps, module)
2443		}
2444
2445		sorted = append(sorted, module)
2446
2447		return nil
2448	}
2449
2450	for _, module := range c.moduleInfo {
2451		if !visited[module] {
2452			cycle := check(module)
2453			if cycle != nil {
2454				if cycle[len(cycle)-1] != module {
2455					panic("inconceivable!")
2456				}
2457				errs = append(errs, cycleError(cycle)...)
2458			}
2459		}
2460	}
2461
2462	c.modulesSorted = sorted
2463
2464	return
2465}
2466
2467type jsonVariations []Variation
2468
2469type jsonModuleName struct {
2470	Name                 string
2471	Variant              string
2472	Variations           jsonVariations
2473	DependencyVariations jsonVariations
2474}
2475
2476type jsonDep struct {
2477	jsonModuleName
2478	Tag string
2479}
2480
2481type JsonModule struct {
2482	jsonModuleName
2483	Deps      []jsonDep
2484	Type      string
2485	Blueprint string
2486	CreatedBy *string
2487	Module    map[string]interface{}
2488}
2489
2490func toJsonVariationMap(vm variationMap) jsonVariations {
2491	m := make(jsonVariations, 0, len(vm))
2492	for k, v := range vm {
2493		m = append(m, Variation{k, v})
2494	}
2495	sort.Slice(m, func(i, j int) bool {
2496		if m[i].Mutator != m[j].Mutator {
2497			return m[i].Mutator < m[j].Mutator
2498		}
2499		return m[i].Variation < m[j].Variation
2500	})
2501	return m
2502}
2503
2504func jsonModuleNameFromModuleInfo(m *moduleInfo) *jsonModuleName {
2505	return &jsonModuleName{
2506		Name:                 m.Name(),
2507		Variant:              m.variant.name,
2508		Variations:           toJsonVariationMap(m.variant.variations),
2509		DependencyVariations: toJsonVariationMap(m.variant.dependencyVariations),
2510	}
2511}
2512
2513type JSONDataSupplier interface {
2514	AddJSONData(d *map[string]interface{})
2515}
2516
2517// JSONAction contains the action-related info we expose to json module graph
2518type JSONAction struct {
2519	Inputs  []string
2520	Outputs []string
2521	Desc    string
2522}
2523
2524// JSONActionSupplier allows JSON representation of additional actions that are not registered in
2525// Ninja
2526type JSONActionSupplier interface {
2527	JSONActions() []JSONAction
2528}
2529
2530func jsonModuleFromModuleInfo(m *moduleInfo) *JsonModule {
2531	result := &JsonModule{
2532		jsonModuleName: *jsonModuleNameFromModuleInfo(m),
2533		Deps:           make([]jsonDep, 0),
2534		Type:           m.typeName,
2535		Blueprint:      m.relBlueprintsFile,
2536		Module:         make(map[string]interface{}),
2537	}
2538	if m.createdBy != nil {
2539		n := m.createdBy.Name()
2540		result.CreatedBy = &n
2541	}
2542	if j, ok := m.logicModule.(JSONDataSupplier); ok {
2543		j.AddJSONData(&result.Module)
2544	}
2545	for _, p := range m.providers {
2546		if j, ok := p.(JSONDataSupplier); ok {
2547			j.AddJSONData(&result.Module)
2548		}
2549	}
2550	return result
2551}
2552
2553func jsonModuleWithActionsFromModuleInfo(m *moduleInfo, nameTracker *nameTracker) *JsonModule {
2554	result := &JsonModule{
2555		jsonModuleName: jsonModuleName{
2556			Name:    m.Name(),
2557			Variant: m.variant.name,
2558		},
2559		Deps:      make([]jsonDep, 0),
2560		Type:      m.typeName,
2561		Blueprint: m.relBlueprintsFile,
2562		Module:    make(map[string]interface{}),
2563	}
2564	var actions []JSONAction
2565	for _, bDef := range m.actionDefs.buildDefs {
2566		a := JSONAction{
2567			Inputs: append(append(append(
2568				bDef.InputStrings,
2569				bDef.ImplicitStrings...),
2570				getNinjaStrings(bDef.Inputs, nameTracker)...),
2571				getNinjaStrings(bDef.Implicits, nameTracker)...),
2572
2573			Outputs: append(append(append(
2574				bDef.OutputStrings,
2575				bDef.ImplicitOutputStrings...),
2576				getNinjaStrings(bDef.Outputs, nameTracker)...),
2577				getNinjaStrings(bDef.ImplicitOutputs, nameTracker)...),
2578		}
2579		if d, ok := bDef.Variables["description"]; ok {
2580			a.Desc = d.Value(nameTracker)
2581		}
2582		actions = append(actions, a)
2583	}
2584
2585	if j, ok := m.logicModule.(JSONActionSupplier); ok {
2586		actions = append(actions, j.JSONActions()...)
2587	}
2588	for _, p := range m.providers {
2589		if j, ok := p.(JSONActionSupplier); ok {
2590			actions = append(actions, j.JSONActions()...)
2591		}
2592	}
2593
2594	result.Module["Actions"] = actions
2595	return result
2596}
2597
2598// Gets a list of strings from the given list of ninjaStrings by invoking ninjaString.Value on each.
2599func getNinjaStrings(nStrs []*ninjaString, nameTracker *nameTracker) []string {
2600	var strs []string
2601	for _, nstr := range nStrs {
2602		strs = append(strs, nstr.Value(nameTracker))
2603	}
2604	return strs
2605}
2606
2607func (c *Context) GetWeightedOutputsFromPredicate(predicate func(*JsonModule) (bool, int)) map[string]int {
2608	outputToWeight := make(map[string]int)
2609	for _, m := range c.modulesSorted {
2610		jmWithActions := jsonModuleWithActionsFromModuleInfo(m, c.nameTracker)
2611		if ok, weight := predicate(jmWithActions); ok {
2612			for _, a := range jmWithActions.Module["Actions"].([]JSONAction) {
2613				for _, o := range a.Outputs {
2614					if val, ok := outputToWeight[o]; ok {
2615						if val > weight {
2616							continue
2617						}
2618					}
2619					outputToWeight[o] = weight
2620				}
2621			}
2622		}
2623	}
2624	return outputToWeight
2625}
2626
2627func inList(s string, l []string) bool {
2628	for _, element := range l {
2629		if s == element {
2630			return true
2631		}
2632	}
2633	return false
2634}
2635
2636// PrintJSONGraph prints info of modules in a JSON file.
2637func (c *Context) PrintJSONGraphAndActions(wGraph io.Writer, wActions io.Writer) {
2638	modulesToGraph := make([]*JsonModule, 0)
2639	modulesToActions := make([]*JsonModule, 0)
2640	for _, m := range c.modulesSorted {
2641		jm := jsonModuleFromModuleInfo(m)
2642		jmWithActions := jsonModuleWithActionsFromModuleInfo(m, c.nameTracker)
2643		for _, d := range m.directDeps {
2644			jm.Deps = append(jm.Deps, jsonDep{
2645				jsonModuleName: *jsonModuleNameFromModuleInfo(d.module),
2646				Tag:            fmt.Sprintf("%T %+v", d.tag, d.tag),
2647			})
2648			jmWithActions.Deps = append(jmWithActions.Deps, jsonDep{
2649				jsonModuleName: jsonModuleName{
2650					Name: d.module.Name(),
2651				},
2652			})
2653
2654		}
2655		modulesToGraph = append(modulesToGraph, jm)
2656		modulesToActions = append(modulesToActions, jmWithActions)
2657	}
2658	writeJson(wGraph, modulesToGraph)
2659	writeJson(wActions, modulesToActions)
2660}
2661
2662func writeJson(w io.Writer, modules []*JsonModule) {
2663	e := json.NewEncoder(w)
2664	e.SetIndent("", "\t")
2665	e.Encode(modules)
2666}
2667
2668// PrepareBuildActions generates an internal representation of all the build
2669// actions that need to be performed.  This process involves invoking the
2670// GenerateBuildActions method on each of the Module objects created during the
2671// parse phase and then on each of the registered Singleton objects.
2672//
2673// If the ResolveDependencies method has not already been called it is called
2674// automatically by this method.
2675//
2676// The config argument is made available to all of the Module and Singleton
2677// objects via the Config method on the ModuleContext and SingletonContext
2678// objects passed to GenerateBuildActions.  It is also passed to the functions
2679// specified via PoolFunc, RuleFunc, and VariableFunc so that they can compute
2680// config-specific values.
2681//
2682// The returned deps is a list of the ninja files dependencies that were added
2683// by the modules and singletons via the ModuleContext.AddNinjaFileDeps(),
2684// SingletonContext.AddNinjaFileDeps(), and PackageContext.AddNinjaFileDeps()
2685// methods.
2686
2687func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs []error) {
2688	c.BeginEvent("prepare_build_actions")
2689	defer c.EndEvent("prepare_build_actions")
2690	pprof.Do(c.Context, pprof.Labels("blueprint", "PrepareBuildActions"), func(ctx context.Context) {
2691		c.buildActionsReady = false
2692
2693		if !c.dependenciesReady {
2694			var extraDeps []string
2695			extraDeps, errs = c.resolveDependencies(ctx, config)
2696			if len(errs) > 0 {
2697				return
2698			}
2699			deps = append(deps, extraDeps...)
2700		}
2701
2702		var depsModules []string
2703		depsModules, errs = c.generateModuleBuildActions(config, c.liveGlobals)
2704		if len(errs) > 0 {
2705			return
2706		}
2707
2708		var depsSingletons []string
2709		depsSingletons, errs = c.generateSingletonBuildActions(config, c.singletonInfo, c.liveGlobals)
2710		if len(errs) > 0 {
2711			return
2712		}
2713
2714		deps = append(deps, depsModules...)
2715		deps = append(deps, depsSingletons...)
2716
2717		if c.outDir != nil {
2718			err := c.liveGlobals.addNinjaStringDeps(c.outDir)
2719			if err != nil {
2720				errs = []error{err}
2721				return
2722			}
2723		}
2724
2725		pkgNames, depsPackages := c.makeUniquePackageNames(c.liveGlobals)
2726
2727		deps = append(deps, depsPackages...)
2728
2729		nameTracker := c.memoizeFullNames(c.liveGlobals, pkgNames)
2730
2731		// This will panic if it finds a problem since it's a programming error.
2732		c.checkForVariableReferenceCycles(c.liveGlobals.variables, nameTracker)
2733
2734		c.nameTracker = nameTracker
2735		c.globalVariables = c.liveGlobals.variables
2736		c.globalPools = c.liveGlobals.pools
2737		c.globalRules = c.liveGlobals.rules
2738
2739		c.buildActionsReady = true
2740	})
2741
2742	if len(errs) > 0 {
2743		return nil, errs
2744	}
2745
2746	return deps, nil
2747}
2748
2749func (c *Context) runMutators(ctx context.Context, config interface{}) (deps []string, errs []error) {
2750	pprof.Do(ctx, pprof.Labels("blueprint", "runMutators"), func(ctx context.Context) {
2751		for _, mutator := range c.mutatorInfo {
2752			pprof.Do(ctx, pprof.Labels("mutator", mutator.name), func(context.Context) {
2753				c.BeginEvent(mutator.name)
2754				defer c.EndEvent(mutator.name)
2755				var newDeps []string
2756				if mutator.topDownMutator != nil {
2757					newDeps, errs = c.runMutator(config, mutator, topDownMutator)
2758				} else if mutator.bottomUpMutator != nil {
2759					newDeps, errs = c.runMutator(config, mutator, bottomUpMutator)
2760				} else {
2761					panic("no mutator set on " + mutator.name)
2762				}
2763				if len(errs) > 0 {
2764					return
2765				}
2766				deps = append(deps, newDeps...)
2767			})
2768			if len(errs) > 0 {
2769				return
2770			}
2771		}
2772	})
2773
2774	if len(errs) > 0 {
2775		return nil, errs
2776	}
2777
2778	return deps, nil
2779}
2780
2781type mutatorDirection interface {
2782	run(mutator *mutatorInfo, ctx *mutatorContext)
2783	orderer() visitOrderer
2784	fmt.Stringer
2785}
2786
2787type bottomUpMutatorImpl struct{}
2788
2789func (bottomUpMutatorImpl) run(mutator *mutatorInfo, ctx *mutatorContext) {
2790	mutator.bottomUpMutator(ctx)
2791}
2792
2793func (bottomUpMutatorImpl) orderer() visitOrderer {
2794	return bottomUpVisitor
2795}
2796
2797func (bottomUpMutatorImpl) String() string {
2798	return "bottom up mutator"
2799}
2800
2801type topDownMutatorImpl struct{}
2802
2803func (topDownMutatorImpl) run(mutator *mutatorInfo, ctx *mutatorContext) {
2804	mutator.topDownMutator(ctx)
2805}
2806
2807func (topDownMutatorImpl) orderer() visitOrderer {
2808	return topDownVisitor
2809}
2810
2811func (topDownMutatorImpl) String() string {
2812	return "top down mutator"
2813}
2814
2815var (
2816	topDownMutator  topDownMutatorImpl
2817	bottomUpMutator bottomUpMutatorImpl
2818)
2819
2820type reverseDep struct {
2821	module *moduleInfo
2822	dep    depInfo
2823}
2824
2825func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
2826	direction mutatorDirection) (deps []string, errs []error) {
2827
2828	newModuleInfo := make(map[Module]*moduleInfo)
2829	for k, v := range c.moduleInfo {
2830		newModuleInfo[k] = v
2831	}
2832
2833	type globalStateChange struct {
2834		reverse    []reverseDep
2835		rename     []rename
2836		replace    []replace
2837		newModules []*moduleInfo
2838		deps       []string
2839	}
2840
2841	type newVariationPair struct {
2842		newVariations   modulesOrAliases
2843		origLogicModule Module
2844	}
2845
2846	reverseDeps := make(map[*moduleInfo][]depInfo)
2847	var rename []rename
2848	var replace []replace
2849	var newModules []*moduleInfo
2850
2851	errsCh := make(chan []error)
2852	globalStateCh := make(chan globalStateChange)
2853	newVariationsCh := make(chan newVariationPair)
2854	done := make(chan bool)
2855
2856	c.depsModified = 0
2857
2858	visit := func(module *moduleInfo, pause chan<- pauseSpec) bool {
2859		if module.splitModules != nil {
2860			panic("split module found in sorted module list")
2861		}
2862
2863		mctx := &mutatorContext{
2864			baseModuleContext: baseModuleContext{
2865				context: c,
2866				config:  config,
2867				module:  module,
2868			},
2869			mutator: mutator,
2870			pauseCh: pause,
2871		}
2872
2873		origLogicModule := module.logicModule
2874
2875		module.startedMutator = mutator
2876
2877		func() {
2878			defer func() {
2879				if r := recover(); r != nil {
2880					in := fmt.Sprintf("%s %q for %s", direction, mutator.name, module)
2881					if err, ok := r.(panicError); ok {
2882						err.addIn(in)
2883						mctx.error(err)
2884					} else {
2885						mctx.error(newPanicErrorf(r, in))
2886					}
2887				}
2888			}()
2889			direction.run(mutator, mctx)
2890		}()
2891
2892		module.finishedMutator = mutator
2893
2894		if len(mctx.errs) > 0 {
2895			errsCh <- mctx.errs
2896			return true
2897		}
2898
2899		if len(mctx.newVariations) > 0 {
2900			newVariationsCh <- newVariationPair{mctx.newVariations, origLogicModule}
2901		}
2902
2903		if len(mctx.reverseDeps) > 0 || len(mctx.replace) > 0 || len(mctx.rename) > 0 || len(mctx.newModules) > 0 || len(mctx.ninjaFileDeps) > 0 {
2904			globalStateCh <- globalStateChange{
2905				reverse:    mctx.reverseDeps,
2906				replace:    mctx.replace,
2907				rename:     mctx.rename,
2908				newModules: mctx.newModules,
2909				deps:       mctx.ninjaFileDeps,
2910			}
2911		}
2912
2913		return false
2914	}
2915
2916	var obsoleteLogicModules []Module
2917
2918	// Process errs and reverseDeps in a single goroutine
2919	go func() {
2920		for {
2921			select {
2922			case newErrs := <-errsCh:
2923				errs = append(errs, newErrs...)
2924			case globalStateChange := <-globalStateCh:
2925				for _, r := range globalStateChange.reverse {
2926					reverseDeps[r.module] = append(reverseDeps[r.module], r.dep)
2927				}
2928				replace = append(replace, globalStateChange.replace...)
2929				rename = append(rename, globalStateChange.rename...)
2930				newModules = append(newModules, globalStateChange.newModules...)
2931				deps = append(deps, globalStateChange.deps...)
2932			case newVariations := <-newVariationsCh:
2933				if newVariations.origLogicModule != newVariations.newVariations[0].module().logicModule {
2934					obsoleteLogicModules = append(obsoleteLogicModules, newVariations.origLogicModule)
2935				}
2936				for _, moduleOrAlias := range newVariations.newVariations {
2937					if m := moduleOrAlias.module(); m != nil {
2938						newModuleInfo[m.logicModule] = m
2939					}
2940				}
2941			case <-done:
2942				return
2943			}
2944		}
2945	}()
2946
2947	c.startedMutator = mutator
2948
2949	var visitErrs []error
2950	if mutator.parallel {
2951		visitErrs = parallelVisit(c.modulesSorted, direction.orderer(), parallelVisitLimit, visit)
2952	} else {
2953		direction.orderer().visit(c.modulesSorted, visit)
2954	}
2955
2956	if len(visitErrs) > 0 {
2957		return nil, visitErrs
2958	}
2959
2960	c.finishedMutators[mutator] = true
2961
2962	done <- true
2963
2964	if len(errs) > 0 {
2965		return nil, errs
2966	}
2967
2968	for _, obsoleteLogicModule := range obsoleteLogicModules {
2969		delete(newModuleInfo, obsoleteLogicModule)
2970	}
2971
2972	c.moduleInfo = newModuleInfo
2973
2974	isTransitionMutator := mutator.transitionMutator != nil
2975
2976	var transitionMutatorInputVariants map[*moduleGroup][]*moduleInfo
2977	if isTransitionMutator {
2978		transitionMutatorInputVariants = make(map[*moduleGroup][]*moduleInfo)
2979	}
2980
2981	for _, group := range c.moduleGroups {
2982		for i := 0; i < len(group.modules); i++ {
2983			module := group.modules[i].module()
2984			if module == nil {
2985				// Existing alias, skip it
2986				continue
2987			}
2988
2989			// Update module group to contain newly split variants
2990			if module.splitModules != nil {
2991				if isTransitionMutator {
2992					// For transition mutators, save the pre-split variant for reusing later in applyTransitions.
2993					transitionMutatorInputVariants[group] = append(transitionMutatorInputVariants[group], module)
2994				}
2995				group.modules, i = spliceModules(group.modules, i, module.splitModules)
2996			}
2997
2998			// Fix up any remaining dependencies on modules that were split into variants
2999			// by replacing them with the first variant
3000			for j, dep := range module.directDeps {
3001				if dep.module.obsoletedByNewVariants {
3002					module.directDeps[j].module = dep.module.splitModules.firstModule()
3003				}
3004			}
3005
3006			if module.createdBy != nil && module.createdBy.obsoletedByNewVariants {
3007				module.createdBy = module.createdBy.splitModules.firstModule()
3008			}
3009
3010			// Add in any new direct dependencies that were added by the mutator
3011			module.directDeps = append(module.directDeps, module.newDirectDeps...)
3012			module.newDirectDeps = nil
3013		}
3014
3015		findAliasTarget := func(variant variant) *moduleInfo {
3016			for _, moduleOrAlias := range group.modules {
3017				if alias := moduleOrAlias.alias(); alias != nil {
3018					if alias.variant.variations.equal(variant.variations) {
3019						return alias.target
3020					}
3021				}
3022			}
3023			return nil
3024		}
3025
3026		// Forward or delete any dangling aliases.
3027		// Use a manual loop instead of range because len(group.modules) can
3028		// change inside the loop
3029		for i := 0; i < len(group.modules); i++ {
3030			if alias := group.modules[i].alias(); alias != nil {
3031				if alias.target.obsoletedByNewVariants {
3032					newTarget := findAliasTarget(alias.target.variant)
3033					if newTarget != nil {
3034						alias.target = newTarget
3035					} else {
3036						// The alias was left dangling, remove it.
3037						group.modules = append(group.modules[:i], group.modules[i+1:]...)
3038						i--
3039					}
3040				}
3041			}
3042		}
3043	}
3044
3045	if isTransitionMutator {
3046		mutator.transitionMutator.inputVariants = transitionMutatorInputVariants
3047		c.transitionMutators = append(c.transitionMutators, mutator.transitionMutator)
3048	}
3049
3050	// Add in any new reverse dependencies that were added by the mutator
3051	for module, deps := range reverseDeps {
3052		sort.Sort(depSorter(deps))
3053		module.directDeps = append(module.directDeps, deps...)
3054		c.depsModified++
3055	}
3056
3057	for _, module := range newModules {
3058		errs = c.addModule(module)
3059		if len(errs) > 0 {
3060			return nil, errs
3061		}
3062		atomic.AddUint32(&c.depsModified, 1)
3063	}
3064
3065	errs = c.handleRenames(rename)
3066	if len(errs) > 0 {
3067		return nil, errs
3068	}
3069
3070	errs = c.handleReplacements(replace)
3071	if len(errs) > 0 {
3072		return nil, errs
3073	}
3074
3075	if c.depsModified > 0 {
3076		errs = c.updateDependencies()
3077		if len(errs) > 0 {
3078			return nil, errs
3079		}
3080	}
3081
3082	return deps, errs
3083}
3084
3085// clearTransitionMutatorInputVariants removes the inputVariants field from every
3086// TransitionMutator now that all dependencies have been resolved.
3087func (c *Context) clearTransitionMutatorInputVariants() {
3088	for _, mutator := range c.transitionMutators {
3089		mutator.inputVariants = nil
3090	}
3091}
3092
3093// Replaces every build logic module with a clone of itself.  Prevents introducing problems where
3094// a mutator sets a non-property member variable on a module, which works until a later mutator
3095// creates variants of that module.
3096func (c *Context) cloneModules() {
3097	type update struct {
3098		orig  Module
3099		clone *moduleInfo
3100	}
3101	ch := make(chan update)
3102	doneCh := make(chan bool)
3103	go func() {
3104		errs := parallelVisit(c.modulesSorted, unorderedVisitorImpl{}, parallelVisitLimit,
3105			func(m *moduleInfo, pause chan<- pauseSpec) bool {
3106				origLogicModule := m.logicModule
3107				m.logicModule, m.properties = c.cloneLogicModule(m)
3108				ch <- update{origLogicModule, m}
3109				return false
3110			})
3111		if len(errs) > 0 {
3112			panic(errs)
3113		}
3114		doneCh <- true
3115	}()
3116
3117	done := false
3118	for !done {
3119		select {
3120		case <-doneCh:
3121			done = true
3122		case update := <-ch:
3123			delete(c.moduleInfo, update.orig)
3124			c.moduleInfo[update.clone.logicModule] = update.clone
3125		}
3126	}
3127}
3128
3129// Removes modules[i] from the list and inserts newModules... where it was located, returning
3130// the new slice and the index of the last inserted element
3131func spliceModules(modules modulesOrAliases, i int, newModules modulesOrAliases) (modulesOrAliases, int) {
3132	spliceSize := len(newModules)
3133	newLen := len(modules) + spliceSize - 1
3134	var dest modulesOrAliases
3135	if cap(modules) >= len(modules)-1+len(newModules) {
3136		// We can fit the splice in the existing capacity, do everything in place
3137		dest = modules[:newLen]
3138	} else {
3139		dest = make(modulesOrAliases, newLen)
3140		copy(dest, modules[:i])
3141	}
3142
3143	// Move the end of the slice over by spliceSize-1
3144	copy(dest[i+spliceSize:], modules[i+1:])
3145
3146	// Copy the new modules into the slice
3147	copy(dest[i:], newModules)
3148
3149	return dest, i + spliceSize - 1
3150}
3151
3152func (c *Context) generateModuleBuildActions(config interface{},
3153	liveGlobals *liveTracker) ([]string, []error) {
3154
3155	c.BeginEvent("generateModuleBuildActions")
3156	defer c.EndEvent("generateModuleBuildActions")
3157	var deps []string
3158	var errs []error
3159
3160	cancelCh := make(chan struct{})
3161	errsCh := make(chan []error)
3162	depsCh := make(chan []string)
3163
3164	go func() {
3165		for {
3166			select {
3167			case <-cancelCh:
3168				close(cancelCh)
3169				return
3170			case newErrs := <-errsCh:
3171				errs = append(errs, newErrs...)
3172			case newDeps := <-depsCh:
3173				deps = append(deps, newDeps...)
3174
3175			}
3176		}
3177	}()
3178
3179	visitErrs := parallelVisit(c.modulesSorted, bottomUpVisitor, parallelVisitLimit,
3180		func(module *moduleInfo, pause chan<- pauseSpec) bool {
3181			uniqueName := c.nameInterface.UniqueName(newNamespaceContext(module), module.group.name)
3182			sanitizedName := toNinjaName(uniqueName)
3183			sanitizedVariant := toNinjaName(module.variant.name)
3184
3185			prefix := moduleNamespacePrefix(sanitizedName + "_" + sanitizedVariant)
3186
3187			// The parent scope of the moduleContext's local scope gets overridden to be that of the
3188			// calling Go package on a per-call basis.  Since the initial parent scope doesn't matter we
3189			// just set it to nil.
3190			scope := newLocalScope(nil, prefix)
3191
3192			mctx := &moduleContext{
3193				baseModuleContext: baseModuleContext{
3194					context: c,
3195					config:  config,
3196					module:  module,
3197				},
3198				scope:              scope,
3199				handledMissingDeps: module.missingDeps == nil,
3200			}
3201
3202			mctx.module.startedGenerateBuildActions = true
3203
3204			func() {
3205				defer func() {
3206					if r := recover(); r != nil {
3207						in := fmt.Sprintf("GenerateBuildActions for %s", module)
3208						if err, ok := r.(panicError); ok {
3209							err.addIn(in)
3210							mctx.error(err)
3211						} else {
3212							mctx.error(newPanicErrorf(r, in))
3213						}
3214					}
3215				}()
3216				mctx.module.logicModule.GenerateBuildActions(mctx)
3217			}()
3218
3219			mctx.module.finishedGenerateBuildActions = true
3220
3221			if len(mctx.errs) > 0 {
3222				errsCh <- mctx.errs
3223				return true
3224			}
3225
3226			if module.missingDeps != nil && !mctx.handledMissingDeps {
3227				var errs []error
3228				for _, depName := range module.missingDeps {
3229					errs = append(errs, c.missingDependencyError(module, depName))
3230				}
3231				errsCh <- errs
3232				return true
3233			}
3234
3235			depsCh <- mctx.ninjaFileDeps
3236
3237			newErrs := c.processLocalBuildActions(&module.actionDefs,
3238				&mctx.actionDefs, liveGlobals)
3239			if len(newErrs) > 0 {
3240				errsCh <- newErrs
3241				return true
3242			}
3243			return false
3244		})
3245
3246	cancelCh <- struct{}{}
3247	<-cancelCh
3248
3249	errs = append(errs, visitErrs...)
3250
3251	return deps, errs
3252}
3253
3254func (c *Context) generateOneSingletonBuildActions(config interface{},
3255	info *singletonInfo, liveGlobals *liveTracker) ([]string, []error) {
3256
3257	var deps []string
3258	var errs []error
3259
3260	// The parent scope of the singletonContext's local scope gets overridden to be that of the
3261	// calling Go package on a per-call basis.  Since the initial parent scope doesn't matter we
3262	// just set it to nil.
3263	scope := newLocalScope(nil, singletonNamespacePrefix(info.name))
3264
3265	sctx := &singletonContext{
3266		name:    info.name,
3267		context: c,
3268		config:  config,
3269		scope:   scope,
3270		globals: liveGlobals,
3271	}
3272
3273	func() {
3274		defer func() {
3275			if r := recover(); r != nil {
3276				in := fmt.Sprintf("GenerateBuildActions for singleton %s", info.name)
3277				if err, ok := r.(panicError); ok {
3278					err.addIn(in)
3279					sctx.error(err)
3280				} else {
3281					sctx.error(newPanicErrorf(r, in))
3282				}
3283			}
3284		}()
3285		info.singleton.GenerateBuildActions(sctx)
3286	}()
3287
3288	if len(sctx.errs) > 0 {
3289		errs = append(errs, sctx.errs...)
3290		return deps, errs
3291	}
3292
3293	deps = append(deps, sctx.ninjaFileDeps...)
3294
3295	newErrs := c.processLocalBuildActions(&info.actionDefs,
3296		&sctx.actionDefs, liveGlobals)
3297	errs = append(errs, newErrs...)
3298	return deps, errs
3299}
3300
3301func (c *Context) generateParallelSingletonBuildActions(config interface{},
3302	singletons []*singletonInfo, liveGlobals *liveTracker) ([]string, []error) {
3303
3304	c.BeginEvent("generateParallelSingletonBuildActions")
3305	defer c.EndEvent("generateParallelSingletonBuildActions")
3306
3307	var deps []string
3308	var errs []error
3309
3310	wg := sync.WaitGroup{}
3311	cancelCh := make(chan struct{})
3312	depsCh := make(chan []string)
3313	errsCh := make(chan []error)
3314
3315	go func() {
3316		for {
3317			select {
3318			case <-cancelCh:
3319				close(cancelCh)
3320				return
3321			case dep := <-depsCh:
3322				deps = append(deps, dep...)
3323			case newErrs := <-errsCh:
3324				if len(errs) <= maxErrors {
3325					errs = append(errs, newErrs...)
3326				}
3327			}
3328		}
3329	}()
3330
3331	for _, info := range singletons {
3332		if !info.parallel {
3333			// Skip any singletons registered with parallel=false.
3334			continue
3335		}
3336		wg.Add(1)
3337		go func(inf *singletonInfo) {
3338			defer wg.Done()
3339			newDeps, newErrs := c.generateOneSingletonBuildActions(config, inf, liveGlobals)
3340			depsCh <- newDeps
3341			errsCh <- newErrs
3342		}(info)
3343	}
3344	wg.Wait()
3345
3346	cancelCh <- struct{}{}
3347	<-cancelCh
3348
3349	return deps, errs
3350}
3351
3352func (c *Context) generateSingletonBuildActions(config interface{},
3353	singletons []*singletonInfo, liveGlobals *liveTracker) ([]string, []error) {
3354
3355	c.BeginEvent("generateSingletonBuildActions")
3356	defer c.EndEvent("generateSingletonBuildActions")
3357
3358	var deps []string
3359	var errs []error
3360
3361	// Run one singleton.  Use a variable to simplify manual validation testing.
3362	var runSingleton = func(info *singletonInfo) {
3363		c.BeginEvent("singleton:" + info.name)
3364		defer c.EndEvent("singleton:" + info.name)
3365		newDeps, newErrs := c.generateOneSingletonBuildActions(config, info, liveGlobals)
3366		deps = append(deps, newDeps...)
3367		errs = append(errs, newErrs...)
3368	}
3369
3370	// Force a resort of the module groups before running singletons so that two singletons running in parallel
3371	// don't cause a data race when they trigger a resort in VisitAllModules.
3372	c.sortedModuleGroups()
3373
3374	// First, take care of any singletons that want to run in parallel.
3375	deps, errs = c.generateParallelSingletonBuildActions(config, singletons, liveGlobals)
3376
3377	for _, info := range singletons {
3378		if !info.parallel {
3379			runSingleton(info)
3380			if len(errs) > maxErrors {
3381				break
3382			}
3383		}
3384	}
3385
3386	return deps, errs
3387}
3388
3389func (c *Context) processLocalBuildActions(out, in *localBuildActions,
3390	liveGlobals *liveTracker) []error {
3391
3392	var errs []error
3393
3394	// First we go through and add everything referenced by the module's
3395	// buildDefs to the live globals set.  This will end up adding the live
3396	// locals to the set as well, but we'll take them out after.
3397	for _, def := range in.buildDefs {
3398		err := liveGlobals.AddBuildDefDeps(def)
3399		if err != nil {
3400			errs = append(errs, err)
3401		}
3402	}
3403
3404	if len(errs) > 0 {
3405		return errs
3406	}
3407
3408	out.buildDefs = append(out.buildDefs, in.buildDefs...)
3409
3410	// We use the now-incorrect set of live "globals" to determine which local
3411	// definitions are live.  As we go through copying those live locals to the
3412	// moduleGroup we remove them from the live globals set.
3413	for _, v := range in.variables {
3414		isLive := liveGlobals.RemoveVariableIfLive(v)
3415		if isLive {
3416			out.variables = append(out.variables, v)
3417		}
3418	}
3419
3420	for _, r := range in.rules {
3421		isLive := liveGlobals.RemoveRuleIfLive(r)
3422		if isLive {
3423			out.rules = append(out.rules, r)
3424		}
3425	}
3426
3427	return nil
3428}
3429
3430func (c *Context) walkDeps(topModule *moduleInfo, allowDuplicates bool,
3431	visitDown func(depInfo, *moduleInfo) bool, visitUp func(depInfo, *moduleInfo)) {
3432
3433	visited := make(map[*moduleInfo]bool)
3434	var visiting *moduleInfo
3435
3436	defer func() {
3437		if r := recover(); r != nil {
3438			panic(newPanicErrorf(r, "WalkDeps(%s, %s, %s) for dependency %s",
3439				topModule, funcName(visitDown), funcName(visitUp), visiting))
3440		}
3441	}()
3442
3443	var walk func(module *moduleInfo)
3444	walk = func(module *moduleInfo) {
3445		for _, dep := range module.directDeps {
3446			if allowDuplicates || !visited[dep.module] {
3447				visiting = dep.module
3448				recurse := true
3449				if visitDown != nil {
3450					recurse = visitDown(dep, module)
3451				}
3452				if recurse && !visited[dep.module] {
3453					walk(dep.module)
3454					visited[dep.module] = true
3455				}
3456				if visitUp != nil {
3457					visitUp(dep, module)
3458				}
3459			}
3460		}
3461	}
3462
3463	walk(topModule)
3464}
3465
3466type replace struct {
3467	from, to  *moduleInfo
3468	predicate ReplaceDependencyPredicate
3469}
3470
3471type rename struct {
3472	group *moduleGroup
3473	name  string
3474}
3475
3476// moduleVariantsThatDependOn takes the name of a module and a dependency and returns the all the variants of the
3477// module that depends on the dependency.
3478func (c *Context) moduleVariantsThatDependOn(name string, dep *moduleInfo) []*moduleInfo {
3479	group := c.moduleGroupFromName(name, dep.namespace())
3480	var variants []*moduleInfo
3481
3482	if group == nil {
3483		return nil
3484	}
3485
3486	for _, module := range group.modules {
3487		m := module.module()
3488		if m == nil {
3489			continue
3490		}
3491		for _, moduleDep := range m.directDeps {
3492			if moduleDep.module == dep {
3493				variants = append(variants, m)
3494			}
3495		}
3496	}
3497
3498	return variants
3499}
3500
3501func (c *Context) handleRenames(renames []rename) []error {
3502	var errs []error
3503	for _, rename := range renames {
3504		group, name := rename.group, rename.name
3505		if name == group.name || len(group.modules) < 1 {
3506			continue
3507		}
3508
3509		errs = append(errs, c.nameInterface.Rename(group.name, rename.name, group.namespace)...)
3510	}
3511
3512	return errs
3513}
3514
3515func (c *Context) handleReplacements(replacements []replace) []error {
3516	var errs []error
3517	changedDeps := false
3518	for _, replace := range replacements {
3519		for _, m := range replace.from.reverseDeps {
3520			for i, d := range m.directDeps {
3521				if d.module == replace.from {
3522					// If the replacement has a predicate then check it.
3523					if replace.predicate == nil || replace.predicate(m.logicModule, d.tag, d.module.logicModule) {
3524						m.directDeps[i].module = replace.to
3525						changedDeps = true
3526					}
3527				}
3528			}
3529		}
3530
3531	}
3532
3533	if changedDeps {
3534		atomic.AddUint32(&c.depsModified, 1)
3535	}
3536	return errs
3537}
3538
3539func (c *Context) discoveredMissingDependencies(module *moduleInfo, depName string, depVariations variationMap) (errs []error) {
3540	if depVariations != nil {
3541		depName = depName + "{" + c.prettyPrintVariant(depVariations) + "}"
3542	}
3543	if c.allowMissingDependencies {
3544		module.missingDeps = append(module.missingDeps, depName)
3545		return nil
3546	}
3547	return []error{c.missingDependencyError(module, depName)}
3548}
3549
3550func (c *Context) missingDependencyError(module *moduleInfo, depName string) (errs error) {
3551	guess := namesLike(depName, module.Name(), c.moduleGroups)
3552	err := c.nameInterface.MissingDependencyError(module.Name(), module.namespace(), depName, guess)
3553	return &BlueprintError{
3554		Err: err,
3555		Pos: module.pos,
3556	}
3557}
3558
3559func (c *Context) moduleGroupFromName(name string, namespace Namespace) *moduleGroup {
3560	group, exists := c.nameInterface.ModuleFromName(name, namespace)
3561	if exists {
3562		return group.moduleGroup
3563	}
3564	return nil
3565}
3566
3567func (c *Context) sortedModuleGroups() []*moduleGroup {
3568	if c.cachedSortedModuleGroups == nil || c.cachedDepsModified {
3569		unwrap := func(wrappers []ModuleGroup) []*moduleGroup {
3570			result := make([]*moduleGroup, 0, len(wrappers))
3571			for _, group := range wrappers {
3572				result = append(result, group.moduleGroup)
3573			}
3574			return result
3575		}
3576
3577		c.cachedSortedModuleGroups = unwrap(c.nameInterface.AllModules())
3578		c.cachedDepsModified = false
3579	}
3580
3581	return c.cachedSortedModuleGroups
3582}
3583
3584func (c *Context) visitAllModules(visit func(Module)) {
3585	var module *moduleInfo
3586
3587	defer func() {
3588		if r := recover(); r != nil {
3589			panic(newPanicErrorf(r, "VisitAllModules(%s) for %s",
3590				funcName(visit), module))
3591		}
3592	}()
3593
3594	for _, moduleGroup := range c.sortedModuleGroups() {
3595		for _, moduleOrAlias := range moduleGroup.modules {
3596			if module = moduleOrAlias.module(); module != nil {
3597				visit(module.logicModule)
3598			}
3599		}
3600	}
3601}
3602
3603func (c *Context) visitAllModulesIf(pred func(Module) bool,
3604	visit func(Module)) {
3605
3606	var module *moduleInfo
3607
3608	defer func() {
3609		if r := recover(); r != nil {
3610			panic(newPanicErrorf(r, "VisitAllModulesIf(%s, %s) for %s",
3611				funcName(pred), funcName(visit), module))
3612		}
3613	}()
3614
3615	for _, moduleGroup := range c.sortedModuleGroups() {
3616		for _, moduleOrAlias := range moduleGroup.modules {
3617			if module = moduleOrAlias.module(); module != nil {
3618				if pred(module.logicModule) {
3619					visit(module.logicModule)
3620				}
3621			}
3622		}
3623	}
3624}
3625
3626func (c *Context) visitAllModuleVariants(module *moduleInfo,
3627	visit func(Module)) {
3628
3629	var variant *moduleInfo
3630
3631	defer func() {
3632		if r := recover(); r != nil {
3633			panic(newPanicErrorf(r, "VisitAllModuleVariants(%s, %s) for %s",
3634				module, funcName(visit), variant))
3635		}
3636	}()
3637
3638	for _, moduleOrAlias := range module.group.modules {
3639		if variant = moduleOrAlias.module(); variant != nil {
3640			visit(variant.logicModule)
3641		}
3642	}
3643}
3644
3645func (c *Context) visitAllModuleInfos(visit func(*moduleInfo)) {
3646	var module *moduleInfo
3647
3648	defer func() {
3649		if r := recover(); r != nil {
3650			panic(newPanicErrorf(r, "VisitAllModules(%s) for %s",
3651				funcName(visit), module))
3652		}
3653	}()
3654
3655	for _, moduleGroup := range c.sortedModuleGroups() {
3656		for _, moduleOrAlias := range moduleGroup.modules {
3657			if module = moduleOrAlias.module(); module != nil {
3658				visit(module)
3659			}
3660		}
3661	}
3662}
3663
3664func (c *Context) requireNinjaVersion(major, minor, micro int) {
3665	if major != 1 {
3666		panic("ninja version with major version != 1 not supported")
3667	}
3668	if c.requiredNinjaMinor < minor {
3669		c.requiredNinjaMinor = minor
3670		c.requiredNinjaMicro = micro
3671	}
3672	if c.requiredNinjaMinor == minor && c.requiredNinjaMicro < micro {
3673		c.requiredNinjaMicro = micro
3674	}
3675}
3676
3677func (c *Context) setOutDir(value *ninjaString) {
3678	if c.outDir == nil {
3679		c.outDir = value
3680	}
3681}
3682
3683func (c *Context) makeUniquePackageNames(
3684	liveGlobals *liveTracker) (map[*packageContext]string, []string) {
3685
3686	pkgs := make(map[string]*packageContext)
3687	pkgNames := make(map[*packageContext]string)
3688	longPkgNames := make(map[*packageContext]bool)
3689
3690	processPackage := func(pctx *packageContext) {
3691		if pctx == nil {
3692			// This is a built-in rule and has no package.
3693			return
3694		}
3695		if _, ok := pkgNames[pctx]; ok {
3696			// We've already processed this package.
3697			return
3698		}
3699
3700		otherPkg, present := pkgs[pctx.shortName]
3701		if present {
3702			// Short name collision.  Both this package and the one that's
3703			// already there need to use their full names.  We leave the short
3704			// name in pkgNames for now so future collisions still get caught.
3705			longPkgNames[pctx] = true
3706			longPkgNames[otherPkg] = true
3707		} else {
3708			// No collision so far.  Tentatively set the package's name to be
3709			// its short name.
3710			pkgNames[pctx] = pctx.shortName
3711			pkgs[pctx.shortName] = pctx
3712		}
3713	}
3714
3715	// We try to give all packages their short name, but when we get collisions
3716	// we need to use the full unique package name.
3717	for v, _ := range liveGlobals.variables {
3718		processPackage(v.packageContext())
3719	}
3720	for p, _ := range liveGlobals.pools {
3721		processPackage(p.packageContext())
3722	}
3723	for r, _ := range liveGlobals.rules {
3724		processPackage(r.packageContext())
3725	}
3726
3727	// Add the packages that had collisions using their full unique names.  This
3728	// will overwrite any short names that were added in the previous step.
3729	for pctx := range longPkgNames {
3730		pkgNames[pctx] = pctx.fullName
3731	}
3732
3733	// Create deps list from calls to PackageContext.AddNinjaFileDeps
3734	deps := []string{}
3735	for _, pkg := range pkgs {
3736		deps = append(deps, pkg.ninjaFileDeps...)
3737	}
3738
3739	return pkgNames, deps
3740}
3741
3742// memoizeFullNames stores the full name of each live global variable, rule and pool since each is
3743// guaranteed to be used at least twice, once in the definition and once for each usage, and many
3744// are used much more than once.
3745func (c *Context) memoizeFullNames(liveGlobals *liveTracker, pkgNames map[*packageContext]string) *nameTracker {
3746	nameTracker := &nameTracker{
3747		pkgNames:  pkgNames,
3748		variables: make(map[Variable]string),
3749		rules:     make(map[Rule]string),
3750		pools:     make(map[Pool]string),
3751	}
3752	for v := range liveGlobals.variables {
3753		nameTracker.variables[v] = v.fullName(pkgNames)
3754	}
3755	for r := range liveGlobals.rules {
3756		nameTracker.rules[r] = r.fullName(pkgNames)
3757	}
3758	for p := range liveGlobals.pools {
3759		nameTracker.pools[p] = p.fullName(pkgNames)
3760	}
3761	return nameTracker
3762}
3763
3764func (c *Context) checkForVariableReferenceCycles(
3765	variables map[Variable]*ninjaString, nameTracker *nameTracker) {
3766
3767	visited := make(map[Variable]bool)  // variables that were already checked
3768	checking := make(map[Variable]bool) // variables actively being checked
3769
3770	var check func(v Variable) []Variable
3771
3772	check = func(v Variable) []Variable {
3773		visited[v] = true
3774		checking[v] = true
3775		defer delete(checking, v)
3776
3777		value := variables[v]
3778		for _, dep := range value.Variables() {
3779			if checking[dep] {
3780				// This is a cycle.
3781				return []Variable{dep, v}
3782			}
3783
3784			if !visited[dep] {
3785				cycle := check(dep)
3786				if cycle != nil {
3787					if cycle[0] == v {
3788						// We are the "start" of the cycle, so we're responsible
3789						// for generating the errors.  The cycle list is in
3790						// reverse order because all the 'check' calls append
3791						// their own module to the list.
3792						msgs := []string{"detected variable reference cycle:"}
3793
3794						// Iterate backwards through the cycle list.
3795						curName := nameTracker.Variable(v)
3796						curValue := value.Value(nameTracker)
3797						for i := len(cycle) - 1; i >= 0; i-- {
3798							next := cycle[i]
3799							nextName := nameTracker.Variable(next)
3800							nextValue := variables[next].Value(nameTracker)
3801
3802							msgs = append(msgs, fmt.Sprintf(
3803								"    %q depends on %q", curName, nextName))
3804							msgs = append(msgs, fmt.Sprintf(
3805								"    [%s = %s]", curName, curValue))
3806
3807							curName = nextName
3808							curValue = nextValue
3809						}
3810
3811						// Variable reference cycles are a programming error,
3812						// not the fault of the Blueprint file authors.
3813						panic(strings.Join(msgs, "\n"))
3814					} else {
3815						// We're not the "start" of the cycle, so we just append
3816						// our module to the list and return it.
3817						return append(cycle, v)
3818					}
3819				}
3820			}
3821		}
3822
3823		return nil
3824	}
3825
3826	for v := range variables {
3827		if !visited[v] {
3828			cycle := check(v)
3829			if cycle != nil {
3830				panic("inconceivable!")
3831			}
3832		}
3833	}
3834}
3835
3836// AllTargets returns a map all the build target names to the rule used to build
3837// them.  This is the same information that is output by running 'ninja -t
3838// targets all'.  If this is called before PrepareBuildActions successfully
3839// completes then ErrbuildActionsNotReady is returned.
3840func (c *Context) AllTargets() (map[string]string, error) {
3841	if !c.buildActionsReady {
3842		return nil, ErrBuildActionsNotReady
3843	}
3844
3845	targets := map[string]string{}
3846	var collectTargets = func(actionDefs localBuildActions) error {
3847		for _, buildDef := range actionDefs.buildDefs {
3848			ruleName := c.nameTracker.Rule(buildDef.Rule)
3849			for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
3850				outputValue, err := output.Eval(c.globalVariables)
3851				if err != nil {
3852					return err
3853				}
3854				targets[outputValue] = ruleName
3855			}
3856			for _, output := range append(buildDef.OutputStrings, buildDef.ImplicitOutputStrings...) {
3857				targets[output] = ruleName
3858			}
3859		}
3860		return nil
3861	}
3862	// Collect all the module build targets.
3863	for _, module := range c.moduleInfo {
3864		if err := collectTargets(module.actionDefs); err != nil {
3865			return nil, err
3866		}
3867	}
3868
3869	// Collect all the singleton build targets.
3870	for _, info := range c.singletonInfo {
3871		if err := collectTargets(info.actionDefs); err != nil {
3872			return nil, err
3873		}
3874	}
3875
3876	return targets, nil
3877}
3878
3879func (c *Context) OutDir() (string, error) {
3880	if c.outDir != nil {
3881		return c.outDir.Eval(c.globalVariables)
3882	} else {
3883		return "", nil
3884	}
3885}
3886
3887// ModuleTypePropertyStructs returns a mapping from module type name to a list of pointers to
3888// property structs returned by the factory for that module type.
3889func (c *Context) ModuleTypePropertyStructs() map[string][]interface{} {
3890	ret := make(map[string][]interface{}, len(c.moduleFactories))
3891	for moduleType, factory := range c.moduleFactories {
3892		_, ret[moduleType] = factory()
3893	}
3894
3895	return ret
3896}
3897
3898func (c *Context) ModuleTypeFactories() map[string]ModuleFactory {
3899	ret := make(map[string]ModuleFactory)
3900	for k, v := range c.moduleFactories {
3901		ret[k] = v
3902	}
3903	return ret
3904}
3905
3906func (c *Context) ModuleName(logicModule Module) string {
3907	module := c.moduleInfo[logicModule]
3908	return module.Name()
3909}
3910
3911func (c *Context) ModuleDir(logicModule Module) string {
3912	return filepath.Dir(c.BlueprintFile(logicModule))
3913}
3914
3915func (c *Context) ModuleSubDir(logicModule Module) string {
3916	module := c.moduleInfo[logicModule]
3917	return module.variant.name
3918}
3919
3920func (c *Context) ModuleType(logicModule Module) string {
3921	module := c.moduleInfo[logicModule]
3922	return module.typeName
3923}
3924
3925// ModuleProvider returns the value, if any, for the provider for a module.  If the value for the
3926// provider was not set it returns nil and false.  The return value should always be considered read-only.
3927// It panics if called before the appropriate mutator or GenerateBuildActions pass for the provider on the
3928// module.  The value returned may be a deep copy of the value originally passed to SetProvider.
3929func (c *Context) ModuleProvider(logicModule Module, provider AnyProviderKey) (any, bool) {
3930	module := c.moduleInfo[logicModule]
3931	return c.provider(module, provider.provider())
3932}
3933
3934func (c *Context) BlueprintFile(logicModule Module) string {
3935	module := c.moduleInfo[logicModule]
3936	return module.relBlueprintsFile
3937}
3938
3939func (c *Context) ModuleErrorf(logicModule Module, format string,
3940	args ...interface{}) error {
3941
3942	module := c.moduleInfo[logicModule]
3943	if module == nil {
3944		// This can happen if ModuleErrorf is called from a load hook
3945		return &BlueprintError{
3946			Err: fmt.Errorf(format, args...),
3947		}
3948	}
3949
3950	return &ModuleError{
3951		BlueprintError: BlueprintError{
3952			Err: fmt.Errorf(format, args...),
3953			Pos: module.pos,
3954		},
3955		module: module,
3956	}
3957}
3958
3959func (c *Context) PropertyErrorf(logicModule Module, property string, format string,
3960	args ...interface{}) error {
3961
3962	module := c.moduleInfo[logicModule]
3963	if module == nil {
3964		// This can happen if PropertyErrorf is called from a load hook
3965		return &BlueprintError{
3966			Err: fmt.Errorf(format, args...),
3967		}
3968	}
3969
3970	pos := module.propertyPos[property]
3971	if !pos.IsValid() {
3972		pos = module.pos
3973	}
3974
3975	return &PropertyError{
3976		ModuleError: ModuleError{
3977			BlueprintError: BlueprintError{
3978				Err: fmt.Errorf(format, args...),
3979				Pos: pos,
3980			},
3981			module: module,
3982		},
3983		property: property,
3984	}
3985}
3986
3987func (c *Context) VisitAllModules(visit func(Module)) {
3988	c.visitAllModules(visit)
3989}
3990
3991func (c *Context) VisitAllModulesIf(pred func(Module) bool,
3992	visit func(Module)) {
3993
3994	c.visitAllModulesIf(pred, visit)
3995}
3996
3997func (c *Context) VisitDirectDeps(module Module, visit func(Module)) {
3998	topModule := c.moduleInfo[module]
3999
4000	var visiting *moduleInfo
4001
4002	defer func() {
4003		if r := recover(); r != nil {
4004			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
4005				topModule, funcName(visit), visiting))
4006		}
4007	}()
4008
4009	for _, dep := range topModule.directDeps {
4010		visiting = dep.module
4011		visit(dep.module.logicModule)
4012	}
4013}
4014
4015func (c *Context) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
4016	topModule := c.moduleInfo[module]
4017
4018	var visiting *moduleInfo
4019
4020	defer func() {
4021		if r := recover(); r != nil {
4022			panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
4023				topModule, funcName(pred), funcName(visit), visiting))
4024		}
4025	}()
4026
4027	for _, dep := range topModule.directDeps {
4028		visiting = dep.module
4029		if pred(dep.module.logicModule) {
4030			visit(dep.module.logicModule)
4031		}
4032	}
4033}
4034
4035func (c *Context) VisitDepsDepthFirst(module Module, visit func(Module)) {
4036	topModule := c.moduleInfo[module]
4037
4038	var visiting *moduleInfo
4039
4040	defer func() {
4041		if r := recover(); r != nil {
4042			panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
4043				topModule, funcName(visit), visiting))
4044		}
4045	}()
4046
4047	c.walkDeps(topModule, false, nil, func(dep depInfo, parent *moduleInfo) {
4048		visiting = dep.module
4049		visit(dep.module.logicModule)
4050	})
4051}
4052
4053func (c *Context) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
4054	topModule := c.moduleInfo[module]
4055
4056	var visiting *moduleInfo
4057
4058	defer func() {
4059		if r := recover(); r != nil {
4060			panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
4061				topModule, funcName(pred), funcName(visit), visiting))
4062		}
4063	}()
4064
4065	c.walkDeps(topModule, false, nil, func(dep depInfo, parent *moduleInfo) {
4066		if pred(dep.module.logicModule) {
4067			visiting = dep.module
4068			visit(dep.module.logicModule)
4069		}
4070	})
4071}
4072
4073func (c *Context) PrimaryModule(module Module) Module {
4074	return c.moduleInfo[module].group.modules.firstModule().logicModule
4075}
4076
4077func (c *Context) FinalModule(module Module) Module {
4078	return c.moduleInfo[module].group.modules.lastModule().logicModule
4079}
4080
4081func (c *Context) VisitAllModuleVariants(module Module,
4082	visit func(Module)) {
4083
4084	c.visitAllModuleVariants(c.moduleInfo[module], visit)
4085}
4086
4087// Singletons returns a list of all registered Singletons.
4088func (c *Context) Singletons() []Singleton {
4089	var ret []Singleton
4090	for _, s := range c.singletonInfo {
4091		ret = append(ret, s.singleton)
4092	}
4093	return ret
4094}
4095
4096// SingletonName returns the name that the given singleton was registered with.
4097func (c *Context) SingletonName(singleton Singleton) string {
4098	for _, s := range c.singletonInfo {
4099		if s.singleton == singleton {
4100			return s.name
4101		}
4102	}
4103	return ""
4104}
4105
4106// Checks that the hashes of all the providers match the hashes from when they were first set.
4107// Does nothing on success, returns a list of errors otherwise. It's recommended to run this
4108// in a goroutine.
4109func (c *Context) VerifyProvidersWereUnchanged() []error {
4110	if !c.buildActionsReady {
4111		return []error{ErrBuildActionsNotReady}
4112	}
4113	toProcess := make(chan *moduleInfo)
4114	errorCh := make(chan []error)
4115	var wg sync.WaitGroup
4116	go func() {
4117		for _, m := range c.modulesSorted {
4118			toProcess <- m
4119		}
4120		close(toProcess)
4121	}()
4122	for i := 0; i < 1000; i++ {
4123		wg.Add(1)
4124		go func() {
4125			var errors []error
4126			for m := range toProcess {
4127				for i, provider := range m.providers {
4128					if provider != nil {
4129						hash, err := proptools.CalculateHash(provider)
4130						if err != nil {
4131							errors = append(errors, fmt.Errorf("provider %q on module %q was modified after being set, and no longer hashable afterwards: %s", providerRegistry[i].typ, m.Name(), err.Error()))
4132							continue
4133						}
4134						if m.providerInitialValueHashes[i] != hash {
4135							errors = append(errors, fmt.Errorf("provider %q on module %q was modified after being set", providerRegistry[i].typ, m.Name()))
4136						}
4137					} else if m.providerInitialValueHashes[i] != 0 {
4138						// This should be unreachable, because in setProvider we check if the provider has already been set.
4139						errors = append(errors, fmt.Errorf("provider %q on module %q was unset somehow, this is an internal error", providerRegistry[i].typ, m.Name()))
4140					}
4141				}
4142			}
4143			if errors != nil {
4144				errorCh <- errors
4145			}
4146			wg.Done()
4147		}()
4148	}
4149	go func() {
4150		wg.Wait()
4151		close(errorCh)
4152	}()
4153
4154	var errors []error
4155	for newErrors := range errorCh {
4156		errors = append(errors, newErrors...)
4157	}
4158	return errors
4159}
4160
4161// WriteBuildFile writes the Ninja manifest text for the generated build
4162// actions to w.  If this is called before PrepareBuildActions successfully
4163// completes then ErrBuildActionsNotReady is returned.
4164func (c *Context) WriteBuildFile(w StringWriterWriter, shardNinja bool, ninjaFileName string) error {
4165	var err error
4166	pprof.Do(c.Context, pprof.Labels("blueprint", "WriteBuildFile"), func(ctx context.Context) {
4167		if !c.buildActionsReady {
4168			err = ErrBuildActionsNotReady
4169			return
4170		}
4171
4172		nw := newNinjaWriter(w)
4173
4174		if err = c.writeBuildFileHeader(nw); err != nil {
4175			return
4176		}
4177
4178		if err = c.writeNinjaRequiredVersion(nw); err != nil {
4179			return
4180		}
4181
4182		if err = c.writeSubninjas(nw); err != nil {
4183			return
4184		}
4185
4186		// TODO: Group the globals by package.
4187
4188		if err = c.writeGlobalVariables(nw); err != nil {
4189			return
4190		}
4191
4192		if err = c.writeGlobalPools(nw); err != nil {
4193			return
4194		}
4195
4196		if err = c.writeBuildDir(nw); err != nil {
4197			return
4198		}
4199
4200		if err = c.writeGlobalRules(nw); err != nil {
4201			return
4202		}
4203
4204		if err = c.writeAllModuleActions(nw, shardNinja, ninjaFileName); err != nil {
4205			return
4206		}
4207
4208		if err = c.writeAllSingletonActions(nw); err != nil {
4209			return
4210		}
4211	})
4212
4213	return err
4214}
4215
4216type pkgAssociation struct {
4217	PkgName string
4218	PkgPath string
4219}
4220
4221type pkgAssociationSorter struct {
4222	pkgs []pkgAssociation
4223}
4224
4225func (s *pkgAssociationSorter) Len() int {
4226	return len(s.pkgs)
4227}
4228
4229func (s *pkgAssociationSorter) Less(i, j int) bool {
4230	iName := s.pkgs[i].PkgName
4231	jName := s.pkgs[j].PkgName
4232	return iName < jName
4233}
4234
4235func (s *pkgAssociationSorter) Swap(i, j int) {
4236	s.pkgs[i], s.pkgs[j] = s.pkgs[j], s.pkgs[i]
4237}
4238
4239func (c *Context) writeBuildFileHeader(nw *ninjaWriter) error {
4240	headerTemplate := template.New("fileHeader")
4241	_, err := headerTemplate.Parse(fileHeaderTemplate)
4242	if err != nil {
4243		// This is a programming error.
4244		panic(err)
4245	}
4246
4247	var pkgs []pkgAssociation
4248	maxNameLen := 0
4249	for pkg, name := range c.nameTracker.pkgNames {
4250		pkgs = append(pkgs, pkgAssociation{
4251			PkgName: name,
4252			PkgPath: pkg.pkgPath,
4253		})
4254		if len(name) > maxNameLen {
4255			maxNameLen = len(name)
4256		}
4257	}
4258
4259	for i := range pkgs {
4260		pkgs[i].PkgName += strings.Repeat(" ", maxNameLen-len(pkgs[i].PkgName))
4261	}
4262
4263	sort.Sort(&pkgAssociationSorter{pkgs})
4264
4265	params := map[string]interface{}{
4266		"Pkgs": pkgs,
4267	}
4268
4269	buf := bytes.NewBuffer(nil)
4270	err = headerTemplate.Execute(buf, params)
4271	if err != nil {
4272		return err
4273	}
4274
4275	return nw.Comment(buf.String())
4276}
4277
4278func (c *Context) writeNinjaRequiredVersion(nw *ninjaWriter) error {
4279	value := fmt.Sprintf("%d.%d.%d", c.requiredNinjaMajor, c.requiredNinjaMinor,
4280		c.requiredNinjaMicro)
4281
4282	err := nw.Assign("ninja_required_version", value)
4283	if err != nil {
4284		return err
4285	}
4286
4287	return nw.BlankLine()
4288}
4289
4290func (c *Context) writeSubninjas(nw *ninjaWriter) error {
4291	for _, subninja := range c.subninjas {
4292		err := nw.Subninja(subninja)
4293		if err != nil {
4294			return err
4295		}
4296	}
4297	return nw.BlankLine()
4298}
4299
4300func (c *Context) writeBuildDir(nw *ninjaWriter) error {
4301	if c.outDir != nil {
4302		err := nw.Assign("builddir", c.outDir.Value(c.nameTracker))
4303		if err != nil {
4304			return err
4305		}
4306
4307		err = nw.BlankLine()
4308		if err != nil {
4309			return err
4310		}
4311	}
4312	return nil
4313}
4314
4315func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
4316	visited := make(map[Variable]bool)
4317
4318	var walk func(v Variable) error
4319	walk = func(v Variable) error {
4320		visited[v] = true
4321
4322		// First visit variables on which this variable depends.
4323		value := c.globalVariables[v]
4324		for _, dep := range value.Variables() {
4325			if !visited[dep] {
4326				err := walk(dep)
4327				if err != nil {
4328					return err
4329				}
4330			}
4331		}
4332
4333		err := nw.Assign(c.nameTracker.Variable(v), value.Value(c.nameTracker))
4334		if err != nil {
4335			return err
4336		}
4337
4338		err = nw.BlankLine()
4339		if err != nil {
4340			return err
4341		}
4342
4343		return nil
4344	}
4345
4346	globalVariables := make([]Variable, 0, len(c.globalVariables))
4347	for variable := range c.globalVariables {
4348		globalVariables = append(globalVariables, variable)
4349	}
4350
4351	slices.SortFunc(globalVariables, func(a, b Variable) int {
4352		return cmp.Compare(c.nameTracker.Variable(a), c.nameTracker.Variable(b))
4353	})
4354
4355	for _, v := range globalVariables {
4356		if !visited[v] {
4357			err := walk(v)
4358			if err != nil {
4359				return nil
4360			}
4361		}
4362	}
4363
4364	return nil
4365}
4366
4367func (c *Context) writeGlobalPools(nw *ninjaWriter) error {
4368	globalPools := make([]Pool, 0, len(c.globalPools))
4369	for pool := range c.globalPools {
4370		globalPools = append(globalPools, pool)
4371	}
4372
4373	slices.SortFunc(globalPools, func(a, b Pool) int {
4374		return cmp.Compare(c.nameTracker.Pool(a), c.nameTracker.Pool(b))
4375	})
4376
4377	for _, pool := range globalPools {
4378		name := c.nameTracker.Pool(pool)
4379		def := c.globalPools[pool]
4380		err := def.WriteTo(nw, name)
4381		if err != nil {
4382			return err
4383		}
4384
4385		err = nw.BlankLine()
4386		if err != nil {
4387			return err
4388		}
4389	}
4390
4391	return nil
4392}
4393
4394func (c *Context) writeGlobalRules(nw *ninjaWriter) error {
4395	globalRules := make([]Rule, 0, len(c.globalRules))
4396	for rule := range c.globalRules {
4397		globalRules = append(globalRules, rule)
4398	}
4399
4400	slices.SortFunc(globalRules, func(a, b Rule) int {
4401		return cmp.Compare(c.nameTracker.Rule(a), c.nameTracker.Rule(b))
4402	})
4403
4404	for _, rule := range globalRules {
4405		name := c.nameTracker.Rule(rule)
4406		def := c.globalRules[rule]
4407		err := def.WriteTo(nw, name, c.nameTracker)
4408		if err != nil {
4409			return err
4410		}
4411
4412		err = nw.BlankLine()
4413		if err != nil {
4414			return err
4415		}
4416	}
4417
4418	return nil
4419}
4420
4421type depSorter []depInfo
4422
4423func (s depSorter) Len() int {
4424	return len(s)
4425}
4426
4427func (s depSorter) Less(i, j int) bool {
4428	iName := s[i].module.Name()
4429	jName := s[j].module.Name()
4430	if iName == jName {
4431		iName = s[i].module.variant.name
4432		jName = s[j].module.variant.name
4433	}
4434	return iName < jName
4435}
4436
4437func (s depSorter) Swap(i, j int) {
4438	s[i], s[j] = s[j], s[i]
4439}
4440
4441type moduleSorter struct {
4442	modules       []*moduleInfo
4443	nameInterface NameInterface
4444}
4445
4446func (s moduleSorter) Len() int {
4447	return len(s.modules)
4448}
4449
4450func (s moduleSorter) Less(i, j int) bool {
4451	iMod := s.modules[i]
4452	jMod := s.modules[j]
4453	iName := s.nameInterface.UniqueName(newNamespaceContext(iMod), iMod.group.name)
4454	jName := s.nameInterface.UniqueName(newNamespaceContext(jMod), jMod.group.name)
4455	if iName == jName {
4456		iVariantName := s.modules[i].variant.name
4457		jVariantName := s.modules[j].variant.name
4458		if iVariantName == jVariantName {
4459			panic(fmt.Sprintf("duplicate module name: %s %s: %#v and %#v\n",
4460				iName, iVariantName, iMod.variant.variations, jMod.variant.variations))
4461		} else {
4462			return iVariantName < jVariantName
4463		}
4464	} else {
4465		return iName < jName
4466	}
4467}
4468
4469func (s moduleSorter) Swap(i, j int) {
4470	s.modules[i], s.modules[j] = s.modules[j], s.modules[i]
4471}
4472
4473func GetNinjaShardFiles(ninjaFile string) []string {
4474	ninjaShardCnt := 10
4475	fileNames := make([]string, ninjaShardCnt)
4476
4477	for i := 0; i < ninjaShardCnt; i++ {
4478		fileNames[i] = fmt.Sprintf("%s.%d", ninjaFile, i)
4479	}
4480	return fileNames
4481}
4482
4483func (c *Context) writeAllModuleActions(nw *ninjaWriter, shardNinja bool, ninjaFileName string) error {
4484	c.BeginEvent("modules")
4485	defer c.EndEvent("modules")
4486
4487	modules := make([]*moduleInfo, 0, len(c.moduleInfo))
4488	for _, module := range c.moduleInfo {
4489		modules = append(modules, module)
4490	}
4491	sort.Sort(moduleSorter{modules, c.nameInterface})
4492
4493	phonys := c.deduplicateOrderOnlyDeps(modules)
4494	if err := c.writeLocalBuildActions(nw, phonys); err != nil {
4495		return err
4496	}
4497
4498	headerTemplate := template.New("moduleHeader")
4499	if _, err := headerTemplate.Parse(moduleHeaderTemplate); err != nil {
4500		// This is a programming error.
4501		panic(err)
4502	}
4503
4504	if shardNinja {
4505		var wg sync.WaitGroup
4506		errorCh := make(chan error)
4507		files := GetNinjaShardFiles(ninjaFileName)
4508		shardedModules := proptools.ShardByCount(modules, len(files))
4509		for i, batchModules := range shardedModules {
4510			file := files[i]
4511			wg.Add(1)
4512			go func(file string, batchModules []*moduleInfo) {
4513				defer wg.Done()
4514				f, err := os.OpenFile(JoinPath(c.SrcDir(), file), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, OutFilePermissions)
4515				if err != nil {
4516					errorCh <- fmt.Errorf("error opening Ninja file shard: %s", err)
4517					return
4518				}
4519				defer func() {
4520					err := f.Close()
4521					if err != nil {
4522						errorCh <- err
4523					}
4524				}()
4525				buf := bufio.NewWriterSize(f, 16*1024*1024)
4526				defer func() {
4527					err := buf.Flush()
4528					if err != nil {
4529						errorCh <- err
4530					}
4531				}()
4532				writer := newNinjaWriter(buf)
4533				err = c.writeModuleAction(batchModules, writer, headerTemplate)
4534				if err != nil {
4535					errorCh <- err
4536				}
4537			}(file, batchModules)
4538			nw.Subninja(file)
4539		}
4540		go func() {
4541			wg.Wait()
4542			close(errorCh)
4543		}()
4544
4545		var errors []error
4546		for newErrors := range errorCh {
4547			errors = append(errors, newErrors)
4548		}
4549		if len(errors) > 0 {
4550			return proptools.MergeErrors(errors)
4551		}
4552		return nil
4553	} else {
4554		return c.writeModuleAction(modules, nw, headerTemplate)
4555	}
4556}
4557
4558func (c *Context) writeModuleAction(modules []*moduleInfo, nw *ninjaWriter, headerTemplate *template.Template) error {
4559	buf := bytes.NewBuffer(nil)
4560
4561	for _, module := range modules {
4562		if len(module.actionDefs.variables)+len(module.actionDefs.rules)+len(module.actionDefs.buildDefs) == 0 {
4563			continue
4564		}
4565
4566		buf.Reset()
4567
4568		// In order to make the bootstrap build manifest independent of the
4569		// build dir we need to output the Blueprints file locations in the
4570		// comments as paths relative to the source directory.
4571		relPos := module.pos
4572		relPos.Filename = module.relBlueprintsFile
4573
4574		// Get the name and location of the factory function for the module.
4575		factoryFunc := runtime.FuncForPC(reflect.ValueOf(module.factory).Pointer())
4576		factoryName := factoryFunc.Name()
4577
4578		infoMap := map[string]interface{}{
4579			"name":      module.Name(),
4580			"typeName":  module.typeName,
4581			"goFactory": factoryName,
4582			"pos":       relPos,
4583			"variant":   module.variant.name,
4584		}
4585		if err := headerTemplate.Execute(buf, infoMap); err != nil {
4586			return err
4587		}
4588
4589		if err := nw.Comment(buf.String()); err != nil {
4590			return err
4591		}
4592
4593		if err := nw.BlankLine(); err != nil {
4594			return err
4595		}
4596
4597		if err := c.writeLocalBuildActions(nw, &module.actionDefs); err != nil {
4598			return err
4599		}
4600
4601		if err := nw.BlankLine(); err != nil {
4602			return err
4603		}
4604	}
4605
4606	return nil
4607}
4608
4609func (c *Context) writeAllSingletonActions(nw *ninjaWriter) error {
4610	c.BeginEvent("singletons")
4611	defer c.EndEvent("singletons")
4612	headerTemplate := template.New("singletonHeader")
4613	_, err := headerTemplate.Parse(singletonHeaderTemplate)
4614	if err != nil {
4615		// This is a programming error.
4616		panic(err)
4617	}
4618
4619	buf := bytes.NewBuffer(nil)
4620
4621	for _, info := range c.singletonInfo {
4622		if len(info.actionDefs.variables)+len(info.actionDefs.rules)+len(info.actionDefs.buildDefs) == 0 {
4623			continue
4624		}
4625
4626		// Get the name of the factory function for the module.
4627		factory := info.factory
4628		factoryFunc := runtime.FuncForPC(reflect.ValueOf(factory).Pointer())
4629		factoryName := factoryFunc.Name()
4630
4631		buf.Reset()
4632		infoMap := map[string]interface{}{
4633			"name":      info.name,
4634			"goFactory": factoryName,
4635		}
4636		err = headerTemplate.Execute(buf, infoMap)
4637		if err != nil {
4638			return err
4639		}
4640
4641		err = nw.Comment(buf.String())
4642		if err != nil {
4643			return err
4644		}
4645
4646		err = nw.BlankLine()
4647		if err != nil {
4648			return err
4649		}
4650
4651		err = c.writeLocalBuildActions(nw, &info.actionDefs)
4652		if err != nil {
4653			return err
4654		}
4655
4656		err = nw.BlankLine()
4657		if err != nil {
4658			return err
4659		}
4660	}
4661
4662	return nil
4663}
4664
4665func (c *Context) GetEventHandler() *metrics.EventHandler {
4666	return c.EventHandler
4667}
4668
4669func (c *Context) BeginEvent(name string) {
4670	c.EventHandler.Begin(name)
4671}
4672
4673func (c *Context) EndEvent(name string) {
4674	c.EventHandler.End(name)
4675}
4676
4677func (c *Context) SetBeforePrepareBuildActionsHook(hookFn func() error) {
4678	c.BeforePrepareBuildActionsHook = hookFn
4679}
4680
4681// phonyCandidate represents the state of a set of deps that decides its eligibility
4682// to be extracted as a phony output
4683type phonyCandidate struct {
4684	sync.Once
4685	phony            *buildDef      // the phony buildDef that wraps the set
4686	first            *buildDef      // the first buildDef that uses this set
4687	orderOnlyStrings []string       // the original OrderOnlyStrings of the first buildDef that uses this set
4688	orderOnly        []*ninjaString // the original OrderOnly of the first buildDef that uses this set
4689}
4690
4691// keyForPhonyCandidate gives a unique identifier for a set of deps.
4692// If any of the deps use a variable, we return an empty string to signal
4693// that this set of deps is ineligible for extraction.
4694func keyForPhonyCandidate(deps []*ninjaString, stringDeps []string) uint64 {
4695	hasher := fnv.New64a()
4696	write := func(s string) {
4697		// The hasher doesn't retain or modify the input slice, so pass the string data directly to avoid
4698		// an extra allocation and copy.
4699		_, err := hasher.Write(unsafe.Slice(unsafe.StringData(s), len(s)))
4700		if err != nil {
4701			panic(fmt.Errorf("write failed: %w", err))
4702		}
4703	}
4704	for _, d := range deps {
4705		if len(d.Variables()) != 0 {
4706			return 0
4707		}
4708		write(d.Value(nil))
4709	}
4710	for _, d := range stringDeps {
4711		write(d)
4712	}
4713	return hasher.Sum64()
4714}
4715
4716// scanBuildDef is called for every known buildDef `b` that has a non-empty `b.OrderOnly`.
4717// If `b.OrderOnly` is not present in `candidates`, it gets stored.
4718// But if `b.OrderOnly` already exists in `candidates`, then `b.OrderOnly`
4719// (and phonyCandidate#first.OrderOnly) will be replaced with phonyCandidate#phony.Outputs
4720func scanBuildDef(candidates *sync.Map, b *buildDef) {
4721	key := keyForPhonyCandidate(b.OrderOnly, b.OrderOnlyStrings)
4722	if key == 0 {
4723		return
4724	}
4725	if v, loaded := candidates.LoadOrStore(key, &phonyCandidate{
4726		first:            b,
4727		orderOnly:        b.OrderOnly,
4728		orderOnlyStrings: b.OrderOnlyStrings,
4729	}); loaded {
4730		m := v.(*phonyCandidate)
4731		if slices.EqualFunc(m.orderOnly, b.OrderOnly, ninjaStringsEqual) &&
4732			slices.Equal(m.orderOnlyStrings, b.OrderOnlyStrings) {
4733			m.Do(func() {
4734				// this is the second occurrence and hence it makes sense to
4735				// extract it as a phony output
4736				m.phony = &buildDef{
4737					Rule:          Phony,
4738					OutputStrings: []string{fmt.Sprintf("dedup-%x", key)},
4739					Inputs:        m.first.OrderOnly, //we could also use b.OrderOnly
4740					InputStrings:  m.first.OrderOnlyStrings,
4741					Optional:      true,
4742				}
4743				// the previously recorded build-def, which first had these deps as its
4744				// order-only deps, should now use this phony output instead
4745				m.first.OrderOnlyStrings = m.phony.OutputStrings
4746				m.first.OrderOnly = nil
4747				m.first = nil
4748			})
4749			b.OrderOnlyStrings = m.phony.OutputStrings
4750			b.OrderOnly = nil
4751		}
4752	}
4753}
4754
4755// deduplicateOrderOnlyDeps searches for common sets of order-only dependencies across all
4756// buildDef instances in the provided moduleInfo instances. Each such
4757// common set forms a new buildDef representing a phony output that then becomes
4758// the sole order-only dependency of those buildDef instances
4759func (c *Context) deduplicateOrderOnlyDeps(modules []*moduleInfo) *localBuildActions {
4760	c.BeginEvent("deduplicate_order_only_deps")
4761	defer c.EndEvent("deduplicate_order_only_deps")
4762
4763	candidates := sync.Map{} //used as map[key]*candidate
4764	parallelVisit(modules, unorderedVisitorImpl{}, parallelVisitLimit,
4765		func(m *moduleInfo, pause chan<- pauseSpec) bool {
4766			for _, b := range m.actionDefs.buildDefs {
4767				if len(b.OrderOnly) > 0 || len(b.OrderOnlyStrings) > 0 {
4768					scanBuildDef(&candidates, b)
4769				}
4770			}
4771			return false
4772		})
4773
4774	// now collect all created phonys to return
4775	var phonys []*buildDef
4776	candidates.Range(func(_ any, v any) bool {
4777		candidate := v.(*phonyCandidate)
4778		if candidate.phony != nil {
4779			phonys = append(phonys, candidate.phony)
4780		}
4781		return true
4782	})
4783
4784	c.EventHandler.Do("sort_phony_builddefs", func() {
4785		// sorting for determinism, the phony output names are stable
4786		sort.Slice(phonys, func(i int, j int) bool {
4787			return phonys[i].OutputStrings[0] < phonys[j].OutputStrings[0]
4788		})
4789	})
4790
4791	return &localBuildActions{buildDefs: phonys}
4792}
4793
4794func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
4795	defs *localBuildActions) error {
4796
4797	// Write the local variable assignments.
4798	for _, v := range defs.variables {
4799		// A localVariable doesn't need the package names or config to
4800		// determine its name or value.
4801		name := v.fullName(nil)
4802		value, err := v.value(nil, nil)
4803		if err != nil {
4804			panic(err)
4805		}
4806		err = nw.Assign(name, value.Value(c.nameTracker))
4807		if err != nil {
4808			return err
4809		}
4810	}
4811
4812	if len(defs.variables) > 0 {
4813		err := nw.BlankLine()
4814		if err != nil {
4815			return err
4816		}
4817	}
4818
4819	// Write the local rules.
4820	for _, r := range defs.rules {
4821		// A localRule doesn't need the package names or config to determine
4822		// its name or definition.
4823		name := r.fullName(nil)
4824		def, err := r.def(nil)
4825		if err != nil {
4826			panic(err)
4827		}
4828
4829		err = def.WriteTo(nw, name, c.nameTracker)
4830		if err != nil {
4831			return err
4832		}
4833
4834		err = nw.BlankLine()
4835		if err != nil {
4836			return err
4837		}
4838	}
4839
4840	// Write the build definitions.
4841	for _, buildDef := range defs.buildDefs {
4842		err := buildDef.WriteTo(nw, c.nameTracker)
4843		if err != nil {
4844			return err
4845		}
4846
4847		if len(buildDef.Args) > 0 {
4848			err = nw.BlankLine()
4849			if err != nil {
4850				return err
4851			}
4852		}
4853	}
4854
4855	return nil
4856}
4857
4858func beforeInModuleList(a, b *moduleInfo, list modulesOrAliases) bool {
4859	found := false
4860	if a == b {
4861		return false
4862	}
4863	for _, l := range list {
4864		if l.module() == a {
4865			found = true
4866		} else if l.module() == b {
4867			return found
4868		}
4869	}
4870
4871	missing := a
4872	if found {
4873		missing = b
4874	}
4875	panic(fmt.Errorf("element %v not found in list %v", missing, list))
4876}
4877
4878type panicError struct {
4879	panic interface{}
4880	stack []byte
4881	in    string
4882}
4883
4884func newPanicErrorf(panic interface{}, in string, a ...interface{}) error {
4885	buf := make([]byte, 4096)
4886	count := runtime.Stack(buf, false)
4887	return panicError{
4888		panic: panic,
4889		in:    fmt.Sprintf(in, a...),
4890		stack: buf[:count],
4891	}
4892}
4893
4894func (p panicError) Error() string {
4895	return fmt.Sprintf("panic in %s\n%s\n%s\n", p.in, p.panic, p.stack)
4896}
4897
4898func (p *panicError) addIn(in string) {
4899	p.in += " in " + in
4900}
4901
4902func funcName(f interface{}) string {
4903	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
4904}
4905
4906// json representation of a dependency
4907type depJson struct {
4908	Name    string      `json:"name"`
4909	Variant string      `json:"variant"`
4910	TagType string      `json:"tag_type"`
4911	TagData interface{} `json:"tag_data"`
4912}
4913
4914// json representation of a provider
4915type providerJson struct {
4916	Type   string      `json:"type"`
4917	Debug  string      `json:"debug"` // from GetDebugString on the provider data
4918	Fields interface{} `json:"fields"`
4919}
4920
4921// interface for getting debug info from various data.
4922// TODO: Consider having this return a json object instead
4923type Debuggable interface {
4924	GetDebugString() string
4925}
4926
4927// Convert a slice in a reflect.Value to a value suitable for outputting to json
4928func debugSlice(value reflect.Value) interface{} {
4929	size := value.Len()
4930	if size == 0 {
4931		return nil
4932	}
4933	result := make([]interface{}, size)
4934	for i := 0; i < size; i++ {
4935		result[i] = debugValue(value.Index(i))
4936	}
4937	return result
4938}
4939
4940// Convert a map in a reflect.Value to a value suitable for outputting to json
4941func debugMap(value reflect.Value) interface{} {
4942	if value.IsNil() {
4943		return nil
4944	}
4945	result := make(map[string]interface{})
4946	iter := value.MapRange()
4947	for iter.Next() {
4948		// In the (hopefully) rare case of a key collision (which will happen when multiple
4949		// go-typed keys have the same string representation, we'll just overwrite the last
4950		// value.
4951		result[debugKey(iter.Key())] = debugValue(iter.Value())
4952	}
4953	return result
4954}
4955
4956// Convert a value into a string, suitable for being a json map key.
4957func debugKey(value reflect.Value) string {
4958	return fmt.Sprintf("%v", value)
4959}
4960
4961// Convert a single value (possibly a map or slice too) in a reflect.Value to a value suitable for outputting to json
4962func debugValue(value reflect.Value) interface{} {
4963	// Remember if we originally received a reflect.Interface.
4964	wasInterface := value.Kind() == reflect.Interface
4965	// Dereference pointers down to the real type
4966	for value.Kind() == reflect.Ptr || value.Kind() == reflect.Interface {
4967		// If it's nil, return nil
4968		if value.IsNil() {
4969			return nil
4970		}
4971		value = value.Elem()
4972	}
4973
4974	// Skip private fields, maybe other weird corner cases of go's bizarre type system.
4975	if !value.CanInterface() {
4976		return nil
4977	}
4978
4979	switch kind := value.Kind(); kind {
4980	case reflect.Bool, reflect.String, reflect.Int, reflect.Uint:
4981		return value.Interface()
4982	case reflect.Slice:
4983		return debugSlice(value)
4984	case reflect.Struct:
4985		// If we originally received an interface, and there is a String() method, call that.
4986		// TODO: figure out why Path doesn't work correctly otherwise (in aconfigPropagatingDeclarationsInfo)
4987		if s, ok := value.Interface().(interface{ String() string }); wasInterface && ok {
4988			return s.String()
4989		}
4990		return debugStruct(value)
4991	case reflect.Map:
4992		return debugMap(value)
4993	default:
4994		// TODO: add cases as we find them.
4995		return fmt.Sprintf("debugValue(Kind=%v, wasInterface=%v)", kind, wasInterface)
4996	}
4997
4998	return nil
4999}
5000
5001// Convert an object in a reflect.Value to a value suitable for outputting to json
5002func debugStruct(value reflect.Value) interface{} {
5003	result := make(map[string]interface{})
5004	debugStructAppend(value, &result)
5005	if len(result) == 0 {
5006		return nil
5007	}
5008	return result
5009}
5010
5011// Convert an object to a value suiable for outputting to json
5012func debugStructAppend(value reflect.Value, result *map[string]interface{}) {
5013	for value.Kind() == reflect.Ptr {
5014		if value.IsNil() {
5015			return
5016		}
5017		value = value.Elem()
5018	}
5019	if value.IsZero() {
5020		return
5021	}
5022
5023	if value.Kind() != reflect.Struct {
5024		// TODO: could maybe support other types
5025		return
5026	}
5027
5028	structType := value.Type()
5029	for i := 0; i < value.NumField(); i++ {
5030		v := debugValue(value.Field(i))
5031		if v != nil {
5032			(*result)[structType.Field(i).Name] = v
5033		}
5034	}
5035}
5036
5037func debugPropertyStruct(props interface{}, result *map[string]interface{}) {
5038	if props == nil {
5039		return
5040	}
5041	debugStructAppend(reflect.ValueOf(props), result)
5042}
5043
5044// Get the debug json for a single module. Returns thae data as
5045// flattened json text for easy concatenation by GenerateModuleDebugInfo.
5046func getModuleDebugJson(module *moduleInfo) []byte {
5047	info := struct {
5048		Name       string                 `json:"name"`
5049		SourceFile string                 `json:"source_file"`
5050		SourceLine int                    `json:"source_line"`
5051		Type       string                 `json:"type"`
5052		Variant    string                 `json:"variant"`
5053		Deps       []depJson              `json:"deps"`
5054		Providers  []providerJson         `json:"providers"`
5055		Debug      string                 `json:"debug"` // from GetDebugString on the module
5056		Properties map[string]interface{} `json:"properties"`
5057	}{
5058		Name:       module.logicModule.Name(),
5059		SourceFile: module.pos.Filename,
5060		SourceLine: module.pos.Line,
5061		Type:       module.typeName,
5062		Variant:    module.variant.name,
5063		Deps: func() []depJson {
5064			result := make([]depJson, len(module.directDeps))
5065			for i, dep := range module.directDeps {
5066				result[i] = depJson{
5067					Name:    dep.module.logicModule.Name(),
5068					Variant: dep.module.variant.name,
5069				}
5070				t := reflect.TypeOf(dep.tag)
5071				if t != nil {
5072					result[i].TagType = t.PkgPath() + "." + t.Name()
5073					result[i].TagData = debugStruct(reflect.ValueOf(dep.tag))
5074				}
5075			}
5076			return result
5077		}(),
5078		Providers: func() []providerJson {
5079			result := make([]providerJson, 0, len(module.providers))
5080			for _, p := range module.providers {
5081				pj := providerJson{}
5082				include := false
5083
5084				t := reflect.TypeOf(p)
5085				if t != nil {
5086					pj.Type = t.PkgPath() + "." + t.Name()
5087					include = true
5088				}
5089
5090				if dbg, ok := p.(Debuggable); ok {
5091					pj.Debug = dbg.GetDebugString()
5092					if pj.Debug != "" {
5093						include = true
5094					}
5095				}
5096
5097				if p != nil {
5098					pj.Fields = debugValue(reflect.ValueOf(p))
5099					include = true
5100				}
5101
5102				if include {
5103					result = append(result, pj)
5104				}
5105			}
5106			return result
5107		}(),
5108		Debug: func() string {
5109			if dbg, ok := module.logicModule.(Debuggable); ok {
5110				return dbg.GetDebugString()
5111			} else {
5112				return ""
5113			}
5114		}(),
5115		Properties: func() map[string]interface{} {
5116			result := make(map[string]interface{})
5117			for _, props := range module.properties {
5118				debugPropertyStruct(props, &result)
5119			}
5120			return result
5121		}(),
5122	}
5123	buf, _ := json.Marshal(info)
5124	return buf
5125}
5126
5127// Generate out/soong/soong-debug-info.json Called if GENERATE_SOONG_DEBUG=true.
5128func (this *Context) GenerateModuleDebugInfo(filename string) {
5129	err := os.MkdirAll(filepath.Dir(filename), 0777)
5130	if err != nil {
5131		// We expect this to be writable
5132		panic(fmt.Sprintf("couldn't create directory for soong module debug file %s: %s", filepath.Dir(filename), err))
5133	}
5134
5135	f, err := os.Create(filename)
5136	if err != nil {
5137		// We expect this to be writable
5138		panic(fmt.Sprintf("couldn't create soong module debug file %s: %s", filename, err))
5139	}
5140	defer f.Close()
5141
5142	needComma := false
5143	f.WriteString("{\n\"modules\": [\n")
5144
5145	// TODO: Optimize this (parallel execution, etc) if it gets slow.
5146	this.visitAllModuleInfos(func(module *moduleInfo) {
5147		if needComma {
5148			f.WriteString(",\n")
5149		} else {
5150			needComma = true
5151		}
5152
5153		moduleData := getModuleDebugJson(module)
5154		f.Write(moduleData)
5155	})
5156
5157	f.WriteString("\n]\n}")
5158}
5159
5160var fileHeaderTemplate = `******************************************************************************
5161***            This file is generated and should not be edited             ***
5162******************************************************************************
5163{{if .Pkgs}}
5164This file contains variables, rules, and pools with name prefixes indicating
5165they were generated by the following Go packages:
5166{{range .Pkgs}}
5167    {{.PkgName}} [from Go package {{.PkgPath}}]{{end}}{{end}}
5168
5169`
5170
5171var moduleHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
5172Module:  {{.name}}
5173Variant: {{.variant}}
5174Type:    {{.typeName}}
5175Factory: {{.goFactory}}
5176Defined: {{.pos}}
5177`
5178
5179var singletonHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
5180Singleton: {{.name}}
5181Factory:   {{.goFactory}}
5182`
5183
5184func JoinPath(base, path string) string {
5185	if filepath.IsAbs(path) {
5186		return path
5187	}
5188	return filepath.Join(base, path)
5189}
5190