• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"bytes"
19	"errors"
20	"fmt"
21	"io"
22	"path/filepath"
23	"reflect"
24	"runtime"
25	"sort"
26	"strconv"
27	"strings"
28	"sync"
29	"sync/atomic"
30	"text/scanner"
31	"text/template"
32
33	"github.com/google/blueprint/parser"
34	"github.com/google/blueprint/pathtools"
35	"github.com/google/blueprint/proptools"
36)
37
38var ErrBuildActionsNotReady = errors.New("build actions are not ready")
39
40const maxErrors = 10
41
42// A Context contains all the state needed to parse a set of Blueprints files
43// and generate a Ninja file.  The process of generating a Ninja file proceeds
44// through a series of four phases.  Each phase corresponds with a some methods
45// on the Context object
46//
47//         Phase                            Methods
48//      ------------      -------------------------------------------
49//   1. Registration         RegisterModuleType, RegisterSingletonType
50//
51//   2. Parse                    ParseBlueprintsFiles, Parse
52//
53//   3. Generate            ResolveDependencies, PrepareBuildActions
54//
55//   4. Write                           WriteBuildFile
56//
57// The registration phase prepares the context to process Blueprints files
58// containing various types of modules.  The parse phase reads in one or more
59// Blueprints files and validates their contents against the module types that
60// have been registered.  The generate phase then analyzes the parsed Blueprints
61// contents to create an internal representation for the build actions that must
62// be performed.  This phase also performs validation of the module dependencies
63// and property values defined in the parsed Blueprints files.  Finally, the
64// write phase generates the Ninja manifest text based on the generated build
65// actions.
66type Context struct {
67	// set at instantiation
68	moduleFactories     map[string]ModuleFactory
69	moduleNames         map[string]*moduleGroup
70	moduleGroups        []*moduleGroup
71	moduleInfo          map[Module]*moduleInfo
72	modulesSorted       []*moduleInfo
73	singletonInfo       []*singletonInfo
74	mutatorInfo         []*mutatorInfo
75	earlyMutatorInfo    []*mutatorInfo
76	variantMutatorNames []string
77	moduleNinjaNames    map[string]*moduleGroup
78
79	depsModified uint32 // positive if a mutator modified the dependencies
80
81	dependenciesReady bool // set to true on a successful ResolveDependencies
82	buildActionsReady bool // set to true on a successful PrepareBuildActions
83
84	// set by SetIgnoreUnknownModuleTypes
85	ignoreUnknownModuleTypes bool
86
87	// set by SetAllowMissingDependencies
88	allowMissingDependencies bool
89
90	// set during PrepareBuildActions
91	pkgNames        map[*packageContext]string
92	globalVariables map[Variable]*ninjaString
93	globalPools     map[Pool]*poolDef
94	globalRules     map[Rule]*ruleDef
95
96	// set during PrepareBuildActions
97	ninjaBuildDir      *ninjaString // The builddir special Ninja variable
98	requiredNinjaMajor int          // For the ninja_required_version variable
99	requiredNinjaMinor int          // For the ninja_required_version variable
100	requiredNinjaMicro int          // For the ninja_required_version variable
101
102	// set lazily by sortedModuleNames
103	cachedSortedModuleNames []string
104
105	globs    map[string]GlobPath
106	globLock sync.Mutex
107
108	fs pathtools.FileSystem
109}
110
111// An Error describes a problem that was encountered that is related to a
112// particular location in a Blueprints file.
113type BlueprintError struct {
114	Err error            // the error that occurred
115	Pos scanner.Position // the relevant Blueprints file location
116}
117
118// A ModuleError describes a problem that was encountered that is related to a
119// particular module in a Blueprints file
120type ModuleError struct {
121	BlueprintError
122	module *moduleInfo
123}
124
125// A PropertyError describes a problem that was encountered that is related to a
126// particular property in a Blueprints file
127type PropertyError struct {
128	ModuleError
129	property string
130}
131
132func (e *BlueprintError) Error() string {
133	return fmt.Sprintf("%s: %s", e.Pos, e.Err)
134}
135
136func (e *ModuleError) Error() string {
137	return fmt.Sprintf("%s: %s: %s", e.Pos, e.module, e.Err)
138}
139
140func (e *PropertyError) Error() string {
141	return fmt.Sprintf("%s: %s: %s: %s", e.Pos, e.module, e.property, e.Err)
142}
143
144type localBuildActions struct {
145	variables []*localVariable
146	rules     []*localRule
147	buildDefs []*buildDef
148}
149
150type moduleGroup struct {
151	name      string
152	ninjaName string
153
154	modules []*moduleInfo
155}
156
157type moduleInfo struct {
158	// set during Parse
159	typeName          string
160	relBlueprintsFile string
161	pos               scanner.Position
162	propertyPos       map[string]scanner.Position
163
164	variantName       string
165	variant           variationMap
166	dependencyVariant variationMap
167
168	logicModule      Module
169	group            *moduleGroup
170	moduleProperties []interface{}
171
172	// set during ResolveDependencies
173	directDeps  []depInfo
174	missingDeps []string
175
176	// set during updateDependencies
177	reverseDeps []*moduleInfo
178	forwardDeps []*moduleInfo
179
180	// used by parallelVisitAllBottomUp
181	waitingCount int
182
183	// set during each runMutator
184	splitModules []*moduleInfo
185
186	// set during PrepareBuildActions
187	actionDefs localBuildActions
188}
189
190type depInfo struct {
191	module *moduleInfo
192	tag    DependencyTag
193}
194
195func (module *moduleInfo) Name() string {
196	return module.group.name
197}
198
199func (module *moduleInfo) String() string {
200	s := fmt.Sprintf("module %q", module.Name())
201	if module.variantName != "" {
202		s += fmt.Sprintf(" variant %q", module.variantName)
203	}
204	return s
205}
206
207// A Variation is a way that a variant of a module differs from other variants of the same module.
208// For example, two variants of the same module might have Variation{"arch","arm"} and
209// Variation{"arch","arm64"}
210type Variation struct {
211	// Mutator is the axis on which this variation applies, i.e. "arch" or "link"
212	Mutator string
213	// Variation is the name of the variation on the axis, i.e. "arm" or "arm64" for arch, or
214	// "shared" or "static" for link.
215	Variation string
216}
217
218// A variationMap stores a map of Mutator to Variation to specify a variant of a module.
219type variationMap map[string]string
220
221func (vm variationMap) clone() variationMap {
222	newVm := make(variationMap)
223	for k, v := range vm {
224		newVm[k] = v
225	}
226
227	return newVm
228}
229
230// Compare this variationMap to another one.  Returns true if the every entry in this map
231// is either the same in the other map or doesn't exist in the other map.
232func (vm variationMap) subset(other variationMap) bool {
233	for k, v1 := range vm {
234		if v2, ok := other[k]; ok && v1 != v2 {
235			return false
236		}
237	}
238	return true
239}
240
241func (vm variationMap) equal(other variationMap) bool {
242	return reflect.DeepEqual(vm, other)
243}
244
245type singletonInfo struct {
246	// set during RegisterSingletonType
247	factory   SingletonFactory
248	singleton Singleton
249	name      string
250
251	// set during PrepareBuildActions
252	actionDefs localBuildActions
253}
254
255type mutatorInfo struct {
256	// set during RegisterMutator
257	topDownMutator  TopDownMutator
258	bottomUpMutator BottomUpMutator
259	name            string
260	parallel        bool
261}
262
263// NewContext creates a new Context object.  The created context initially has
264// no module or singleton factories registered, so the RegisterModuleFactory and
265// RegisterSingletonFactory methods must be called before it can do anything
266// useful.
267func NewContext() *Context {
268	ctx := &Context{
269		moduleFactories:  make(map[string]ModuleFactory),
270		moduleNames:      make(map[string]*moduleGroup),
271		moduleInfo:       make(map[Module]*moduleInfo),
272		moduleNinjaNames: make(map[string]*moduleGroup),
273		globs:            make(map[string]GlobPath),
274		fs:               pathtools.OsFs,
275	}
276
277	ctx.RegisterBottomUpMutator("blueprint_deps", blueprintDepsMutator)
278
279	return ctx
280}
281
282// A ModuleFactory function creates a new Module object.  See the
283// Context.RegisterModuleType method for details about how a registered
284// ModuleFactory is used by a Context.
285type ModuleFactory func() (m Module, propertyStructs []interface{})
286
287// RegisterModuleType associates a module type name (which can appear in a
288// Blueprints file) with a Module factory function.  When the given module type
289// name is encountered in a Blueprints file during parsing, the Module factory
290// is invoked to instantiate a new Module object to handle the build action
291// generation for the module.  If a Mutator splits a module into multiple variants,
292// the factory is invoked again to create a new Module for each variant.
293//
294// The module type names given here must be unique for the context.  The factory
295// function should be a named function so that its package and name can be
296// included in the generated Ninja file for debugging purposes.
297//
298// The factory function returns two values.  The first is the newly created
299// Module object.  The second is a slice of pointers to that Module object's
300// properties structs.  Each properties struct is examined when parsing a module
301// definition of this type in a Blueprints file.  Exported fields of the
302// properties structs are automatically set to the property values specified in
303// the Blueprints file.  The properties struct field names determine the name of
304// the Blueprints file properties that are used - the Blueprints property name
305// matches that of the properties struct field name with the first letter
306// converted to lower-case.
307//
308// The fields of the properties struct must be either []string, a string, or
309// bool. The Context will panic if a Module gets instantiated with a properties
310// struct containing a field that is not one these supported types.
311//
312// Any properties that appear in the Blueprints files that are not built-in
313// module properties (such as "name" and "deps") and do not have a corresponding
314// field in the returned module properties struct result in an error during the
315// Context's parse phase.
316//
317// As an example, the follow code:
318//
319//   type myModule struct {
320//       properties struct {
321//           Foo string
322//           Bar []string
323//       }
324//   }
325//
326//   func NewMyModule() (blueprint.Module, []interface{}) {
327//       module := new(myModule)
328//       properties := &module.properties
329//       return module, []interface{}{properties}
330//   }
331//
332//   func main() {
333//       ctx := blueprint.NewContext()
334//       ctx.RegisterModuleType("my_module", NewMyModule)
335//       // ...
336//   }
337//
338// would support parsing a module defined in a Blueprints file as follows:
339//
340//   my_module {
341//       name: "myName",
342//       foo:  "my foo string",
343//       bar:  ["my", "bar", "strings"],
344//   }
345//
346// The factory function may be called from multiple goroutines.  Any accesses
347// to global variables must be synchronized.
348func (c *Context) RegisterModuleType(name string, factory ModuleFactory) {
349	if _, present := c.moduleFactories[name]; present {
350		panic(errors.New("module type name is already registered"))
351	}
352	c.moduleFactories[name] = factory
353}
354
355// A SingletonFactory function creates a new Singleton object.  See the
356// Context.RegisterSingletonType method for details about how a registered
357// SingletonFactory is used by a Context.
358type SingletonFactory func() Singleton
359
360// RegisterSingletonType registers a singleton type that will be invoked to
361// generate build actions.  Each registered singleton type is instantiated and
362// and invoked exactly once as part of the generate phase.  Each registered
363// singleton is invoked in registration order.
364//
365// The singleton type names given here must be unique for the context.  The
366// factory function should be a named function so that its package and name can
367// be included in the generated Ninja file for debugging purposes.
368func (c *Context) RegisterSingletonType(name string, factory SingletonFactory) {
369	for _, s := range c.singletonInfo {
370		if s.name == name {
371			panic(errors.New("singleton name is already registered"))
372		}
373	}
374
375	c.singletonInfo = append(c.singletonInfo, &singletonInfo{
376		factory:   factory,
377		singleton: factory(),
378		name:      name,
379	})
380}
381
382func singletonPkgPath(singleton Singleton) string {
383	typ := reflect.TypeOf(singleton)
384	for typ.Kind() == reflect.Ptr {
385		typ = typ.Elem()
386	}
387	return typ.PkgPath()
388}
389
390func singletonTypeName(singleton Singleton) string {
391	typ := reflect.TypeOf(singleton)
392	for typ.Kind() == reflect.Ptr {
393		typ = typ.Elem()
394	}
395	return typ.PkgPath() + "." + typ.Name()
396}
397
398// RegisterTopDownMutator registers a mutator that will be invoked to propagate dependency info
399// top-down between Modules.  Each registered mutator is invoked in registration order (mixing
400// TopDownMutators and BottomUpMutators) once per Module, and the invocation on any module will
401// have returned before it is in invoked on any of its dependencies.
402//
403// The mutator type names given here must be unique to all top down mutators in
404// the Context.
405//
406// Returns a MutatorHandle, on which Parallel can be called to set the mutator to visit modules in
407// parallel while maintaining ordering.
408func (c *Context) RegisterTopDownMutator(name string, mutator TopDownMutator) MutatorHandle {
409	for _, m := range c.mutatorInfo {
410		if m.name == name && m.topDownMutator != nil {
411			panic(fmt.Errorf("mutator name %s is already registered", name))
412		}
413	}
414
415	info := &mutatorInfo{
416		topDownMutator: mutator,
417		name:           name,
418	}
419
420	c.mutatorInfo = append(c.mutatorInfo, info)
421
422	return info
423}
424
425// RegisterBottomUpMutator registers a mutator that will be invoked to split Modules into variants.
426// Each registered mutator is invoked in registration order (mixing TopDownMutators and
427// BottomUpMutators) once per Module, will not be invoked on a module until the invocations on all
428// of the modules dependencies have returned.
429//
430// The mutator type names given here must be unique to all bottom up or early
431// mutators in the Context.
432//
433// Returns a MutatorHandle, on which Parallel can be called to set the mutator to visit modules in
434// parallel while maintaining ordering.
435func (c *Context) RegisterBottomUpMutator(name string, mutator BottomUpMutator) MutatorHandle {
436	for _, m := range c.variantMutatorNames {
437		if m == name {
438			panic(fmt.Errorf("mutator name %s is already registered", name))
439		}
440	}
441
442	info := &mutatorInfo{
443		bottomUpMutator: mutator,
444		name:            name,
445	}
446	c.mutatorInfo = append(c.mutatorInfo, info)
447
448	c.variantMutatorNames = append(c.variantMutatorNames, name)
449
450	return info
451}
452
453type MutatorHandle interface {
454	// Set the mutator to visit modules in parallel while maintaining ordering.  Calling any
455	// method on the mutator context is thread-safe, but the mutator must handle synchronization
456	// for any modifications to global state or any modules outside the one it was invoked on.
457	Parallel() MutatorHandle
458}
459
460func (mutator *mutatorInfo) Parallel() MutatorHandle {
461	mutator.parallel = true
462	return mutator
463}
464
465// RegisterEarlyMutator registers a mutator that will be invoked to split
466// Modules into multiple variant Modules before any dependencies have been
467// created.  Each registered mutator is invoked in registration order once
468// per Module (including each variant from previous early mutators).  Module
469// order is unpredictable.
470//
471// In order for dependencies to be satisifed in a later pass, all dependencies
472// of a module either must have an identical variant or must have no variations.
473//
474// The mutator type names given here must be unique to all bottom up or early
475// mutators in the Context.
476//
477// Deprecated, use a BottomUpMutator instead.  The only difference between
478// EarlyMutator and BottomUpMutator is that EarlyMutator runs before the
479// deprecated DynamicDependencies.
480func (c *Context) RegisterEarlyMutator(name string, mutator EarlyMutator) {
481	for _, m := range c.variantMutatorNames {
482		if m == name {
483			panic(fmt.Errorf("mutator name %s is already registered", name))
484		}
485	}
486
487	c.earlyMutatorInfo = append(c.earlyMutatorInfo, &mutatorInfo{
488		bottomUpMutator: func(mctx BottomUpMutatorContext) {
489			mutator(mctx)
490		},
491		name: name,
492	})
493
494	c.variantMutatorNames = append(c.variantMutatorNames, name)
495}
496
497// SetIgnoreUnknownModuleTypes sets the behavior of the context in the case
498// where it encounters an unknown module type while parsing Blueprints files. By
499// default, the context will report unknown module types as an error.  If this
500// method is called with ignoreUnknownModuleTypes set to true then the context
501// will silently ignore unknown module types.
502//
503// This method should generally not be used.  It exists to facilitate the
504// bootstrapping process.
505func (c *Context) SetIgnoreUnknownModuleTypes(ignoreUnknownModuleTypes bool) {
506	c.ignoreUnknownModuleTypes = ignoreUnknownModuleTypes
507}
508
509// SetAllowMissingDependencies changes the behavior of Blueprint to ignore
510// unresolved dependencies.  If the module's GenerateBuildActions calls
511// ModuleContext.GetMissingDependencies Blueprint will not emit any errors
512// for missing dependencies.
513func (c *Context) SetAllowMissingDependencies(allowMissingDependencies bool) {
514	c.allowMissingDependencies = allowMissingDependencies
515}
516
517// Parse parses a single Blueprints file from r, creating Module objects for
518// each of the module definitions encountered.  If the Blueprints file contains
519// an assignment to the "subdirs" variable, then the subdirectories listed are
520// searched for Blueprints files returned in the subBlueprints return value.
521// If the Blueprints file contains an assignment to the "build" variable, then
522// the file listed are returned in the subBlueprints return value.
523//
524// rootDir specifies the path to the root directory of the source tree, while
525// filename specifies the path to the Blueprints file.  These paths are used for
526// error reporting and for determining the module's directory.
527func (c *Context) parse(rootDir, filename string, r io.Reader,
528	scope *parser.Scope) (file *parser.File, subBlueprints []stringAndScope, errs []error) {
529
530	relBlueprintsFile, err := filepath.Rel(rootDir, filename)
531	if err != nil {
532		return nil, nil, []error{err}
533	}
534
535	scope = parser.NewScope(scope)
536	scope.Remove("subdirs")
537	scope.Remove("optional_subdirs")
538	scope.Remove("build")
539	file, errs = parser.ParseAndEval(filename, r, scope)
540	if len(errs) > 0 {
541		for i, err := range errs {
542			if parseErr, ok := err.(*parser.ParseError); ok {
543				err = &BlueprintError{
544					Err: parseErr.Err,
545					Pos: parseErr.Pos,
546				}
547				errs[i] = err
548			}
549		}
550
551		// If there were any parse errors don't bother trying to interpret the
552		// result.
553		return nil, nil, errs
554	}
555	file.Name = relBlueprintsFile
556
557	subdirs, subdirsPos, err := getLocalStringListFromScope(scope, "subdirs")
558	if err != nil {
559		errs = append(errs, err)
560	}
561
562	optionalSubdirs, optionalSubdirsPos, err := getLocalStringListFromScope(scope, "optional_subdirs")
563	if err != nil {
564		errs = append(errs, err)
565	}
566
567	build, buildPos, err := getLocalStringListFromScope(scope, "build")
568	if err != nil {
569		errs = append(errs, err)
570	}
571
572	subBlueprintsName, _, err := getStringFromScope(scope, "subname")
573	if err != nil {
574		errs = append(errs, err)
575	}
576
577	if subBlueprintsName == "" {
578		subBlueprintsName = "Blueprints"
579	}
580
581	var blueprints []string
582
583	newBlueprints, newErrs := c.findBuildBlueprints(filepath.Dir(filename), build, buildPos)
584	blueprints = append(blueprints, newBlueprints...)
585	errs = append(errs, newErrs...)
586
587	newBlueprints, newErrs = c.findSubdirBlueprints(filepath.Dir(filename), subdirs, subdirsPos,
588		subBlueprintsName, false)
589	blueprints = append(blueprints, newBlueprints...)
590	errs = append(errs, newErrs...)
591
592	newBlueprints, newErrs = c.findSubdirBlueprints(filepath.Dir(filename), optionalSubdirs,
593		optionalSubdirsPos, subBlueprintsName, true)
594	blueprints = append(blueprints, newBlueprints...)
595	errs = append(errs, newErrs...)
596
597	subBlueprintsAndScope := make([]stringAndScope, len(blueprints))
598	for i, b := range blueprints {
599		subBlueprintsAndScope[i] = stringAndScope{b, scope}
600	}
601
602	return file, subBlueprintsAndScope, errs
603}
604
605type stringAndScope struct {
606	string
607	*parser.Scope
608}
609
610// ParseBlueprintsFiles parses a set of Blueprints files starting with the file
611// at rootFile.  When it encounters a Blueprints file with a set of subdirs
612// listed it recursively parses any Blueprints files found in those
613// subdirectories.
614//
615// If no errors are encountered while parsing the files, the list of paths on
616// which the future output will depend is returned.  This list will include both
617// Blueprints file paths as well as directory paths for cases where wildcard
618// subdirs are found.
619func (c *Context) ParseBlueprintsFiles(rootFile string) (deps []string,
620	errs []error) {
621
622	c.dependenciesReady = false
623
624	moduleCh := make(chan *moduleInfo)
625	errsCh := make(chan []error)
626	doneCh := make(chan struct{})
627	var numErrs uint32
628	var numGoroutines int32
629
630	// handler must be reentrant
631	handler := func(file *parser.File) {
632		if atomic.LoadUint32(&numErrs) > maxErrors {
633			return
634		}
635
636		atomic.AddInt32(&numGoroutines, 1)
637		go func() {
638			for _, def := range file.Defs {
639				var module *moduleInfo
640				var errs []error
641				switch def := def.(type) {
642				case *parser.Module:
643					module, errs = c.processModuleDef(def, file.Name)
644				case *parser.Assignment:
645					// Already handled via Scope object
646				default:
647					panic("unknown definition type")
648				}
649
650				if len(errs) > 0 {
651					atomic.AddUint32(&numErrs, uint32(len(errs)))
652					errsCh <- errs
653				} else if module != nil {
654					moduleCh <- module
655				}
656			}
657			doneCh <- struct{}{}
658		}()
659	}
660
661	atomic.AddInt32(&numGoroutines, 1)
662	go func() {
663		var errs []error
664		deps, errs = c.WalkBlueprintsFiles(rootFile, handler)
665		if len(errs) > 0 {
666			errsCh <- errs
667		}
668		doneCh <- struct{}{}
669	}()
670
671loop:
672	for {
673		select {
674		case newErrs := <-errsCh:
675			errs = append(errs, newErrs...)
676		case module := <-moduleCh:
677			newErrs := c.addModule(module)
678			if len(newErrs) > 0 {
679				errs = append(errs, newErrs...)
680			}
681		case <-doneCh:
682			n := atomic.AddInt32(&numGoroutines, -1)
683			if n == 0 {
684				break loop
685			}
686		}
687	}
688
689	return deps, errs
690}
691
692type FileHandler func(*parser.File)
693
694// Walk a set of Blueprints files starting with the file at rootFile, calling handler on each.
695// When it encounters a Blueprints file with a set of subdirs listed it recursively parses any
696// Blueprints files found in those subdirectories.  handler will be called from a goroutine, so
697// it must be reentrant.
698//
699// If no errors are encountered while parsing the files, the list of paths on
700// which the future output will depend is returned.  This list will include both
701// Blueprints file paths as well as directory paths for cases where wildcard
702// subdirs are found.
703func (c *Context) WalkBlueprintsFiles(rootFile string, handler FileHandler) (deps []string,
704	errs []error) {
705
706	rootDir := filepath.Dir(rootFile)
707
708	blueprintsSet := make(map[string]bool)
709
710	// Channels to receive data back from parseBlueprintsFile goroutines
711	blueprintsCh := make(chan stringAndScope)
712	errsCh := make(chan []error)
713	fileCh := make(chan *parser.File)
714	depsCh := make(chan string)
715
716	// Channel to notify main loop that a parseBlueprintsFile goroutine has finished
717	doneCh := make(chan struct{})
718
719	// Number of outstanding goroutines to wait for
720	count := 0
721
722	startParseBlueprintsFile := func(blueprint stringAndScope) {
723		if blueprintsSet[blueprint.string] {
724			return
725		}
726		blueprintsSet[blueprint.string] = true
727		count++
728		go func() {
729			c.parseBlueprintsFile(blueprint.string, blueprint.Scope, rootDir,
730				errsCh, fileCh, blueprintsCh, depsCh)
731			doneCh <- struct{}{}
732		}()
733	}
734
735	tooManyErrors := false
736
737	startParseBlueprintsFile(stringAndScope{rootFile, nil})
738
739	var pending []stringAndScope
740
741loop:
742	for {
743		if len(errs) > maxErrors {
744			tooManyErrors = true
745		}
746
747		select {
748		case newErrs := <-errsCh:
749			errs = append(errs, newErrs...)
750		case dep := <-depsCh:
751			deps = append(deps, dep)
752		case file := <-fileCh:
753			handler(file)
754		case blueprint := <-blueprintsCh:
755			if tooManyErrors {
756				continue
757			}
758			// Limit concurrent calls to parseBlueprintFiles to 200
759			// Darwin has a default limit of 256 open files
760			if count >= 200 {
761				pending = append(pending, blueprint)
762				continue
763			}
764			startParseBlueprintsFile(blueprint)
765		case <-doneCh:
766			count--
767			if len(pending) > 0 {
768				startParseBlueprintsFile(pending[len(pending)-1])
769				pending = pending[:len(pending)-1]
770			}
771			if count == 0 {
772				break loop
773			}
774		}
775	}
776
777	return
778}
779
780// MockFileSystem causes the Context to replace all reads with accesses to the provided map of
781// filenames to contents stored as a byte slice.
782func (c *Context) MockFileSystem(files map[string][]byte) {
783	c.fs = pathtools.MockFs(files)
784}
785
786// parseBlueprintFile parses a single Blueprints file, returning any errors through
787// errsCh, any defined modules through modulesCh, any sub-Blueprints files through
788// blueprintsCh, and any dependencies on Blueprints files or directories through
789// depsCh.
790func (c *Context) parseBlueprintsFile(filename string, scope *parser.Scope, rootDir string,
791	errsCh chan<- []error, fileCh chan<- *parser.File, blueprintsCh chan<- stringAndScope,
792	depsCh chan<- string) {
793
794	f, err := c.fs.Open(filename)
795	if err != nil {
796		errsCh <- []error{err}
797		return
798	}
799	defer func() {
800		err = f.Close()
801		if err != nil {
802			errsCh <- []error{err}
803		}
804	}()
805
806	file, subBlueprints, errs := c.parse(rootDir, filename, f, scope)
807	if len(errs) > 0 {
808		errsCh <- errs
809	} else {
810		fileCh <- file
811	}
812
813	for _, b := range subBlueprints {
814		blueprintsCh <- b
815		depsCh <- b.string
816	}
817}
818
819func (c *Context) findBuildBlueprints(dir string, build []string,
820	buildPos scanner.Position) ([]string, []error) {
821
822	var blueprints []string
823	var errs []error
824
825	for _, file := range build {
826		pattern := filepath.Join(dir, file)
827		var matches []string
828		var err error
829
830		matches, err = c.glob(pattern, nil)
831
832		if err != nil {
833			errs = append(errs, &BlueprintError{
834				Err: fmt.Errorf("%q: %s", pattern, err.Error()),
835				Pos: buildPos,
836			})
837			continue
838		}
839
840		if len(matches) == 0 {
841			errs = append(errs, &BlueprintError{
842				Err: fmt.Errorf("%q: not found", pattern),
843				Pos: buildPos,
844			})
845		}
846
847		for _, foundBlueprints := range matches {
848			blueprints = append(blueprints, foundBlueprints)
849		}
850	}
851
852	return blueprints, errs
853}
854
855func (c *Context) findSubdirBlueprints(dir string, subdirs []string, subdirsPos scanner.Position,
856	subBlueprintsName string, optional bool) ([]string, []error) {
857
858	var blueprints []string
859	var errs []error
860
861	for _, subdir := range subdirs {
862		pattern := filepath.Join(dir, subdir, subBlueprintsName)
863		var matches []string
864		var err error
865
866		matches, err = c.glob(pattern, nil)
867
868		if err != nil {
869			errs = append(errs, &BlueprintError{
870				Err: fmt.Errorf("%q: %s", pattern, err.Error()),
871				Pos: subdirsPos,
872			})
873			continue
874		}
875
876		if len(matches) == 0 && !optional {
877			errs = append(errs, &BlueprintError{
878				Err: fmt.Errorf("%q: not found", pattern),
879				Pos: subdirsPos,
880			})
881		}
882
883		for _, subBlueprints := range matches {
884			blueprints = append(blueprints, subBlueprints)
885		}
886	}
887
888	return blueprints, errs
889}
890
891func getLocalStringListFromScope(scope *parser.Scope, v string) ([]string, scanner.Position, error) {
892	if assignment, local := scope.Get(v); assignment == nil || !local {
893		return nil, scanner.Position{}, nil
894	} else {
895		switch value := assignment.Value.Eval().(type) {
896		case *parser.List:
897			ret := make([]string, 0, len(value.Values))
898
899			for _, listValue := range value.Values {
900				s, ok := listValue.(*parser.String)
901				if !ok {
902					// The parser should not produce this.
903					panic("non-string value found in list")
904				}
905
906				ret = append(ret, s.Value)
907			}
908
909			return ret, assignment.EqualsPos, nil
910		case *parser.Bool, *parser.String:
911			return nil, scanner.Position{}, &BlueprintError{
912				Err: fmt.Errorf("%q must be a list of strings", v),
913				Pos: assignment.EqualsPos,
914			}
915		default:
916			panic(fmt.Errorf("unknown value type: %d", assignment.Value.Type))
917		}
918	}
919}
920
921func getStringFromScope(scope *parser.Scope, v string) (string, scanner.Position, error) {
922	if assignment, _ := scope.Get(v); assignment == nil {
923		return "", scanner.Position{}, nil
924	} else {
925		switch value := assignment.Value.Eval().(type) {
926		case *parser.String:
927			return value.Value, assignment.EqualsPos, nil
928		case *parser.Bool, *parser.List:
929			return "", scanner.Position{}, &BlueprintError{
930				Err: fmt.Errorf("%q must be a string", v),
931				Pos: assignment.EqualsPos,
932			}
933		default:
934			panic(fmt.Errorf("unknown value type: %d", assignment.Value.Type))
935		}
936	}
937}
938
939// Clones a build logic module by calling the factory method for its module type, and then cloning
940// property values.  Any values stored in the module object that are not stored in properties
941// structs will be lost.
942func (c *Context) cloneLogicModule(origModule *moduleInfo) (Module, []interface{}) {
943	typeName := origModule.typeName
944	factory, ok := c.moduleFactories[typeName]
945	if !ok {
946		panic(fmt.Sprintf("unrecognized module type %q during cloning", typeName))
947	}
948
949	newLogicModule, newProperties := factory()
950
951	if len(newProperties) != len(origModule.moduleProperties) {
952		panic("mismatched properties array length in " + origModule.Name())
953	}
954
955	for i := range newProperties {
956		dst := reflect.ValueOf(newProperties[i]).Elem()
957		src := reflect.ValueOf(origModule.moduleProperties[i]).Elem()
958
959		proptools.CopyProperties(dst, src)
960	}
961
962	return newLogicModule, newProperties
963}
964
965func (c *Context) createVariations(origModule *moduleInfo, mutatorName string,
966	variationNames []string) ([]*moduleInfo, []error) {
967
968	if len(variationNames) == 0 {
969		panic(fmt.Errorf("mutator %q passed zero-length variation list for module %q",
970			mutatorName, origModule.Name()))
971	}
972
973	newModules := []*moduleInfo{}
974
975	var errs []error
976
977	for i, variationName := range variationNames {
978		var newLogicModule Module
979		var newProperties []interface{}
980
981		if i == 0 {
982			// Reuse the existing module for the first new variant
983			// This both saves creating a new module, and causes the insertion in c.moduleInfo below
984			// with logicModule as the key to replace the original entry in c.moduleInfo
985			newLogicModule, newProperties = origModule.logicModule, origModule.moduleProperties
986		} else {
987			newLogicModule, newProperties = c.cloneLogicModule(origModule)
988		}
989
990		newVariant := origModule.variant.clone()
991		newVariant[mutatorName] = variationName
992
993		m := *origModule
994		newModule := &m
995		newModule.directDeps = append([]depInfo{}, origModule.directDeps...)
996		newModule.logicModule = newLogicModule
997		newModule.variant = newVariant
998		newModule.dependencyVariant = origModule.dependencyVariant.clone()
999		newModule.moduleProperties = newProperties
1000
1001		if variationName != "" {
1002			if newModule.variantName == "" {
1003				newModule.variantName = variationName
1004			} else {
1005				newModule.variantName += "_" + variationName
1006			}
1007		}
1008
1009		newModules = append(newModules, newModule)
1010
1011		newErrs := c.convertDepsToVariation(newModule, mutatorName, variationName)
1012		if len(newErrs) > 0 {
1013			errs = append(errs, newErrs...)
1014		}
1015	}
1016
1017	// Mark original variant as invalid.  Modules that depend on this module will still
1018	// depend on origModule, but we'll fix it when the mutator is called on them.
1019	origModule.logicModule = nil
1020	origModule.splitModules = newModules
1021
1022	atomic.AddUint32(&c.depsModified, 1)
1023
1024	return newModules, errs
1025}
1026
1027func (c *Context) convertDepsToVariation(module *moduleInfo,
1028	mutatorName, variationName string) (errs []error) {
1029
1030	for i, dep := range module.directDeps {
1031		if dep.module.logicModule == nil {
1032			var newDep *moduleInfo
1033			for _, m := range dep.module.splitModules {
1034				if m.variant[mutatorName] == variationName {
1035					newDep = m
1036					break
1037				}
1038			}
1039			if newDep == nil {
1040				errs = append(errs, &BlueprintError{
1041					Err: fmt.Errorf("failed to find variation %q for module %q needed by %q",
1042						variationName, dep.module.Name(), module.Name()),
1043					Pos: module.pos,
1044				})
1045				continue
1046			}
1047			module.directDeps[i].module = newDep
1048		}
1049	}
1050
1051	return errs
1052}
1053
1054func (c *Context) prettyPrintVariant(variant variationMap) string {
1055	names := make([]string, 0, len(variant))
1056	for _, m := range c.variantMutatorNames {
1057		if v, ok := variant[m]; ok {
1058			names = append(names, m+":"+v)
1059		}
1060	}
1061
1062	return strings.Join(names, ", ")
1063}
1064
1065func (c *Context) processModuleDef(moduleDef *parser.Module,
1066	relBlueprintsFile string) (*moduleInfo, []error) {
1067
1068	factory, ok := c.moduleFactories[moduleDef.Type]
1069	if !ok {
1070		if c.ignoreUnknownModuleTypes {
1071			return nil, nil
1072		}
1073
1074		return nil, []error{
1075			&BlueprintError{
1076				Err: fmt.Errorf("unrecognized module type %q", moduleDef.Type),
1077				Pos: moduleDef.TypePos,
1078			},
1079		}
1080	}
1081
1082	logicModule, properties := factory()
1083
1084	module := &moduleInfo{
1085		logicModule:       logicModule,
1086		typeName:          moduleDef.Type,
1087		relBlueprintsFile: relBlueprintsFile,
1088	}
1089
1090	module.moduleProperties = properties
1091
1092	propertyMap, errs := unpackProperties(moduleDef.Properties, properties...)
1093	if len(errs) > 0 {
1094		return nil, errs
1095	}
1096
1097	module.pos = moduleDef.TypePos
1098	module.propertyPos = make(map[string]scanner.Position)
1099	for name, propertyDef := range propertyMap {
1100		module.propertyPos[name] = propertyDef.ColonPos
1101	}
1102
1103	return module, nil
1104}
1105
1106func (c *Context) addModule(module *moduleInfo) []error {
1107	name := module.logicModule.Name()
1108	c.moduleInfo[module.logicModule] = module
1109
1110	if group, present := c.moduleNames[name]; present {
1111		return []error{
1112			&BlueprintError{
1113				Err: fmt.Errorf("module %q already defined", name),
1114				Pos: module.pos,
1115			},
1116			&BlueprintError{
1117				Err: fmt.Errorf("<-- previous definition here"),
1118				Pos: group.modules[0].pos,
1119			},
1120		}
1121	}
1122
1123	ninjaName := toNinjaName(name)
1124
1125	// The sanitizing in toNinjaName can result in collisions, uniquify the name if it
1126	// already exists
1127	for i := 0; c.moduleNinjaNames[ninjaName] != nil; i++ {
1128		ninjaName = toNinjaName(name) + strconv.Itoa(i)
1129	}
1130
1131	group := &moduleGroup{
1132		name:      name,
1133		ninjaName: ninjaName,
1134		modules:   []*moduleInfo{module},
1135	}
1136	module.group = group
1137	c.moduleNames[name] = group
1138	c.moduleNinjaNames[ninjaName] = group
1139	c.moduleGroups = append(c.moduleGroups, group)
1140
1141	return nil
1142}
1143
1144// ResolveDependencies checks that the dependencies specified by all of the
1145// modules defined in the parsed Blueprints files are valid.  This means that
1146// the modules depended upon are defined and that no circular dependencies
1147// exist.
1148func (c *Context) ResolveDependencies(config interface{}) []error {
1149	errs := c.updateDependencies()
1150	if len(errs) > 0 {
1151		return errs
1152	}
1153
1154	errs = c.runMutators(config)
1155	if len(errs) > 0 {
1156		return errs
1157	}
1158
1159	c.cloneModules()
1160
1161	c.dependenciesReady = true
1162	return nil
1163}
1164
1165// Default dependencies handling.  If the module implements the (deprecated)
1166// DynamicDependerModule interface then this set consists of the union of those
1167// module names returned by its DynamicDependencies method and those added by calling
1168// AddDependencies or AddVariationDependencies on DynamicDependencyModuleContext.
1169func blueprintDepsMutator(ctx BottomUpMutatorContext) {
1170	if dynamicDepender, ok := ctx.Module().(DynamicDependerModule); ok {
1171		func() {
1172			defer func() {
1173				if r := recover(); r != nil {
1174					ctx.error(newPanicErrorf(r, "DynamicDependencies for %s", ctx.moduleInfo()))
1175				}
1176			}()
1177			dynamicDeps := dynamicDepender.DynamicDependencies(ctx)
1178
1179			if ctx.Failed() {
1180				return
1181			}
1182
1183			ctx.AddDependency(ctx.Module(), nil, dynamicDeps...)
1184		}()
1185	}
1186}
1187
1188// findMatchingVariant searches the moduleGroup for a module with the same variant as module,
1189// and returns the matching module, or nil if one is not found.
1190func (c *Context) findMatchingVariant(module *moduleInfo, possible []*moduleInfo) *moduleInfo {
1191	if len(possible) == 1 {
1192		return possible[0]
1193	} else {
1194		for _, m := range possible {
1195			if m.variant.equal(module.dependencyVariant) {
1196				return m
1197			}
1198		}
1199	}
1200
1201	return nil
1202}
1203
1204func (c *Context) addDependency(module *moduleInfo, tag DependencyTag, depName string) []error {
1205	if _, ok := tag.(BaseDependencyTag); ok {
1206		panic("BaseDependencyTag is not allowed to be used directly!")
1207	}
1208
1209	if depName == module.Name() {
1210		return []error{&BlueprintError{
1211			Err: fmt.Errorf("%q depends on itself", depName),
1212			Pos: module.pos,
1213		}}
1214	}
1215
1216	possibleDeps := c.modulesFromName(depName)
1217	if possibleDeps == nil {
1218		if c.allowMissingDependencies {
1219			module.missingDeps = append(module.missingDeps, depName)
1220			return nil
1221		}
1222		return []error{&BlueprintError{
1223			Err: fmt.Errorf("%q depends on undefined module %q",
1224				module.Name(), depName),
1225			Pos: module.pos,
1226		}}
1227	}
1228
1229	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
1230		for _, dep := range module.directDeps {
1231			if m == dep.module {
1232				// TODO(ccross): what if adding a dependency with a different tag?
1233				return nil
1234			}
1235		}
1236		module.directDeps = append(module.directDeps, depInfo{m, tag})
1237		atomic.AddUint32(&c.depsModified, 1)
1238		return nil
1239	}
1240
1241	variants := make([]string, len(possibleDeps))
1242	for i, mod := range possibleDeps {
1243		variants[i] = c.prettyPrintVariant(mod.variant)
1244	}
1245	sort.Strings(variants)
1246
1247	return []error{&BlueprintError{
1248		Err: fmt.Errorf("dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1249			depName, module.Name(),
1250			c.prettyPrintVariant(module.dependencyVariant),
1251			strings.Join(variants, "\n  ")),
1252		Pos: module.pos,
1253	}}
1254}
1255
1256func (c *Context) findReverseDependency(module *moduleInfo, destName string) (*moduleInfo, []error) {
1257	if destName == module.Name() {
1258		return nil, []error{&BlueprintError{
1259			Err: fmt.Errorf("%q depends on itself", destName),
1260			Pos: module.pos,
1261		}}
1262	}
1263
1264	possibleDeps := c.modulesFromName(destName)
1265	if possibleDeps == nil {
1266		return nil, []error{&BlueprintError{
1267			Err: fmt.Errorf("%q has a reverse dependency on undefined module %q",
1268				module.Name(), destName),
1269			Pos: module.pos,
1270		}}
1271	}
1272
1273	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
1274		return m, nil
1275	}
1276
1277	variants := make([]string, len(possibleDeps))
1278	for i, mod := range possibleDeps {
1279		variants[i] = c.prettyPrintVariant(mod.variant)
1280	}
1281	sort.Strings(variants)
1282
1283	return nil, []error{&BlueprintError{
1284		Err: fmt.Errorf("reverse dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1285			destName, module.Name(),
1286			c.prettyPrintVariant(module.dependencyVariant),
1287			strings.Join(variants, "\n  ")),
1288		Pos: module.pos,
1289	}}
1290}
1291
1292func (c *Context) addVariationDependency(module *moduleInfo, variations []Variation,
1293	tag DependencyTag, depName string, far bool) []error {
1294	if _, ok := tag.(BaseDependencyTag); ok {
1295		panic("BaseDependencyTag is not allowed to be used directly!")
1296	}
1297
1298	possibleDeps := c.modulesFromName(depName)
1299	if possibleDeps == nil {
1300		if c.allowMissingDependencies {
1301			module.missingDeps = append(module.missingDeps, depName)
1302			return nil
1303		}
1304		return []error{&BlueprintError{
1305			Err: fmt.Errorf("%q depends on undefined module %q",
1306				module.Name(), depName),
1307			Pos: module.pos,
1308		}}
1309	}
1310
1311	// We can't just append variant.Variant to module.dependencyVariants.variantName and
1312	// compare the strings because the result won't be in mutator registration order.
1313	// Create a new map instead, and then deep compare the maps.
1314	var newVariant variationMap
1315	if !far {
1316		newVariant = module.dependencyVariant.clone()
1317	} else {
1318		newVariant = make(variationMap)
1319	}
1320	for _, v := range variations {
1321		newVariant[v.Mutator] = v.Variation
1322	}
1323
1324	for _, m := range possibleDeps {
1325		var found bool
1326		if far {
1327			found = m.variant.subset(newVariant)
1328		} else {
1329			found = m.variant.equal(newVariant)
1330		}
1331		if found {
1332			if module == m {
1333				return []error{&BlueprintError{
1334					Err: fmt.Errorf("%q depends on itself", depName),
1335					Pos: module.pos,
1336				}}
1337			}
1338			// AddVariationDependency allows adding a dependency on itself, but only if
1339			// that module is earlier in the module list than this one, since we always
1340			// run GenerateBuildActions in order for the variants of a module
1341			if m.group == module.group && beforeInModuleList(module, m, module.group.modules) {
1342				return []error{&BlueprintError{
1343					Err: fmt.Errorf("%q depends on later version of itself", depName),
1344					Pos: module.pos,
1345				}}
1346			}
1347			module.directDeps = append(module.directDeps, depInfo{m, tag})
1348			atomic.AddUint32(&c.depsModified, 1)
1349			return nil
1350		}
1351	}
1352
1353	variants := make([]string, len(possibleDeps))
1354	for i, mod := range possibleDeps {
1355		variants[i] = c.prettyPrintVariant(mod.variant)
1356	}
1357	sort.Strings(variants)
1358
1359	return []error{&BlueprintError{
1360		Err: fmt.Errorf("dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1361			depName, module.Name(),
1362			c.prettyPrintVariant(newVariant),
1363			strings.Join(variants, "\n  ")),
1364		Pos: module.pos,
1365	}}
1366}
1367
1368func (c *Context) addInterVariantDependency(origModule *moduleInfo, tag DependencyTag,
1369	from, to Module) {
1370	if _, ok := tag.(BaseDependencyTag); ok {
1371		panic("BaseDependencyTag is not allowed to be used directly!")
1372	}
1373
1374	var fromInfo, toInfo *moduleInfo
1375	for _, m := range origModule.splitModules {
1376		if m.logicModule == from {
1377			fromInfo = m
1378		}
1379		if m.logicModule == to {
1380			toInfo = m
1381			if fromInfo != nil {
1382				panic(fmt.Errorf("%q depends on later version of itself", origModule.Name()))
1383			}
1384		}
1385	}
1386
1387	if fromInfo == nil || toInfo == nil {
1388		panic(fmt.Errorf("AddInterVariantDependency called for module %q on invalid variant",
1389			origModule.Name()))
1390	}
1391
1392	fromInfo.directDeps = append(fromInfo.directDeps, depInfo{toInfo, tag})
1393	atomic.AddUint32(&c.depsModified, 1)
1394}
1395
1396type visitOrderer interface {
1397	// returns the number of modules that this module needs to wait for
1398	waitCount(module *moduleInfo) int
1399	// returns the list of modules that are waiting for this module
1400	propagate(module *moduleInfo) []*moduleInfo
1401	// visit modules in order
1402	visit(modules []*moduleInfo, visit func(*moduleInfo) bool)
1403}
1404
1405type bottomUpVisitorImpl struct{}
1406
1407func (bottomUpVisitorImpl) waitCount(module *moduleInfo) int {
1408	return len(module.forwardDeps)
1409}
1410
1411func (bottomUpVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
1412	return module.reverseDeps
1413}
1414
1415func (bottomUpVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo) bool) {
1416	for _, module := range modules {
1417		if visit(module) {
1418			return
1419		}
1420	}
1421}
1422
1423type topDownVisitorImpl struct{}
1424
1425func (topDownVisitorImpl) waitCount(module *moduleInfo) int {
1426	return len(module.reverseDeps)
1427}
1428
1429func (topDownVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
1430	return module.forwardDeps
1431}
1432
1433func (topDownVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo) bool) {
1434	for i := 0; i < len(modules); i++ {
1435		module := modules[len(modules)-1-i]
1436		if visit(module) {
1437			return
1438		}
1439	}
1440}
1441
1442var (
1443	bottomUpVisitor bottomUpVisitorImpl
1444	topDownVisitor  topDownVisitorImpl
1445)
1446
1447// Calls visit on each module, guaranteeing that visit is not called on a module until visit on all
1448// of its dependencies has finished.
1449func (c *Context) parallelVisit(order visitOrderer, visit func(group *moduleInfo) bool) {
1450	doneCh := make(chan *moduleInfo)
1451	cancelCh := make(chan bool)
1452	count := 0
1453	cancel := false
1454
1455	for _, module := range c.modulesSorted {
1456		module.waitingCount = order.waitCount(module)
1457	}
1458
1459	visitOne := func(module *moduleInfo) {
1460		count++
1461		go func() {
1462			ret := visit(module)
1463			if ret {
1464				cancelCh <- true
1465			}
1466			doneCh <- module
1467		}()
1468	}
1469
1470	for _, module := range c.modulesSorted {
1471		if module.waitingCount == 0 {
1472			visitOne(module)
1473		}
1474	}
1475
1476	for count > 0 {
1477		select {
1478		case cancel = <-cancelCh:
1479		case doneModule := <-doneCh:
1480			if !cancel {
1481				for _, module := range order.propagate(doneModule) {
1482					module.waitingCount--
1483					if module.waitingCount == 0 {
1484						visitOne(module)
1485					}
1486				}
1487			}
1488			count--
1489		}
1490	}
1491}
1492
1493// updateDependencies recursively walks the module dependency graph and updates
1494// additional fields based on the dependencies.  It builds a sorted list of modules
1495// such that dependencies of a module always appear first, and populates reverse
1496// dependency links and counts of total dependencies.  It also reports errors when
1497// it encounters dependency cycles.  This should called after resolveDependencies,
1498// as well as after any mutator pass has called addDependency
1499func (c *Context) updateDependencies() (errs []error) {
1500	visited := make(map[*moduleInfo]bool)  // modules that were already checked
1501	checking := make(map[*moduleInfo]bool) // modules actively being checked
1502
1503	sorted := make([]*moduleInfo, 0, len(c.moduleInfo))
1504
1505	var check func(group *moduleInfo) []*moduleInfo
1506
1507	cycleError := func(cycle []*moduleInfo) {
1508		// We are the "start" of the cycle, so we're responsible
1509		// for generating the errors.  The cycle list is in
1510		// reverse order because all the 'check' calls append
1511		// their own module to the list.
1512		errs = append(errs, &BlueprintError{
1513			Err: fmt.Errorf("encountered dependency cycle:"),
1514			Pos: cycle[len(cycle)-1].pos,
1515		})
1516
1517		// Iterate backwards through the cycle list.
1518		curModule := cycle[0]
1519		for i := len(cycle) - 1; i >= 0; i-- {
1520			nextModule := cycle[i]
1521			errs = append(errs, &BlueprintError{
1522				Err: fmt.Errorf("    %q depends on %q",
1523					curModule.Name(),
1524					nextModule.Name()),
1525				Pos: curModule.pos,
1526			})
1527			curModule = nextModule
1528		}
1529	}
1530
1531	check = func(module *moduleInfo) []*moduleInfo {
1532		visited[module] = true
1533		checking[module] = true
1534		defer delete(checking, module)
1535
1536		deps := make(map[*moduleInfo]bool)
1537
1538		// Add an implicit dependency ordering on all earlier modules in the same module group
1539		for _, dep := range module.group.modules {
1540			if dep == module {
1541				break
1542			}
1543			deps[dep] = true
1544		}
1545
1546		for _, dep := range module.directDeps {
1547			deps[dep.module] = true
1548		}
1549
1550		module.reverseDeps = []*moduleInfo{}
1551		module.forwardDeps = []*moduleInfo{}
1552
1553		for dep := range deps {
1554			if checking[dep] {
1555				// This is a cycle.
1556				return []*moduleInfo{dep, module}
1557			}
1558
1559			if !visited[dep] {
1560				cycle := check(dep)
1561				if cycle != nil {
1562					if cycle[0] == module {
1563						// We are the "start" of the cycle, so we're responsible
1564						// for generating the errors.  The cycle list is in
1565						// reverse order because all the 'check' calls append
1566						// their own module to the list.
1567						cycleError(cycle)
1568
1569						// We can continue processing this module's children to
1570						// find more cycles.  Since all the modules that were
1571						// part of the found cycle were marked as visited we
1572						// won't run into that cycle again.
1573					} else {
1574						// We're not the "start" of the cycle, so we just append
1575						// our module to the list and return it.
1576						return append(cycle, module)
1577					}
1578				}
1579			}
1580
1581			module.forwardDeps = append(module.forwardDeps, dep)
1582			dep.reverseDeps = append(dep.reverseDeps, module)
1583		}
1584
1585		sorted = append(sorted, module)
1586
1587		return nil
1588	}
1589
1590	for _, module := range c.moduleInfo {
1591		if !visited[module] {
1592			cycle := check(module)
1593			if cycle != nil {
1594				if cycle[len(cycle)-1] != module {
1595					panic("inconceivable!")
1596				}
1597				cycleError(cycle)
1598			}
1599		}
1600	}
1601
1602	c.modulesSorted = sorted
1603
1604	return
1605}
1606
1607// PrepareBuildActions generates an internal representation of all the build
1608// actions that need to be performed.  This process involves invoking the
1609// GenerateBuildActions method on each of the Module objects created during the
1610// parse phase and then on each of the registered Singleton objects.
1611//
1612// If the ResolveDependencies method has not already been called it is called
1613// automatically by this method.
1614//
1615// The config argument is made available to all of the Module and Singleton
1616// objects via the Config method on the ModuleContext and SingletonContext
1617// objects passed to GenerateBuildActions.  It is also passed to the functions
1618// specified via PoolFunc, RuleFunc, and VariableFunc so that they can compute
1619// config-specific values.
1620//
1621// The returned deps is a list of the ninja files dependencies that were added
1622// by the modules and singletons via the ModuleContext.AddNinjaFileDeps(),
1623// SingletonContext.AddNinjaFileDeps(), and PackageContext.AddNinjaFileDeps()
1624// methods.
1625func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs []error) {
1626	c.buildActionsReady = false
1627
1628	if !c.dependenciesReady {
1629		errs := c.ResolveDependencies(config)
1630		if len(errs) > 0 {
1631			return nil, errs
1632		}
1633	}
1634
1635	liveGlobals := newLiveTracker(config)
1636
1637	c.initSpecialVariables()
1638
1639	depsModules, errs := c.generateModuleBuildActions(config, liveGlobals)
1640	if len(errs) > 0 {
1641		return nil, errs
1642	}
1643
1644	depsSingletons, errs := c.generateSingletonBuildActions(config, liveGlobals)
1645	if len(errs) > 0 {
1646		return nil, errs
1647	}
1648
1649	deps = append(depsModules, depsSingletons...)
1650
1651	if c.ninjaBuildDir != nil {
1652		liveGlobals.addNinjaStringDeps(c.ninjaBuildDir)
1653	}
1654
1655	pkgNames, depsPackages := c.makeUniquePackageNames(liveGlobals)
1656
1657	deps = append(deps, depsPackages...)
1658
1659	// This will panic if it finds a problem since it's a programming error.
1660	c.checkForVariableReferenceCycles(liveGlobals.variables, pkgNames)
1661
1662	c.pkgNames = pkgNames
1663	c.globalVariables = liveGlobals.variables
1664	c.globalPools = liveGlobals.pools
1665	c.globalRules = liveGlobals.rules
1666
1667	c.buildActionsReady = true
1668
1669	return deps, nil
1670}
1671
1672func (c *Context) runMutators(config interface{}) (errs []error) {
1673	var mutators []*mutatorInfo
1674
1675	mutators = append(mutators, c.earlyMutatorInfo...)
1676	mutators = append(mutators, c.mutatorInfo...)
1677
1678	for _, mutator := range mutators {
1679		if mutator.topDownMutator != nil {
1680			errs = c.runMutator(config, mutator, topDownMutator)
1681		} else if mutator.bottomUpMutator != nil {
1682			errs = c.runMutator(config, mutator, bottomUpMutator)
1683		} else {
1684			panic("no mutator set on " + mutator.name)
1685		}
1686		if len(errs) > 0 {
1687			return errs
1688		}
1689	}
1690
1691	return nil
1692}
1693
1694type mutatorDirection interface {
1695	run(mutator *mutatorInfo, ctx *mutatorContext)
1696	orderer() visitOrderer
1697	fmt.Stringer
1698}
1699
1700type bottomUpMutatorImpl struct{}
1701
1702func (bottomUpMutatorImpl) run(mutator *mutatorInfo, ctx *mutatorContext) {
1703	mutator.bottomUpMutator(ctx)
1704}
1705
1706func (bottomUpMutatorImpl) orderer() visitOrderer {
1707	return bottomUpVisitor
1708}
1709
1710func (bottomUpMutatorImpl) String() string {
1711	return "bottom up mutator"
1712}
1713
1714type topDownMutatorImpl struct{}
1715
1716func (topDownMutatorImpl) run(mutator *mutatorInfo, ctx *mutatorContext) {
1717	mutator.topDownMutator(ctx)
1718}
1719
1720func (topDownMutatorImpl) orderer() visitOrderer {
1721	return topDownVisitor
1722}
1723
1724func (topDownMutatorImpl) String() string {
1725	return "top down mutator"
1726}
1727
1728var (
1729	topDownMutator  topDownMutatorImpl
1730	bottomUpMutator bottomUpMutatorImpl
1731)
1732
1733type reverseDep struct {
1734	module *moduleInfo
1735	dep    depInfo
1736}
1737
1738func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
1739	direction mutatorDirection) (errs []error) {
1740
1741	newModuleInfo := make(map[Module]*moduleInfo)
1742	for k, v := range c.moduleInfo {
1743		newModuleInfo[k] = v
1744	}
1745
1746	type globalStateChange struct {
1747		reverse []reverseDep
1748		rename  []rename
1749		replace []replace
1750	}
1751
1752	reverseDeps := make(map[*moduleInfo][]depInfo)
1753	var rename []rename
1754	var replace []replace
1755
1756	errsCh := make(chan []error)
1757	globalStateCh := make(chan globalStateChange)
1758	newModulesCh := make(chan []*moduleInfo)
1759	done := make(chan bool)
1760
1761	c.depsModified = 0
1762
1763	visit := func(module *moduleInfo) bool {
1764		if module.splitModules != nil {
1765			panic("split module found in sorted module list")
1766		}
1767
1768		mctx := &mutatorContext{
1769			baseModuleContext: baseModuleContext{
1770				context: c,
1771				config:  config,
1772				module:  module,
1773			},
1774			name: mutator.name,
1775		}
1776
1777		func() {
1778			defer func() {
1779				if r := recover(); r != nil {
1780					in := fmt.Sprintf("%s %q for %s", direction, mutator.name, module)
1781					if err, ok := r.(panicError); ok {
1782						err.addIn(in)
1783						mctx.error(err)
1784					} else {
1785						mctx.error(newPanicErrorf(r, in))
1786					}
1787				}
1788			}()
1789			direction.run(mutator, mctx)
1790		}()
1791
1792		if len(mctx.errs) > 0 {
1793			errsCh <- mctx.errs
1794			return true
1795		}
1796
1797		if len(mctx.newModules) > 0 {
1798			newModulesCh <- mctx.newModules
1799		}
1800
1801		if len(mctx.reverseDeps) > 0 || len(mctx.replace) > 0 || len(mctx.rename) > 0 {
1802			globalStateCh <- globalStateChange{
1803				reverse: mctx.reverseDeps,
1804				replace: mctx.replace,
1805				rename:  mctx.rename,
1806			}
1807		}
1808
1809		return false
1810	}
1811
1812	// Process errs and reverseDeps in a single goroutine
1813	go func() {
1814		for {
1815			select {
1816			case newErrs := <-errsCh:
1817				errs = append(errs, newErrs...)
1818			case globalStateChange := <-globalStateCh:
1819				for _, r := range globalStateChange.reverse {
1820					reverseDeps[r.module] = append(reverseDeps[r.module], r.dep)
1821				}
1822				replace = append(replace, globalStateChange.replace...)
1823				rename = append(rename, globalStateChange.rename...)
1824			case newModules := <-newModulesCh:
1825				for _, m := range newModules {
1826					newModuleInfo[m.logicModule] = m
1827				}
1828			case <-done:
1829				return
1830			}
1831		}
1832	}()
1833
1834	if mutator.parallel {
1835		c.parallelVisit(direction.orderer(), visit)
1836	} else {
1837		direction.orderer().visit(c.modulesSorted, visit)
1838	}
1839
1840	done <- true
1841
1842	if len(errs) > 0 {
1843		return errs
1844	}
1845
1846	c.moduleInfo = newModuleInfo
1847
1848	for _, group := range c.moduleGroups {
1849		for i := 0; i < len(group.modules); i++ {
1850			module := group.modules[i]
1851
1852			// Update module group to contain newly split variants
1853			if module.splitModules != nil {
1854				group.modules, i = spliceModules(group.modules, i, module.splitModules)
1855			}
1856
1857			// Fix up any remaining dependencies on modules that were split into variants
1858			// by replacing them with the first variant
1859			for j, dep := range module.directDeps {
1860				if dep.module.logicModule == nil {
1861					module.directDeps[j].module = dep.module.splitModules[0]
1862				}
1863			}
1864		}
1865	}
1866
1867	for module, deps := range reverseDeps {
1868		sort.Sort(depSorter(deps))
1869		module.directDeps = append(module.directDeps, deps...)
1870		c.depsModified++
1871	}
1872
1873	errs = c.handleRenames(rename)
1874	if len(errs) > 0 {
1875		return errs
1876	}
1877
1878	errs = c.handleReplacements(replace)
1879	if len(errs) > 0 {
1880		return errs
1881	}
1882
1883	if c.depsModified > 0 {
1884		errs = c.updateDependencies()
1885		if len(errs) > 0 {
1886			return errs
1887		}
1888	}
1889
1890	return errs
1891}
1892
1893// Replaces every build logic module with a clone of itself.  Prevents introducing problems where
1894// a mutator sets a non-property member variable on a module, which works until a later mutator
1895// creates variants of that module.
1896func (c *Context) cloneModules() {
1897	type update struct {
1898		orig  Module
1899		clone *moduleInfo
1900	}
1901	ch := make(chan update, 100)
1902
1903	for _, m := range c.modulesSorted {
1904		go func(m *moduleInfo) {
1905			origLogicModule := m.logicModule
1906			m.logicModule, m.moduleProperties = c.cloneLogicModule(m)
1907			ch <- update{origLogicModule, m}
1908		}(m)
1909	}
1910
1911	for i := 0; i < len(c.modulesSorted); i++ {
1912		update := <-ch
1913		delete(c.moduleInfo, update.orig)
1914		c.moduleInfo[update.clone.logicModule] = update.clone
1915	}
1916}
1917
1918// Removes modules[i] from the list and inserts newModules... where it was located, returning
1919// the new slice and the index of the last inserted element
1920func spliceModules(modules []*moduleInfo, i int, newModules []*moduleInfo) ([]*moduleInfo, int) {
1921	spliceSize := len(newModules)
1922	newLen := len(modules) + spliceSize - 1
1923	var dest []*moduleInfo
1924	if cap(modules) >= len(modules)-1+len(newModules) {
1925		// We can fit the splice in the existing capacity, do everything in place
1926		dest = modules[:newLen]
1927	} else {
1928		dest = make([]*moduleInfo, newLen)
1929		copy(dest, modules[:i])
1930	}
1931
1932	// Move the end of the slice over by spliceSize-1
1933	copy(dest[i+spliceSize:], modules[i+1:])
1934
1935	// Copy the new modules into the slice
1936	copy(dest[i:], newModules)
1937
1938	return dest, i + spliceSize - 1
1939}
1940
1941func (c *Context) initSpecialVariables() {
1942	c.ninjaBuildDir = nil
1943	c.requiredNinjaMajor = 1
1944	c.requiredNinjaMinor = 7
1945	c.requiredNinjaMicro = 0
1946}
1947
1948func (c *Context) generateModuleBuildActions(config interface{},
1949	liveGlobals *liveTracker) ([]string, []error) {
1950
1951	var deps []string
1952	var errs []error
1953
1954	cancelCh := make(chan struct{})
1955	errsCh := make(chan []error)
1956	depsCh := make(chan []string)
1957
1958	go func() {
1959		for {
1960			select {
1961			case <-cancelCh:
1962				close(cancelCh)
1963				return
1964			case newErrs := <-errsCh:
1965				errs = append(errs, newErrs...)
1966			case newDeps := <-depsCh:
1967				deps = append(deps, newDeps...)
1968
1969			}
1970		}
1971	}()
1972
1973	c.parallelVisit(bottomUpVisitor, func(module *moduleInfo) bool {
1974		// The parent scope of the moduleContext's local scope gets overridden to be that of the
1975		// calling Go package on a per-call basis.  Since the initial parent scope doesn't matter we
1976		// just set it to nil.
1977		prefix := moduleNamespacePrefix(module.group.ninjaName + "_" + module.variantName)
1978		scope := newLocalScope(nil, prefix)
1979
1980		mctx := &moduleContext{
1981			baseModuleContext: baseModuleContext{
1982				context: c,
1983				config:  config,
1984				module:  module,
1985			},
1986			scope:              scope,
1987			handledMissingDeps: module.missingDeps == nil,
1988		}
1989
1990		func() {
1991			defer func() {
1992				if r := recover(); r != nil {
1993					in := fmt.Sprintf("GenerateBuildActions for %s", module)
1994					if err, ok := r.(panicError); ok {
1995						err.addIn(in)
1996						mctx.error(err)
1997					} else {
1998						mctx.error(newPanicErrorf(r, in))
1999					}
2000				}
2001			}()
2002			mctx.module.logicModule.GenerateBuildActions(mctx)
2003		}()
2004
2005		if len(mctx.errs) > 0 {
2006			errsCh <- mctx.errs
2007			return true
2008		}
2009
2010		if module.missingDeps != nil && !mctx.handledMissingDeps {
2011			var errs []error
2012			for _, depName := range module.missingDeps {
2013				errs = append(errs, &BlueprintError{
2014					Err: fmt.Errorf("%q depends on undefined module %q",
2015						module.Name(), depName),
2016					Pos: module.pos,
2017				})
2018			}
2019			errsCh <- errs
2020			return true
2021		}
2022
2023		depsCh <- mctx.ninjaFileDeps
2024
2025		newErrs := c.processLocalBuildActions(&module.actionDefs,
2026			&mctx.actionDefs, liveGlobals)
2027		if len(newErrs) > 0 {
2028			errsCh <- newErrs
2029			return true
2030		}
2031		return false
2032	})
2033
2034	cancelCh <- struct{}{}
2035	<-cancelCh
2036
2037	return deps, errs
2038}
2039
2040func (c *Context) generateSingletonBuildActions(config interface{},
2041	liveGlobals *liveTracker) ([]string, []error) {
2042
2043	var deps []string
2044	var errs []error
2045
2046	for _, info := range c.singletonInfo {
2047		// The parent scope of the singletonContext's local scope gets overridden to be that of the
2048		// calling Go package on a per-call basis.  Since the initial parent scope doesn't matter we
2049		// just set it to nil.
2050		scope := newLocalScope(nil, singletonNamespacePrefix(info.name))
2051
2052		sctx := &singletonContext{
2053			context: c,
2054			config:  config,
2055			scope:   scope,
2056			globals: liveGlobals,
2057		}
2058
2059		func() {
2060			defer func() {
2061				if r := recover(); r != nil {
2062					in := fmt.Sprintf("GenerateBuildActions for singleton %s", info.name)
2063					if err, ok := r.(panicError); ok {
2064						err.addIn(in)
2065						sctx.error(err)
2066					} else {
2067						sctx.error(newPanicErrorf(r, in))
2068					}
2069				}
2070			}()
2071			info.singleton.GenerateBuildActions(sctx)
2072		}()
2073
2074		if len(sctx.errs) > 0 {
2075			errs = append(errs, sctx.errs...)
2076			if len(errs) > maxErrors {
2077				break
2078			}
2079			continue
2080		}
2081
2082		deps = append(deps, sctx.ninjaFileDeps...)
2083
2084		newErrs := c.processLocalBuildActions(&info.actionDefs,
2085			&sctx.actionDefs, liveGlobals)
2086		errs = append(errs, newErrs...)
2087		if len(errs) > maxErrors {
2088			break
2089		}
2090	}
2091
2092	return deps, errs
2093}
2094
2095func (c *Context) processLocalBuildActions(out, in *localBuildActions,
2096	liveGlobals *liveTracker) []error {
2097
2098	var errs []error
2099
2100	// First we go through and add everything referenced by the module's
2101	// buildDefs to the live globals set.  This will end up adding the live
2102	// locals to the set as well, but we'll take them out after.
2103	for _, def := range in.buildDefs {
2104		err := liveGlobals.AddBuildDefDeps(def)
2105		if err != nil {
2106			errs = append(errs, err)
2107		}
2108	}
2109
2110	if len(errs) > 0 {
2111		return errs
2112	}
2113
2114	out.buildDefs = append(out.buildDefs, in.buildDefs...)
2115
2116	// We use the now-incorrect set of live "globals" to determine which local
2117	// definitions are live.  As we go through copying those live locals to the
2118	// moduleGroup we remove them from the live globals set.
2119	for _, v := range in.variables {
2120		isLive := liveGlobals.RemoveVariableIfLive(v)
2121		if isLive {
2122			out.variables = append(out.variables, v)
2123		}
2124	}
2125
2126	for _, r := range in.rules {
2127		isLive := liveGlobals.RemoveRuleIfLive(r)
2128		if isLive {
2129			out.rules = append(out.rules, r)
2130		}
2131	}
2132
2133	return nil
2134}
2135
2136func (c *Context) walkDeps(topModule *moduleInfo,
2137	visitDown func(depInfo, *moduleInfo) bool, visitUp func(depInfo, *moduleInfo)) {
2138
2139	visited := make(map[*moduleInfo]bool)
2140	var visiting *moduleInfo
2141
2142	defer func() {
2143		if r := recover(); r != nil {
2144			panic(newPanicErrorf(r, "WalkDeps(%s, %s, %s) for dependency %s",
2145				topModule, funcName(visitDown), funcName(visitUp), visiting))
2146		}
2147	}()
2148
2149	var walk func(module *moduleInfo)
2150	walk = func(module *moduleInfo) {
2151		for _, dep := range module.directDeps {
2152			if !visited[dep.module] {
2153				visited[dep.module] = true
2154				visiting = dep.module
2155				recurse := true
2156				if visitDown != nil {
2157					recurse = visitDown(dep, module)
2158				}
2159				if recurse {
2160					walk(dep.module)
2161				}
2162				if visitUp != nil {
2163					visitUp(dep, module)
2164				}
2165			}
2166		}
2167	}
2168
2169	walk(topModule)
2170}
2171
2172type replace struct {
2173	from, to *moduleInfo
2174}
2175
2176type rename struct {
2177	group *moduleGroup
2178	name  string
2179}
2180
2181func (c *Context) moduleMatchingVariant(module *moduleInfo, name string) *moduleInfo {
2182	targets := c.modulesFromName(name)
2183
2184	if targets == nil {
2185		return nil
2186	}
2187
2188	for _, m := range targets {
2189		if module.variantName == m.variantName {
2190			return m
2191		}
2192	}
2193
2194	return nil
2195}
2196
2197func (c *Context) handleRenames(renames []rename) []error {
2198	var errs []error
2199	for _, rename := range renames {
2200		group, name := rename.group, rename.name
2201		if name == group.name {
2202			continue
2203		}
2204
2205		existing := c.moduleNames[name]
2206		if existing != nil {
2207			errs = append(errs,
2208				&BlueprintError{
2209					Err: fmt.Errorf("renaming module %q to %q conflicts with existing module",
2210						group.name, name),
2211					Pos: group.modules[0].pos,
2212				},
2213				&BlueprintError{
2214					Err: fmt.Errorf("<-- existing module defined here"),
2215					Pos: existing.modules[0].pos,
2216				},
2217			)
2218			continue
2219		}
2220
2221		c.moduleNames[name] = group
2222		delete(c.moduleNames, group.name)
2223		group.name = name
2224	}
2225
2226	return errs
2227}
2228
2229func (c *Context) handleReplacements(replacements []replace) []error {
2230	var errs []error
2231	for _, replace := range replacements {
2232		for _, m := range replace.from.reverseDeps {
2233			for i, d := range m.directDeps {
2234				if d.module == replace.from {
2235					m.directDeps[i].module = replace.to
2236				}
2237			}
2238		}
2239
2240		atomic.AddUint32(&c.depsModified, 1)
2241	}
2242
2243	return errs
2244}
2245
2246func (c *Context) modulesFromName(name string) []*moduleInfo {
2247	if group := c.moduleNames[name]; group != nil {
2248		return group.modules
2249	}
2250	return nil
2251}
2252
2253func (c *Context) sortedModuleNames() []string {
2254	if c.cachedSortedModuleNames == nil {
2255		c.cachedSortedModuleNames = make([]string, 0, len(c.moduleNames))
2256		for moduleName := range c.moduleNames {
2257			c.cachedSortedModuleNames = append(c.cachedSortedModuleNames,
2258				moduleName)
2259		}
2260		sort.Strings(c.cachedSortedModuleNames)
2261	}
2262
2263	return c.cachedSortedModuleNames
2264}
2265
2266func (c *Context) visitAllModules(visit func(Module)) {
2267	var module *moduleInfo
2268
2269	defer func() {
2270		if r := recover(); r != nil {
2271			panic(newPanicErrorf(r, "VisitAllModules(%s) for %s",
2272				funcName(visit), module))
2273		}
2274	}()
2275
2276	for _, moduleName := range c.sortedModuleNames() {
2277		modules := c.modulesFromName(moduleName)
2278		for _, module = range modules {
2279			visit(module.logicModule)
2280		}
2281	}
2282}
2283
2284func (c *Context) visitAllModulesIf(pred func(Module) bool,
2285	visit func(Module)) {
2286
2287	var module *moduleInfo
2288
2289	defer func() {
2290		if r := recover(); r != nil {
2291			panic(newPanicErrorf(r, "VisitAllModulesIf(%s, %s) for %s",
2292				funcName(pred), funcName(visit), module))
2293		}
2294	}()
2295
2296	for _, moduleName := range c.sortedModuleNames() {
2297		modules := c.modulesFromName(moduleName)
2298		for _, module := range modules {
2299			if pred(module.logicModule) {
2300				visit(module.logicModule)
2301			}
2302		}
2303	}
2304}
2305
2306func (c *Context) visitAllModuleVariants(module *moduleInfo,
2307	visit func(Module)) {
2308
2309	var variant *moduleInfo
2310
2311	defer func() {
2312		if r := recover(); r != nil {
2313			panic(newPanicErrorf(r, "VisitAllModuleVariants(%s, %s) for %s",
2314				module, funcName(visit), variant))
2315		}
2316	}()
2317
2318	for _, variant = range module.group.modules {
2319		visit(variant.logicModule)
2320	}
2321}
2322
2323func (c *Context) requireNinjaVersion(major, minor, micro int) {
2324	if major != 1 {
2325		panic("ninja version with major version != 1 not supported")
2326	}
2327	if c.requiredNinjaMinor < minor {
2328		c.requiredNinjaMinor = minor
2329		c.requiredNinjaMicro = micro
2330	}
2331	if c.requiredNinjaMinor == minor && c.requiredNinjaMicro < micro {
2332		c.requiredNinjaMicro = micro
2333	}
2334}
2335
2336func (c *Context) setNinjaBuildDir(value *ninjaString) {
2337	if c.ninjaBuildDir == nil {
2338		c.ninjaBuildDir = value
2339	}
2340}
2341
2342func (c *Context) makeUniquePackageNames(
2343	liveGlobals *liveTracker) (map[*packageContext]string, []string) {
2344
2345	pkgs := make(map[string]*packageContext)
2346	pkgNames := make(map[*packageContext]string)
2347	longPkgNames := make(map[*packageContext]bool)
2348
2349	processPackage := func(pctx *packageContext) {
2350		if pctx == nil {
2351			// This is a built-in rule and has no package.
2352			return
2353		}
2354		if _, ok := pkgNames[pctx]; ok {
2355			// We've already processed this package.
2356			return
2357		}
2358
2359		otherPkg, present := pkgs[pctx.shortName]
2360		if present {
2361			// Short name collision.  Both this package and the one that's
2362			// already there need to use their full names.  We leave the short
2363			// name in pkgNames for now so future collisions still get caught.
2364			longPkgNames[pctx] = true
2365			longPkgNames[otherPkg] = true
2366		} else {
2367			// No collision so far.  Tentatively set the package's name to be
2368			// its short name.
2369			pkgNames[pctx] = pctx.shortName
2370			pkgs[pctx.shortName] = pctx
2371		}
2372	}
2373
2374	// We try to give all packages their short name, but when we get collisions
2375	// we need to use the full unique package name.
2376	for v, _ := range liveGlobals.variables {
2377		processPackage(v.packageContext())
2378	}
2379	for p, _ := range liveGlobals.pools {
2380		processPackage(p.packageContext())
2381	}
2382	for r, _ := range liveGlobals.rules {
2383		processPackage(r.packageContext())
2384	}
2385
2386	// Add the packages that had collisions using their full unique names.  This
2387	// will overwrite any short names that were added in the previous step.
2388	for pctx := range longPkgNames {
2389		pkgNames[pctx] = pctx.fullName
2390	}
2391
2392	// Create deps list from calls to PackageContext.AddNinjaFileDeps
2393	deps := []string{}
2394	for _, pkg := range pkgs {
2395		deps = append(deps, pkg.ninjaFileDeps...)
2396	}
2397
2398	return pkgNames, deps
2399}
2400
2401func (c *Context) checkForVariableReferenceCycles(
2402	variables map[Variable]*ninjaString, pkgNames map[*packageContext]string) {
2403
2404	visited := make(map[Variable]bool)  // variables that were already checked
2405	checking := make(map[Variable]bool) // variables actively being checked
2406
2407	var check func(v Variable) []Variable
2408
2409	check = func(v Variable) []Variable {
2410		visited[v] = true
2411		checking[v] = true
2412		defer delete(checking, v)
2413
2414		value := variables[v]
2415		for _, dep := range value.variables {
2416			if checking[dep] {
2417				// This is a cycle.
2418				return []Variable{dep, v}
2419			}
2420
2421			if !visited[dep] {
2422				cycle := check(dep)
2423				if cycle != nil {
2424					if cycle[0] == v {
2425						// We are the "start" of the cycle, so we're responsible
2426						// for generating the errors.  The cycle list is in
2427						// reverse order because all the 'check' calls append
2428						// their own module to the list.
2429						msgs := []string{"detected variable reference cycle:"}
2430
2431						// Iterate backwards through the cycle list.
2432						curName := v.fullName(pkgNames)
2433						curValue := value.Value(pkgNames)
2434						for i := len(cycle) - 1; i >= 0; i-- {
2435							next := cycle[i]
2436							nextName := next.fullName(pkgNames)
2437							nextValue := variables[next].Value(pkgNames)
2438
2439							msgs = append(msgs, fmt.Sprintf(
2440								"    %q depends on %q", curName, nextName))
2441							msgs = append(msgs, fmt.Sprintf(
2442								"    [%s = %s]", curName, curValue))
2443
2444							curName = nextName
2445							curValue = nextValue
2446						}
2447
2448						// Variable reference cycles are a programming error,
2449						// not the fault of the Blueprint file authors.
2450						panic(strings.Join(msgs, "\n"))
2451					} else {
2452						// We're not the "start" of the cycle, so we just append
2453						// our module to the list and return it.
2454						return append(cycle, v)
2455					}
2456				}
2457			}
2458		}
2459
2460		return nil
2461	}
2462
2463	for v := range variables {
2464		if !visited[v] {
2465			cycle := check(v)
2466			if cycle != nil {
2467				panic("inconceivable!")
2468			}
2469		}
2470	}
2471}
2472
2473// AllTargets returns a map all the build target names to the rule used to build
2474// them.  This is the same information that is output by running 'ninja -t
2475// targets all'.  If this is called before PrepareBuildActions successfully
2476// completes then ErrbuildActionsNotReady is returned.
2477func (c *Context) AllTargets() (map[string]string, error) {
2478	if !c.buildActionsReady {
2479		return nil, ErrBuildActionsNotReady
2480	}
2481
2482	targets := map[string]string{}
2483
2484	// Collect all the module build targets.
2485	for _, module := range c.moduleInfo {
2486		for _, buildDef := range module.actionDefs.buildDefs {
2487			ruleName := buildDef.Rule.fullName(c.pkgNames)
2488			for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
2489				outputValue, err := output.Eval(c.globalVariables)
2490				if err != nil {
2491					return nil, err
2492				}
2493				targets[outputValue] = ruleName
2494			}
2495		}
2496	}
2497
2498	// Collect all the singleton build targets.
2499	for _, info := range c.singletonInfo {
2500		for _, buildDef := range info.actionDefs.buildDefs {
2501			ruleName := buildDef.Rule.fullName(c.pkgNames)
2502			for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
2503				outputValue, err := output.Eval(c.globalVariables)
2504				if err != nil {
2505					return nil, err
2506				}
2507				targets[outputValue] = ruleName
2508			}
2509		}
2510	}
2511
2512	return targets, nil
2513}
2514
2515func (c *Context) NinjaBuildDir() (string, error) {
2516	if c.ninjaBuildDir != nil {
2517		return c.ninjaBuildDir.Eval(c.globalVariables)
2518	} else {
2519		return "", nil
2520	}
2521}
2522
2523// ModuleTypePropertyStructs returns a mapping from module type name to a list of pointers to
2524// property structs returned by the factory for that module type.
2525func (c *Context) ModuleTypePropertyStructs() map[string][]interface{} {
2526	ret := make(map[string][]interface{})
2527	for moduleType, factory := range c.moduleFactories {
2528		_, ret[moduleType] = factory()
2529	}
2530
2531	return ret
2532}
2533
2534func (c *Context) ModuleName(logicModule Module) string {
2535	module := c.moduleInfo[logicModule]
2536	return module.Name()
2537}
2538
2539func (c *Context) ModuleDir(logicModule Module) string {
2540	module := c.moduleInfo[logicModule]
2541	return filepath.Dir(module.relBlueprintsFile)
2542}
2543
2544func (c *Context) ModuleSubDir(logicModule Module) string {
2545	module := c.moduleInfo[logicModule]
2546	return module.variantName
2547}
2548
2549func (c *Context) ModuleType(logicModule Module) string {
2550	module := c.moduleInfo[logicModule]
2551	return module.typeName
2552}
2553
2554func (c *Context) BlueprintFile(logicModule Module) string {
2555	module := c.moduleInfo[logicModule]
2556	return module.relBlueprintsFile
2557}
2558
2559func (c *Context) ModuleErrorf(logicModule Module, format string,
2560	args ...interface{}) error {
2561
2562	module := c.moduleInfo[logicModule]
2563	return &BlueprintError{
2564		Err: fmt.Errorf(format, args...),
2565		Pos: module.pos,
2566	}
2567}
2568
2569func (c *Context) VisitAllModules(visit func(Module)) {
2570	c.visitAllModules(visit)
2571}
2572
2573func (c *Context) VisitAllModulesIf(pred func(Module) bool,
2574	visit func(Module)) {
2575
2576	c.visitAllModulesIf(pred, visit)
2577}
2578
2579func (c *Context) VisitDirectDeps(module Module, visit func(Module)) {
2580	topModule := c.moduleInfo[module]
2581
2582	var visiting *moduleInfo
2583
2584	defer func() {
2585		if r := recover(); r != nil {
2586			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
2587				topModule, funcName(visit), visiting))
2588		}
2589	}()
2590
2591	for _, dep := range topModule.directDeps {
2592		visiting = dep.module
2593		visit(dep.module.logicModule)
2594	}
2595}
2596
2597func (c *Context) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
2598	topModule := c.moduleInfo[module]
2599
2600	var visiting *moduleInfo
2601
2602	defer func() {
2603		if r := recover(); r != nil {
2604			panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
2605				topModule, funcName(pred), funcName(visit), visiting))
2606		}
2607	}()
2608
2609	for _, dep := range topModule.directDeps {
2610		visiting = dep.module
2611		if pred(dep.module.logicModule) {
2612			visit(dep.module.logicModule)
2613		}
2614	}
2615}
2616
2617func (c *Context) VisitDepsDepthFirst(module Module, visit func(Module)) {
2618	topModule := c.moduleInfo[module]
2619
2620	var visiting *moduleInfo
2621
2622	defer func() {
2623		if r := recover(); r != nil {
2624			panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
2625				topModule, funcName(visit), visiting))
2626		}
2627	}()
2628
2629	c.walkDeps(topModule, nil, func(dep depInfo, parent *moduleInfo) {
2630		visiting = dep.module
2631		visit(dep.module.logicModule)
2632	})
2633}
2634
2635func (c *Context) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
2636	topModule := c.moduleInfo[module]
2637
2638	var visiting *moduleInfo
2639
2640	defer func() {
2641		if r := recover(); r != nil {
2642			panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
2643				topModule, funcName(pred), funcName(visit), visiting))
2644		}
2645	}()
2646
2647	c.walkDeps(topModule, nil, func(dep depInfo, parent *moduleInfo) {
2648		if pred(dep.module.logicModule) {
2649			visiting = dep.module
2650			visit(dep.module.logicModule)
2651		}
2652	})
2653}
2654
2655func (c *Context) PrimaryModule(module Module) Module {
2656	return c.moduleInfo[module].group.modules[0].logicModule
2657}
2658
2659func (c *Context) FinalModule(module Module) Module {
2660	modules := c.moduleInfo[module].group.modules
2661	return modules[len(modules)-1].logicModule
2662}
2663
2664func (c *Context) VisitAllModuleVariants(module Module,
2665	visit func(Module)) {
2666
2667	c.visitAllModuleVariants(c.moduleInfo[module], visit)
2668}
2669
2670// WriteBuildFile writes the Ninja manifeset text for the generated build
2671// actions to w.  If this is called before PrepareBuildActions successfully
2672// completes then ErrBuildActionsNotReady is returned.
2673func (c *Context) WriteBuildFile(w io.Writer) error {
2674	if !c.buildActionsReady {
2675		return ErrBuildActionsNotReady
2676	}
2677
2678	nw := newNinjaWriter(w)
2679
2680	err := c.writeBuildFileHeader(nw)
2681	if err != nil {
2682		return err
2683	}
2684
2685	err = c.writeNinjaRequiredVersion(nw)
2686	if err != nil {
2687		return err
2688	}
2689
2690	// TODO: Group the globals by package.
2691
2692	err = c.writeGlobalVariables(nw)
2693	if err != nil {
2694		return err
2695	}
2696
2697	err = c.writeGlobalPools(nw)
2698	if err != nil {
2699		return err
2700	}
2701
2702	err = c.writeBuildDir(nw)
2703	if err != nil {
2704		return err
2705	}
2706
2707	err = c.writeGlobalRules(nw)
2708	if err != nil {
2709		return err
2710	}
2711
2712	err = c.writeAllModuleActions(nw)
2713	if err != nil {
2714		return err
2715	}
2716
2717	err = c.writeAllSingletonActions(nw)
2718	if err != nil {
2719		return err
2720	}
2721
2722	return nil
2723}
2724
2725type pkgAssociation struct {
2726	PkgName string
2727	PkgPath string
2728}
2729
2730type pkgAssociationSorter struct {
2731	pkgs []pkgAssociation
2732}
2733
2734func (s *pkgAssociationSorter) Len() int {
2735	return len(s.pkgs)
2736}
2737
2738func (s *pkgAssociationSorter) Less(i, j int) bool {
2739	iName := s.pkgs[i].PkgName
2740	jName := s.pkgs[j].PkgName
2741	return iName < jName
2742}
2743
2744func (s *pkgAssociationSorter) Swap(i, j int) {
2745	s.pkgs[i], s.pkgs[j] = s.pkgs[j], s.pkgs[i]
2746}
2747
2748func (c *Context) writeBuildFileHeader(nw *ninjaWriter) error {
2749	headerTemplate := template.New("fileHeader")
2750	_, err := headerTemplate.Parse(fileHeaderTemplate)
2751	if err != nil {
2752		// This is a programming error.
2753		panic(err)
2754	}
2755
2756	var pkgs []pkgAssociation
2757	maxNameLen := 0
2758	for pkg, name := range c.pkgNames {
2759		pkgs = append(pkgs, pkgAssociation{
2760			PkgName: name,
2761			PkgPath: pkg.pkgPath,
2762		})
2763		if len(name) > maxNameLen {
2764			maxNameLen = len(name)
2765		}
2766	}
2767
2768	for i := range pkgs {
2769		pkgs[i].PkgName += strings.Repeat(" ", maxNameLen-len(pkgs[i].PkgName))
2770	}
2771
2772	sort.Sort(&pkgAssociationSorter{pkgs})
2773
2774	params := map[string]interface{}{
2775		"Pkgs": pkgs,
2776	}
2777
2778	buf := bytes.NewBuffer(nil)
2779	err = headerTemplate.Execute(buf, params)
2780	if err != nil {
2781		return err
2782	}
2783
2784	return nw.Comment(buf.String())
2785}
2786
2787func (c *Context) writeNinjaRequiredVersion(nw *ninjaWriter) error {
2788	value := fmt.Sprintf("%d.%d.%d", c.requiredNinjaMajor, c.requiredNinjaMinor,
2789		c.requiredNinjaMicro)
2790
2791	err := nw.Assign("ninja_required_version", value)
2792	if err != nil {
2793		return err
2794	}
2795
2796	return nw.BlankLine()
2797}
2798
2799func (c *Context) writeBuildDir(nw *ninjaWriter) error {
2800	if c.ninjaBuildDir != nil {
2801		err := nw.Assign("builddir", c.ninjaBuildDir.Value(c.pkgNames))
2802		if err != nil {
2803			return err
2804		}
2805
2806		err = nw.BlankLine()
2807		if err != nil {
2808			return err
2809		}
2810	}
2811	return nil
2812}
2813
2814type globalEntity interface {
2815	fullName(pkgNames map[*packageContext]string) string
2816}
2817
2818type globalEntitySorter struct {
2819	pkgNames map[*packageContext]string
2820	entities []globalEntity
2821}
2822
2823func (s *globalEntitySorter) Len() int {
2824	return len(s.entities)
2825}
2826
2827func (s *globalEntitySorter) Less(i, j int) bool {
2828	iName := s.entities[i].fullName(s.pkgNames)
2829	jName := s.entities[j].fullName(s.pkgNames)
2830	return iName < jName
2831}
2832
2833func (s *globalEntitySorter) Swap(i, j int) {
2834	s.entities[i], s.entities[j] = s.entities[j], s.entities[i]
2835}
2836
2837func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
2838	visited := make(map[Variable]bool)
2839
2840	var walk func(v Variable) error
2841	walk = func(v Variable) error {
2842		visited[v] = true
2843
2844		// First visit variables on which this variable depends.
2845		value := c.globalVariables[v]
2846		for _, dep := range value.variables {
2847			if !visited[dep] {
2848				err := walk(dep)
2849				if err != nil {
2850					return err
2851				}
2852			}
2853		}
2854
2855		err := nw.Assign(v.fullName(c.pkgNames), value.Value(c.pkgNames))
2856		if err != nil {
2857			return err
2858		}
2859
2860		err = nw.BlankLine()
2861		if err != nil {
2862			return err
2863		}
2864
2865		return nil
2866	}
2867
2868	globalVariables := make([]globalEntity, 0, len(c.globalVariables))
2869	for variable := range c.globalVariables {
2870		globalVariables = append(globalVariables, variable)
2871	}
2872
2873	sort.Sort(&globalEntitySorter{c.pkgNames, globalVariables})
2874
2875	for _, entity := range globalVariables {
2876		v := entity.(Variable)
2877		if !visited[v] {
2878			err := walk(v)
2879			if err != nil {
2880				return nil
2881			}
2882		}
2883	}
2884
2885	return nil
2886}
2887
2888func (c *Context) writeGlobalPools(nw *ninjaWriter) error {
2889	globalPools := make([]globalEntity, 0, len(c.globalPools))
2890	for pool := range c.globalPools {
2891		globalPools = append(globalPools, pool)
2892	}
2893
2894	sort.Sort(&globalEntitySorter{c.pkgNames, globalPools})
2895
2896	for _, entity := range globalPools {
2897		pool := entity.(Pool)
2898		name := pool.fullName(c.pkgNames)
2899		def := c.globalPools[pool]
2900		err := def.WriteTo(nw, name)
2901		if err != nil {
2902			return err
2903		}
2904
2905		err = nw.BlankLine()
2906		if err != nil {
2907			return err
2908		}
2909	}
2910
2911	return nil
2912}
2913
2914func (c *Context) writeGlobalRules(nw *ninjaWriter) error {
2915	globalRules := make([]globalEntity, 0, len(c.globalRules))
2916	for rule := range c.globalRules {
2917		globalRules = append(globalRules, rule)
2918	}
2919
2920	sort.Sort(&globalEntitySorter{c.pkgNames, globalRules})
2921
2922	for _, entity := range globalRules {
2923		rule := entity.(Rule)
2924		name := rule.fullName(c.pkgNames)
2925		def := c.globalRules[rule]
2926		err := def.WriteTo(nw, name, c.pkgNames)
2927		if err != nil {
2928			return err
2929		}
2930
2931		err = nw.BlankLine()
2932		if err != nil {
2933			return err
2934		}
2935	}
2936
2937	return nil
2938}
2939
2940type depSorter []depInfo
2941
2942func (s depSorter) Len() int {
2943	return len(s)
2944}
2945
2946func (s depSorter) Less(i, j int) bool {
2947	iName := s[i].module.Name()
2948	jName := s[j].module.Name()
2949	if iName == jName {
2950		iName = s[i].module.variantName
2951		jName = s[j].module.variantName
2952	}
2953	return iName < jName
2954}
2955
2956func (s depSorter) Swap(i, j int) {
2957	s[i], s[j] = s[j], s[i]
2958}
2959
2960type moduleSorter []*moduleInfo
2961
2962func (s moduleSorter) Len() int {
2963	return len(s)
2964}
2965
2966func (s moduleSorter) Less(i, j int) bool {
2967	iName := s[i].Name()
2968	jName := s[j].Name()
2969	if iName == jName {
2970		iName = s[i].variantName
2971		jName = s[j].variantName
2972	}
2973	return iName < jName
2974}
2975
2976func (s moduleSorter) Swap(i, j int) {
2977	s[i], s[j] = s[j], s[i]
2978}
2979
2980func (c *Context) writeAllModuleActions(nw *ninjaWriter) error {
2981	headerTemplate := template.New("moduleHeader")
2982	_, err := headerTemplate.Parse(moduleHeaderTemplate)
2983	if err != nil {
2984		// This is a programming error.
2985		panic(err)
2986	}
2987
2988	modules := make([]*moduleInfo, 0, len(c.moduleInfo))
2989	for _, module := range c.moduleInfo {
2990		modules = append(modules, module)
2991	}
2992	sort.Sort(moduleSorter(modules))
2993
2994	buf := bytes.NewBuffer(nil)
2995
2996	for _, module := range modules {
2997		if len(module.actionDefs.variables)+len(module.actionDefs.rules)+len(module.actionDefs.buildDefs) == 0 {
2998			continue
2999		}
3000
3001		buf.Reset()
3002
3003		// In order to make the bootstrap build manifest independent of the
3004		// build dir we need to output the Blueprints file locations in the
3005		// comments as paths relative to the source directory.
3006		relPos := module.pos
3007		relPos.Filename = module.relBlueprintsFile
3008
3009		// Get the name and location of the factory function for the module.
3010		factory := c.moduleFactories[module.typeName]
3011		factoryFunc := runtime.FuncForPC(reflect.ValueOf(factory).Pointer())
3012		factoryName := factoryFunc.Name()
3013
3014		infoMap := map[string]interface{}{
3015			"name":      module.Name(),
3016			"typeName":  module.typeName,
3017			"goFactory": factoryName,
3018			"pos":       relPos,
3019			"variant":   module.variantName,
3020		}
3021		err = headerTemplate.Execute(buf, infoMap)
3022		if err != nil {
3023			return err
3024		}
3025
3026		err = nw.Comment(buf.String())
3027		if err != nil {
3028			return err
3029		}
3030
3031		err = nw.BlankLine()
3032		if err != nil {
3033			return err
3034		}
3035
3036		err = c.writeLocalBuildActions(nw, &module.actionDefs)
3037		if err != nil {
3038			return err
3039		}
3040
3041		err = nw.BlankLine()
3042		if err != nil {
3043			return err
3044		}
3045	}
3046
3047	return nil
3048}
3049
3050func (c *Context) writeAllSingletonActions(nw *ninjaWriter) error {
3051	headerTemplate := template.New("singletonHeader")
3052	_, err := headerTemplate.Parse(singletonHeaderTemplate)
3053	if err != nil {
3054		// This is a programming error.
3055		panic(err)
3056	}
3057
3058	buf := bytes.NewBuffer(nil)
3059
3060	for _, info := range c.singletonInfo {
3061		if len(info.actionDefs.variables)+len(info.actionDefs.rules)+len(info.actionDefs.buildDefs) == 0 {
3062			continue
3063		}
3064
3065		// Get the name of the factory function for the module.
3066		factory := info.factory
3067		factoryFunc := runtime.FuncForPC(reflect.ValueOf(factory).Pointer())
3068		factoryName := factoryFunc.Name()
3069
3070		buf.Reset()
3071		infoMap := map[string]interface{}{
3072			"name":      info.name,
3073			"goFactory": factoryName,
3074		}
3075		err = headerTemplate.Execute(buf, infoMap)
3076		if err != nil {
3077			return err
3078		}
3079
3080		err = nw.Comment(buf.String())
3081		if err != nil {
3082			return err
3083		}
3084
3085		err = nw.BlankLine()
3086		if err != nil {
3087			return err
3088		}
3089
3090		err = c.writeLocalBuildActions(nw, &info.actionDefs)
3091		if err != nil {
3092			return err
3093		}
3094
3095		err = nw.BlankLine()
3096		if err != nil {
3097			return err
3098		}
3099	}
3100
3101	return nil
3102}
3103
3104func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
3105	defs *localBuildActions) error {
3106
3107	// Write the local variable assignments.
3108	for _, v := range defs.variables {
3109		// A localVariable doesn't need the package names or config to
3110		// determine its name or value.
3111		name := v.fullName(nil)
3112		value, err := v.value(nil)
3113		if err != nil {
3114			panic(err)
3115		}
3116		err = nw.Assign(name, value.Value(c.pkgNames))
3117		if err != nil {
3118			return err
3119		}
3120	}
3121
3122	if len(defs.variables) > 0 {
3123		err := nw.BlankLine()
3124		if err != nil {
3125			return err
3126		}
3127	}
3128
3129	// Write the local rules.
3130	for _, r := range defs.rules {
3131		// A localRule doesn't need the package names or config to determine
3132		// its name or definition.
3133		name := r.fullName(nil)
3134		def, err := r.def(nil)
3135		if err != nil {
3136			panic(err)
3137		}
3138
3139		err = def.WriteTo(nw, name, c.pkgNames)
3140		if err != nil {
3141			return err
3142		}
3143
3144		err = nw.BlankLine()
3145		if err != nil {
3146			return err
3147		}
3148	}
3149
3150	// Write the build definitions.
3151	for _, buildDef := range defs.buildDefs {
3152		err := buildDef.WriteTo(nw, c.pkgNames)
3153		if err != nil {
3154			return err
3155		}
3156
3157		if len(buildDef.Args) > 0 {
3158			err = nw.BlankLine()
3159			if err != nil {
3160				return err
3161			}
3162		}
3163	}
3164
3165	return nil
3166}
3167
3168func beforeInModuleList(a, b *moduleInfo, list []*moduleInfo) bool {
3169	found := false
3170	if a == b {
3171		return false
3172	}
3173	for _, l := range list {
3174		if l == a {
3175			found = true
3176		} else if l == b {
3177			return found
3178		}
3179	}
3180
3181	missing := a
3182	if found {
3183		missing = b
3184	}
3185	panic(fmt.Errorf("element %v not found in list %v", missing, list))
3186}
3187
3188type panicError struct {
3189	panic interface{}
3190	stack []byte
3191	in    string
3192}
3193
3194func newPanicErrorf(panic interface{}, in string, a ...interface{}) error {
3195	buf := make([]byte, 4096)
3196	count := runtime.Stack(buf, false)
3197	return panicError{
3198		panic: panic,
3199		in:    fmt.Sprintf(in, a...),
3200		stack: buf[:count],
3201	}
3202}
3203
3204func (p panicError) Error() string {
3205	return fmt.Sprintf("panic in %s\n%s\n%s\n", p.in, p.panic, p.stack)
3206}
3207
3208func (p *panicError) addIn(in string) {
3209	p.in += " in " + in
3210}
3211
3212func funcName(f interface{}) string {
3213	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
3214}
3215
3216var fileHeaderTemplate = `******************************************************************************
3217***            This file is generated and should not be edited             ***
3218******************************************************************************
3219{{if .Pkgs}}
3220This file contains variables, rules, and pools with name prefixes indicating
3221they were generated by the following Go packages:
3222{{range .Pkgs}}
3223    {{.PkgName}} [from Go package {{.PkgPath}}]{{end}}{{end}}
3224
3225`
3226
3227var moduleHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
3228Module:  {{.name}}
3229Variant: {{.variant}}
3230Type:    {{.typeName}}
3231Factory: {{.goFactory}}
3232Defined: {{.pos}}
3233`
3234
3235var singletonHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
3236Singleton: {{.name}}
3237Factory:   {{.goFactory}}
3238`
3239