• 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(filename string, scope *parser.Scope) {
723		count++
724		go func() {
725			c.parseBlueprintsFile(filename, scope, rootDir,
726				errsCh, fileCh, blueprintsCh, depsCh)
727			doneCh <- struct{}{}
728		}()
729	}
730
731	tooManyErrors := false
732
733	startParseBlueprintsFile(rootFile, nil)
734
735loop:
736	for {
737		if len(errs) > maxErrors {
738			tooManyErrors = true
739		}
740
741		select {
742		case newErrs := <-errsCh:
743			errs = append(errs, newErrs...)
744		case dep := <-depsCh:
745			deps = append(deps, dep)
746		case file := <-fileCh:
747			handler(file)
748		case blueprint := <-blueprintsCh:
749			if tooManyErrors {
750				continue
751			}
752			if blueprintsSet[blueprint.string] {
753				continue
754			}
755
756			blueprintsSet[blueprint.string] = true
757			startParseBlueprintsFile(blueprint.string, blueprint.Scope)
758		case <-doneCh:
759			count--
760			if count == 0 {
761				break loop
762			}
763		}
764	}
765
766	return
767}
768
769// MockFileSystem causes the Context to replace all reads with accesses to the provided map of
770// filenames to contents stored as a byte slice.
771func (c *Context) MockFileSystem(files map[string][]byte) {
772	c.fs = pathtools.MockFs(files)
773}
774
775// parseBlueprintFile parses a single Blueprints file, returning any errors through
776// errsCh, any defined modules through modulesCh, any sub-Blueprints files through
777// blueprintsCh, and any dependencies on Blueprints files or directories through
778// depsCh.
779func (c *Context) parseBlueprintsFile(filename string, scope *parser.Scope, rootDir string,
780	errsCh chan<- []error, fileCh chan<- *parser.File, blueprintsCh chan<- stringAndScope,
781	depsCh chan<- string) {
782
783	f, err := c.fs.Open(filename)
784	if err != nil {
785		errsCh <- []error{err}
786		return
787	}
788	defer func() {
789		err = f.Close()
790		if err != nil {
791			errsCh <- []error{err}
792		}
793	}()
794
795	file, subBlueprints, errs := c.parse(rootDir, filename, f, scope)
796	if len(errs) > 0 {
797		errsCh <- errs
798	} else {
799		fileCh <- file
800	}
801
802	for _, b := range subBlueprints {
803		blueprintsCh <- b
804		depsCh <- b.string
805	}
806}
807
808func (c *Context) findBuildBlueprints(dir string, build []string,
809	buildPos scanner.Position) ([]string, []error) {
810
811	var blueprints []string
812	var errs []error
813
814	for _, file := range build {
815		pattern := filepath.Join(dir, file)
816		var matches []string
817		var err error
818
819		matches, err = c.glob(pattern, nil)
820
821		if err != nil {
822			errs = append(errs, &BlueprintError{
823				Err: fmt.Errorf("%q: %s", pattern, err.Error()),
824				Pos: buildPos,
825			})
826			continue
827		}
828
829		if len(matches) == 0 {
830			errs = append(errs, &BlueprintError{
831				Err: fmt.Errorf("%q: not found", pattern),
832				Pos: buildPos,
833			})
834		}
835
836		for _, foundBlueprints := range matches {
837			blueprints = append(blueprints, foundBlueprints)
838		}
839	}
840
841	return blueprints, errs
842}
843
844func (c *Context) findSubdirBlueprints(dir string, subdirs []string, subdirsPos scanner.Position,
845	subBlueprintsName string, optional bool) ([]string, []error) {
846
847	var blueprints []string
848	var errs []error
849
850	for _, subdir := range subdirs {
851		pattern := filepath.Join(dir, subdir, subBlueprintsName)
852		var matches []string
853		var err error
854
855		matches, err = c.glob(pattern, nil)
856
857		if err != nil {
858			errs = append(errs, &BlueprintError{
859				Err: fmt.Errorf("%q: %s", pattern, err.Error()),
860				Pos: subdirsPos,
861			})
862			continue
863		}
864
865		if len(matches) == 0 && !optional {
866			errs = append(errs, &BlueprintError{
867				Err: fmt.Errorf("%q: not found", pattern),
868				Pos: subdirsPos,
869			})
870		}
871
872		for _, subBlueprints := range matches {
873			blueprints = append(blueprints, subBlueprints)
874		}
875	}
876
877	return blueprints, errs
878}
879
880func getLocalStringListFromScope(scope *parser.Scope, v string) ([]string, scanner.Position, error) {
881	if assignment, local := scope.Get(v); assignment == nil || !local {
882		return nil, scanner.Position{}, nil
883	} else {
884		switch value := assignment.Value.Eval().(type) {
885		case *parser.List:
886			ret := make([]string, 0, len(value.Values))
887
888			for _, listValue := range value.Values {
889				s, ok := listValue.(*parser.String)
890				if !ok {
891					// The parser should not produce this.
892					panic("non-string value found in list")
893				}
894
895				ret = append(ret, s.Value)
896			}
897
898			return ret, assignment.EqualsPos, nil
899		case *parser.Bool, *parser.String:
900			return nil, scanner.Position{}, &BlueprintError{
901				Err: fmt.Errorf("%q must be a list of strings", v),
902				Pos: assignment.EqualsPos,
903			}
904		default:
905			panic(fmt.Errorf("unknown value type: %d", assignment.Value.Type))
906		}
907	}
908}
909
910func getStringFromScope(scope *parser.Scope, v string) (string, scanner.Position, error) {
911	if assignment, _ := scope.Get(v); assignment == nil {
912		return "", scanner.Position{}, nil
913	} else {
914		switch value := assignment.Value.Eval().(type) {
915		case *parser.String:
916			return value.Value, assignment.EqualsPos, nil
917		case *parser.Bool, *parser.List:
918			return "", scanner.Position{}, &BlueprintError{
919				Err: fmt.Errorf("%q must be a string", v),
920				Pos: assignment.EqualsPos,
921			}
922		default:
923			panic(fmt.Errorf("unknown value type: %d", assignment.Value.Type))
924		}
925	}
926}
927
928// Clones a build logic module by calling the factory method for its module type, and then cloning
929// property values.  Any values stored in the module object that are not stored in properties
930// structs will be lost.
931func (c *Context) cloneLogicModule(origModule *moduleInfo) (Module, []interface{}) {
932	typeName := origModule.typeName
933	factory, ok := c.moduleFactories[typeName]
934	if !ok {
935		panic(fmt.Sprintf("unrecognized module type %q during cloning", typeName))
936	}
937
938	newLogicModule, newProperties := factory()
939
940	if len(newProperties) != len(origModule.moduleProperties) {
941		panic("mismatched properties array length in " + origModule.Name())
942	}
943
944	for i := range newProperties {
945		dst := reflect.ValueOf(newProperties[i]).Elem()
946		src := reflect.ValueOf(origModule.moduleProperties[i]).Elem()
947
948		proptools.CopyProperties(dst, src)
949	}
950
951	return newLogicModule, newProperties
952}
953
954func (c *Context) createVariations(origModule *moduleInfo, mutatorName string,
955	variationNames []string) ([]*moduleInfo, []error) {
956
957	if len(variationNames) == 0 {
958		panic(fmt.Errorf("mutator %q passed zero-length variation list for module %q",
959			mutatorName, origModule.Name()))
960	}
961
962	newModules := []*moduleInfo{}
963
964	var errs []error
965
966	for i, variationName := range variationNames {
967		var newLogicModule Module
968		var newProperties []interface{}
969
970		if i == 0 {
971			// Reuse the existing module for the first new variant
972			// This both saves creating a new module, and causes the insertion in c.moduleInfo below
973			// with logicModule as the key to replace the original entry in c.moduleInfo
974			newLogicModule, newProperties = origModule.logicModule, origModule.moduleProperties
975		} else {
976			newLogicModule, newProperties = c.cloneLogicModule(origModule)
977		}
978
979		newVariant := origModule.variant.clone()
980		newVariant[mutatorName] = variationName
981
982		m := *origModule
983		newModule := &m
984		newModule.directDeps = append([]depInfo{}, origModule.directDeps...)
985		newModule.logicModule = newLogicModule
986		newModule.variant = newVariant
987		newModule.dependencyVariant = origModule.dependencyVariant.clone()
988		newModule.moduleProperties = newProperties
989
990		if variationName != "" {
991			if newModule.variantName == "" {
992				newModule.variantName = variationName
993			} else {
994				newModule.variantName += "_" + variationName
995			}
996		}
997
998		newModules = append(newModules, newModule)
999
1000		newErrs := c.convertDepsToVariation(newModule, mutatorName, variationName)
1001		if len(newErrs) > 0 {
1002			errs = append(errs, newErrs...)
1003		}
1004	}
1005
1006	// Mark original variant as invalid.  Modules that depend on this module will still
1007	// depend on origModule, but we'll fix it when the mutator is called on them.
1008	origModule.logicModule = nil
1009	origModule.splitModules = newModules
1010
1011	atomic.AddUint32(&c.depsModified, 1)
1012
1013	return newModules, errs
1014}
1015
1016func (c *Context) convertDepsToVariation(module *moduleInfo,
1017	mutatorName, variationName string) (errs []error) {
1018
1019	for i, dep := range module.directDeps {
1020		if dep.module.logicModule == nil {
1021			var newDep *moduleInfo
1022			for _, m := range dep.module.splitModules {
1023				if m.variant[mutatorName] == variationName {
1024					newDep = m
1025					break
1026				}
1027			}
1028			if newDep == nil {
1029				errs = append(errs, &BlueprintError{
1030					Err: fmt.Errorf("failed to find variation %q for module %q needed by %q",
1031						variationName, dep.module.Name(), module.Name()),
1032					Pos: module.pos,
1033				})
1034				continue
1035			}
1036			module.directDeps[i].module = newDep
1037		}
1038	}
1039
1040	return errs
1041}
1042
1043func (c *Context) prettyPrintVariant(variant variationMap) string {
1044	names := make([]string, 0, len(variant))
1045	for _, m := range c.variantMutatorNames {
1046		if v, ok := variant[m]; ok {
1047			names = append(names, m+":"+v)
1048		}
1049	}
1050
1051	return strings.Join(names, ", ")
1052}
1053
1054func (c *Context) processModuleDef(moduleDef *parser.Module,
1055	relBlueprintsFile string) (*moduleInfo, []error) {
1056
1057	factory, ok := c.moduleFactories[moduleDef.Type]
1058	if !ok {
1059		if c.ignoreUnknownModuleTypes {
1060			return nil, nil
1061		}
1062
1063		return nil, []error{
1064			&BlueprintError{
1065				Err: fmt.Errorf("unrecognized module type %q", moduleDef.Type),
1066				Pos: moduleDef.TypePos,
1067			},
1068		}
1069	}
1070
1071	logicModule, properties := factory()
1072
1073	module := &moduleInfo{
1074		logicModule:       logicModule,
1075		typeName:          moduleDef.Type,
1076		relBlueprintsFile: relBlueprintsFile,
1077	}
1078
1079	module.moduleProperties = properties
1080
1081	propertyMap, errs := unpackProperties(moduleDef.Properties, properties...)
1082	if len(errs) > 0 {
1083		return nil, errs
1084	}
1085
1086	module.pos = moduleDef.TypePos
1087	module.propertyPos = make(map[string]scanner.Position)
1088	for name, propertyDef := range propertyMap {
1089		module.propertyPos[name] = propertyDef.ColonPos
1090	}
1091
1092	return module, nil
1093}
1094
1095func (c *Context) addModule(module *moduleInfo) []error {
1096	name := module.logicModule.Name()
1097	c.moduleInfo[module.logicModule] = module
1098
1099	if group, present := c.moduleNames[name]; present {
1100		return []error{
1101			&BlueprintError{
1102				Err: fmt.Errorf("module %q already defined", name),
1103				Pos: module.pos,
1104			},
1105			&BlueprintError{
1106				Err: fmt.Errorf("<-- previous definition here"),
1107				Pos: group.modules[0].pos,
1108			},
1109		}
1110	}
1111
1112	ninjaName := toNinjaName(name)
1113
1114	// The sanitizing in toNinjaName can result in collisions, uniquify the name if it
1115	// already exists
1116	for i := 0; c.moduleNinjaNames[ninjaName] != nil; i++ {
1117		ninjaName = toNinjaName(name) + strconv.Itoa(i)
1118	}
1119
1120	group := &moduleGroup{
1121		name:      name,
1122		ninjaName: ninjaName,
1123		modules:   []*moduleInfo{module},
1124	}
1125	module.group = group
1126	c.moduleNames[name] = group
1127	c.moduleNinjaNames[ninjaName] = group
1128	c.moduleGroups = append(c.moduleGroups, group)
1129
1130	return nil
1131}
1132
1133// ResolveDependencies checks that the dependencies specified by all of the
1134// modules defined in the parsed Blueprints files are valid.  This means that
1135// the modules depended upon are defined and that no circular dependencies
1136// exist.
1137func (c *Context) ResolveDependencies(config interface{}) []error {
1138	errs := c.updateDependencies()
1139	if len(errs) > 0 {
1140		return errs
1141	}
1142
1143	errs = c.runMutators(config)
1144	if len(errs) > 0 {
1145		return errs
1146	}
1147
1148	c.cloneModules()
1149
1150	c.dependenciesReady = true
1151	return nil
1152}
1153
1154// Default dependencies handling.  If the module implements the (deprecated)
1155// DynamicDependerModule interface then this set consists of the union of those
1156// module names returned by its DynamicDependencies method and those added by calling
1157// AddDependencies or AddVariationDependencies on DynamicDependencyModuleContext.
1158func blueprintDepsMutator(ctx BottomUpMutatorContext) {
1159	if dynamicDepender, ok := ctx.Module().(DynamicDependerModule); ok {
1160		func() {
1161			defer func() {
1162				if r := recover(); r != nil {
1163					ctx.error(newPanicErrorf(r, "DynamicDependencies for %s", ctx.moduleInfo()))
1164				}
1165			}()
1166			dynamicDeps := dynamicDepender.DynamicDependencies(ctx)
1167
1168			if ctx.Failed() {
1169				return
1170			}
1171
1172			ctx.AddDependency(ctx.Module(), nil, dynamicDeps...)
1173		}()
1174	}
1175}
1176
1177// findMatchingVariant searches the moduleGroup for a module with the same variant as module,
1178// and returns the matching module, or nil if one is not found.
1179func (c *Context) findMatchingVariant(module *moduleInfo, possible []*moduleInfo) *moduleInfo {
1180	if len(possible) == 1 {
1181		return possible[0]
1182	} else {
1183		for _, m := range possible {
1184			if m.variant.equal(module.dependencyVariant) {
1185				return m
1186			}
1187		}
1188	}
1189
1190	return nil
1191}
1192
1193func (c *Context) addDependency(module *moduleInfo, tag DependencyTag, depName string) []error {
1194	if _, ok := tag.(BaseDependencyTag); ok {
1195		panic("BaseDependencyTag is not allowed to be used directly!")
1196	}
1197
1198	if depName == module.Name() {
1199		return []error{&BlueprintError{
1200			Err: fmt.Errorf("%q depends on itself", depName),
1201			Pos: module.pos,
1202		}}
1203	}
1204
1205	possibleDeps := c.modulesFromName(depName)
1206	if possibleDeps == nil {
1207		if c.allowMissingDependencies {
1208			module.missingDeps = append(module.missingDeps, depName)
1209			return nil
1210		}
1211		return []error{&BlueprintError{
1212			Err: fmt.Errorf("%q depends on undefined module %q",
1213				module.Name(), depName),
1214			Pos: module.pos,
1215		}}
1216	}
1217
1218	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
1219		for _, dep := range module.directDeps {
1220			if m == dep.module {
1221				// TODO(ccross): what if adding a dependency with a different tag?
1222				return nil
1223			}
1224		}
1225		module.directDeps = append(module.directDeps, depInfo{m, tag})
1226		atomic.AddUint32(&c.depsModified, 1)
1227		return nil
1228	}
1229
1230	variants := make([]string, len(possibleDeps))
1231	for i, mod := range possibleDeps {
1232		variants[i] = c.prettyPrintVariant(mod.variant)
1233	}
1234	sort.Strings(variants)
1235
1236	return []error{&BlueprintError{
1237		Err: fmt.Errorf("dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1238			depName, module.Name(),
1239			c.prettyPrintVariant(module.dependencyVariant),
1240			strings.Join(variants, "\n  ")),
1241		Pos: module.pos,
1242	}}
1243}
1244
1245func (c *Context) findReverseDependency(module *moduleInfo, destName string) (*moduleInfo, []error) {
1246	if destName == module.Name() {
1247		return nil, []error{&BlueprintError{
1248			Err: fmt.Errorf("%q depends on itself", destName),
1249			Pos: module.pos,
1250		}}
1251	}
1252
1253	possibleDeps := c.modulesFromName(destName)
1254	if possibleDeps == nil {
1255		return nil, []error{&BlueprintError{
1256			Err: fmt.Errorf("%q has a reverse dependency on undefined module %q",
1257				module.Name(), destName),
1258			Pos: module.pos,
1259		}}
1260	}
1261
1262	if m := c.findMatchingVariant(module, possibleDeps); m != nil {
1263		return m, nil
1264	}
1265
1266	variants := make([]string, len(possibleDeps))
1267	for i, mod := range possibleDeps {
1268		variants[i] = c.prettyPrintVariant(mod.variant)
1269	}
1270	sort.Strings(variants)
1271
1272	return nil, []error{&BlueprintError{
1273		Err: fmt.Errorf("reverse dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1274			destName, module.Name(),
1275			c.prettyPrintVariant(module.dependencyVariant),
1276			strings.Join(variants, "\n  ")),
1277		Pos: module.pos,
1278	}}
1279}
1280
1281func (c *Context) addVariationDependency(module *moduleInfo, variations []Variation,
1282	tag DependencyTag, depName string, far bool) []error {
1283	if _, ok := tag.(BaseDependencyTag); ok {
1284		panic("BaseDependencyTag is not allowed to be used directly!")
1285	}
1286
1287	possibleDeps := c.modulesFromName(depName)
1288	if possibleDeps == nil {
1289		if c.allowMissingDependencies {
1290			module.missingDeps = append(module.missingDeps, depName)
1291			return nil
1292		}
1293		return []error{&BlueprintError{
1294			Err: fmt.Errorf("%q depends on undefined module %q",
1295				module.Name(), depName),
1296			Pos: module.pos,
1297		}}
1298	}
1299
1300	// We can't just append variant.Variant to module.dependencyVariants.variantName and
1301	// compare the strings because the result won't be in mutator registration order.
1302	// Create a new map instead, and then deep compare the maps.
1303	var newVariant variationMap
1304	if !far {
1305		newVariant = module.dependencyVariant.clone()
1306	} else {
1307		newVariant = make(variationMap)
1308	}
1309	for _, v := range variations {
1310		newVariant[v.Mutator] = v.Variation
1311	}
1312
1313	for _, m := range possibleDeps {
1314		var found bool
1315		if far {
1316			found = m.variant.subset(newVariant)
1317		} else {
1318			found = m.variant.equal(newVariant)
1319		}
1320		if found {
1321			if module == m {
1322				return []error{&BlueprintError{
1323					Err: fmt.Errorf("%q depends on itself", depName),
1324					Pos: module.pos,
1325				}}
1326			}
1327			// AddVariationDependency allows adding a dependency on itself, but only if
1328			// that module is earlier in the module list than this one, since we always
1329			// run GenerateBuildActions in order for the variants of a module
1330			if m.group == module.group && beforeInModuleList(module, m, module.group.modules) {
1331				return []error{&BlueprintError{
1332					Err: fmt.Errorf("%q depends on later version of itself", depName),
1333					Pos: module.pos,
1334				}}
1335			}
1336			module.directDeps = append(module.directDeps, depInfo{m, tag})
1337			atomic.AddUint32(&c.depsModified, 1)
1338			return nil
1339		}
1340	}
1341
1342	variants := make([]string, len(possibleDeps))
1343	for i, mod := range possibleDeps {
1344		variants[i] = c.prettyPrintVariant(mod.variant)
1345	}
1346	sort.Strings(variants)
1347
1348	return []error{&BlueprintError{
1349		Err: fmt.Errorf("dependency %q of %q missing variant:\n  %s\navailable variants:\n  %s",
1350			depName, module.Name(),
1351			c.prettyPrintVariant(newVariant),
1352			strings.Join(variants, "\n  ")),
1353		Pos: module.pos,
1354	}}
1355}
1356
1357func (c *Context) addInterVariantDependency(origModule *moduleInfo, tag DependencyTag,
1358	from, to Module) {
1359	if _, ok := tag.(BaseDependencyTag); ok {
1360		panic("BaseDependencyTag is not allowed to be used directly!")
1361	}
1362
1363	var fromInfo, toInfo *moduleInfo
1364	for _, m := range origModule.splitModules {
1365		if m.logicModule == from {
1366			fromInfo = m
1367		}
1368		if m.logicModule == to {
1369			toInfo = m
1370			if fromInfo != nil {
1371				panic(fmt.Errorf("%q depends on later version of itself", origModule.Name()))
1372			}
1373		}
1374	}
1375
1376	if fromInfo == nil || toInfo == nil {
1377		panic(fmt.Errorf("AddInterVariantDependency called for module %q on invalid variant",
1378			origModule.Name()))
1379	}
1380
1381	fromInfo.directDeps = append(fromInfo.directDeps, depInfo{toInfo, tag})
1382	atomic.AddUint32(&c.depsModified, 1)
1383}
1384
1385type visitOrderer interface {
1386	// returns the number of modules that this module needs to wait for
1387	waitCount(module *moduleInfo) int
1388	// returns the list of modules that are waiting for this module
1389	propagate(module *moduleInfo) []*moduleInfo
1390	// visit modules in order
1391	visit(modules []*moduleInfo, visit func(*moduleInfo) bool)
1392}
1393
1394type bottomUpVisitorImpl struct{}
1395
1396func (bottomUpVisitorImpl) waitCount(module *moduleInfo) int {
1397	return len(module.forwardDeps)
1398}
1399
1400func (bottomUpVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
1401	return module.reverseDeps
1402}
1403
1404func (bottomUpVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo) bool) {
1405	for _, module := range modules {
1406		if visit(module) {
1407			return
1408		}
1409	}
1410}
1411
1412type topDownVisitorImpl struct{}
1413
1414func (topDownVisitorImpl) waitCount(module *moduleInfo) int {
1415	return len(module.reverseDeps)
1416}
1417
1418func (topDownVisitorImpl) propagate(module *moduleInfo) []*moduleInfo {
1419	return module.forwardDeps
1420}
1421
1422func (topDownVisitorImpl) visit(modules []*moduleInfo, visit func(*moduleInfo) bool) {
1423	for i := 0; i < len(modules); i++ {
1424		module := modules[len(modules)-1-i]
1425		if visit(module) {
1426			return
1427		}
1428	}
1429}
1430
1431var (
1432	bottomUpVisitor bottomUpVisitorImpl
1433	topDownVisitor  topDownVisitorImpl
1434)
1435
1436// Calls visit on each module, guaranteeing that visit is not called on a module until visit on all
1437// of its dependencies has finished.
1438func (c *Context) parallelVisit(order visitOrderer, visit func(group *moduleInfo) bool) {
1439	doneCh := make(chan *moduleInfo)
1440	cancelCh := make(chan bool)
1441	count := 0
1442	cancel := false
1443
1444	for _, module := range c.modulesSorted {
1445		module.waitingCount = order.waitCount(module)
1446	}
1447
1448	visitOne := func(module *moduleInfo) {
1449		count++
1450		go func() {
1451			ret := visit(module)
1452			if ret {
1453				cancelCh <- true
1454			}
1455			doneCh <- module
1456		}()
1457	}
1458
1459	for _, module := range c.modulesSorted {
1460		if module.waitingCount == 0 {
1461			visitOne(module)
1462		}
1463	}
1464
1465	for count > 0 {
1466		select {
1467		case cancel = <-cancelCh:
1468		case doneModule := <-doneCh:
1469			if !cancel {
1470				for _, module := range order.propagate(doneModule) {
1471					module.waitingCount--
1472					if module.waitingCount == 0 {
1473						visitOne(module)
1474					}
1475				}
1476			}
1477			count--
1478		}
1479	}
1480}
1481
1482// updateDependencies recursively walks the module dependency graph and updates
1483// additional fields based on the dependencies.  It builds a sorted list of modules
1484// such that dependencies of a module always appear first, and populates reverse
1485// dependency links and counts of total dependencies.  It also reports errors when
1486// it encounters dependency cycles.  This should called after resolveDependencies,
1487// as well as after any mutator pass has called addDependency
1488func (c *Context) updateDependencies() (errs []error) {
1489	visited := make(map[*moduleInfo]bool)  // modules that were already checked
1490	checking := make(map[*moduleInfo]bool) // modules actively being checked
1491
1492	sorted := make([]*moduleInfo, 0, len(c.moduleInfo))
1493
1494	var check func(group *moduleInfo) []*moduleInfo
1495
1496	cycleError := func(cycle []*moduleInfo) {
1497		// We are the "start" of the cycle, so we're responsible
1498		// for generating the errors.  The cycle list is in
1499		// reverse order because all the 'check' calls append
1500		// their own module to the list.
1501		errs = append(errs, &BlueprintError{
1502			Err: fmt.Errorf("encountered dependency cycle:"),
1503			Pos: cycle[len(cycle)-1].pos,
1504		})
1505
1506		// Iterate backwards through the cycle list.
1507		curModule := cycle[0]
1508		for i := len(cycle) - 1; i >= 0; i-- {
1509			nextModule := cycle[i]
1510			errs = append(errs, &BlueprintError{
1511				Err: fmt.Errorf("    %q depends on %q",
1512					curModule.Name(),
1513					nextModule.Name()),
1514				Pos: curModule.pos,
1515			})
1516			curModule = nextModule
1517		}
1518	}
1519
1520	check = func(module *moduleInfo) []*moduleInfo {
1521		visited[module] = true
1522		checking[module] = true
1523		defer delete(checking, module)
1524
1525		deps := make(map[*moduleInfo]bool)
1526
1527		// Add an implicit dependency ordering on all earlier modules in the same module group
1528		for _, dep := range module.group.modules {
1529			if dep == module {
1530				break
1531			}
1532			deps[dep] = true
1533		}
1534
1535		for _, dep := range module.directDeps {
1536			deps[dep.module] = true
1537		}
1538
1539		module.reverseDeps = []*moduleInfo{}
1540		module.forwardDeps = []*moduleInfo{}
1541
1542		for dep := range deps {
1543			if checking[dep] {
1544				// This is a cycle.
1545				return []*moduleInfo{dep, module}
1546			}
1547
1548			if !visited[dep] {
1549				cycle := check(dep)
1550				if cycle != nil {
1551					if cycle[0] == module {
1552						// We are the "start" of the cycle, so we're responsible
1553						// for generating the errors.  The cycle list is in
1554						// reverse order because all the 'check' calls append
1555						// their own module to the list.
1556						cycleError(cycle)
1557
1558						// We can continue processing this module's children to
1559						// find more cycles.  Since all the modules that were
1560						// part of the found cycle were marked as visited we
1561						// won't run into that cycle again.
1562					} else {
1563						// We're not the "start" of the cycle, so we just append
1564						// our module to the list and return it.
1565						return append(cycle, module)
1566					}
1567				}
1568			}
1569
1570			module.forwardDeps = append(module.forwardDeps, dep)
1571			dep.reverseDeps = append(dep.reverseDeps, module)
1572		}
1573
1574		sorted = append(sorted, module)
1575
1576		return nil
1577	}
1578
1579	for _, module := range c.moduleInfo {
1580		if !visited[module] {
1581			cycle := check(module)
1582			if cycle != nil {
1583				if cycle[len(cycle)-1] != module {
1584					panic("inconceivable!")
1585				}
1586				cycleError(cycle)
1587			}
1588		}
1589	}
1590
1591	c.modulesSorted = sorted
1592
1593	return
1594}
1595
1596// PrepareBuildActions generates an internal representation of all the build
1597// actions that need to be performed.  This process involves invoking the
1598// GenerateBuildActions method on each of the Module objects created during the
1599// parse phase and then on each of the registered Singleton objects.
1600//
1601// If the ResolveDependencies method has not already been called it is called
1602// automatically by this method.
1603//
1604// The config argument is made available to all of the Module and Singleton
1605// objects via the Config method on the ModuleContext and SingletonContext
1606// objects passed to GenerateBuildActions.  It is also passed to the functions
1607// specified via PoolFunc, RuleFunc, and VariableFunc so that they can compute
1608// config-specific values.
1609//
1610// The returned deps is a list of the ninja files dependencies that were added
1611// by the modules and singletons via the ModuleContext.AddNinjaFileDeps(),
1612// SingletonContext.AddNinjaFileDeps(), and PackageContext.AddNinjaFileDeps()
1613// methods.
1614func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs []error) {
1615	c.buildActionsReady = false
1616
1617	if !c.dependenciesReady {
1618		errs := c.ResolveDependencies(config)
1619		if len(errs) > 0 {
1620			return nil, errs
1621		}
1622	}
1623
1624	liveGlobals := newLiveTracker(config)
1625
1626	c.initSpecialVariables()
1627
1628	depsModules, errs := c.generateModuleBuildActions(config, liveGlobals)
1629	if len(errs) > 0 {
1630		return nil, errs
1631	}
1632
1633	depsSingletons, errs := c.generateSingletonBuildActions(config, liveGlobals)
1634	if len(errs) > 0 {
1635		return nil, errs
1636	}
1637
1638	deps = append(depsModules, depsSingletons...)
1639
1640	if c.ninjaBuildDir != nil {
1641		liveGlobals.addNinjaStringDeps(c.ninjaBuildDir)
1642	}
1643
1644	pkgNames, depsPackages := c.makeUniquePackageNames(liveGlobals)
1645
1646	deps = append(deps, depsPackages...)
1647
1648	// This will panic if it finds a problem since it's a programming error.
1649	c.checkForVariableReferenceCycles(liveGlobals.variables, pkgNames)
1650
1651	c.pkgNames = pkgNames
1652	c.globalVariables = liveGlobals.variables
1653	c.globalPools = liveGlobals.pools
1654	c.globalRules = liveGlobals.rules
1655
1656	c.buildActionsReady = true
1657
1658	return deps, nil
1659}
1660
1661func (c *Context) runMutators(config interface{}) (errs []error) {
1662	var mutators []*mutatorInfo
1663
1664	mutators = append(mutators, c.earlyMutatorInfo...)
1665	mutators = append(mutators, c.mutatorInfo...)
1666
1667	for _, mutator := range mutators {
1668		if mutator.topDownMutator != nil {
1669			errs = c.runMutator(config, mutator, topDownMutator)
1670		} else if mutator.bottomUpMutator != nil {
1671			errs = c.runMutator(config, mutator, bottomUpMutator)
1672		} else {
1673			panic("no mutator set on " + mutator.name)
1674		}
1675		if len(errs) > 0 {
1676			return errs
1677		}
1678	}
1679
1680	return nil
1681}
1682
1683type mutatorDirection interface {
1684	run(mutator *mutatorInfo, ctx *mutatorContext)
1685	orderer() visitOrderer
1686	fmt.Stringer
1687}
1688
1689type bottomUpMutatorImpl struct{}
1690
1691func (bottomUpMutatorImpl) run(mutator *mutatorInfo, ctx *mutatorContext) {
1692	mutator.bottomUpMutator(ctx)
1693}
1694
1695func (bottomUpMutatorImpl) orderer() visitOrderer {
1696	return bottomUpVisitor
1697}
1698
1699func (bottomUpMutatorImpl) String() string {
1700	return "bottom up mutator"
1701}
1702
1703type topDownMutatorImpl struct{}
1704
1705func (topDownMutatorImpl) run(mutator *mutatorInfo, ctx *mutatorContext) {
1706	mutator.topDownMutator(ctx)
1707}
1708
1709func (topDownMutatorImpl) orderer() visitOrderer {
1710	return topDownVisitor
1711}
1712
1713func (topDownMutatorImpl) String() string {
1714	return "top down mutator"
1715}
1716
1717var (
1718	topDownMutator  topDownMutatorImpl
1719	bottomUpMutator bottomUpMutatorImpl
1720)
1721
1722type reverseDep struct {
1723	module *moduleInfo
1724	dep    depInfo
1725}
1726
1727func (c *Context) runMutator(config interface{}, mutator *mutatorInfo,
1728	direction mutatorDirection) (errs []error) {
1729
1730	newModuleInfo := make(map[Module]*moduleInfo)
1731	for k, v := range c.moduleInfo {
1732		newModuleInfo[k] = v
1733	}
1734
1735	type globalStateChange struct {
1736		reverse []reverseDep
1737		rename  []rename
1738		replace []replace
1739	}
1740
1741	reverseDeps := make(map[*moduleInfo][]depInfo)
1742	var rename []rename
1743	var replace []replace
1744
1745	errsCh := make(chan []error)
1746	globalStateCh := make(chan globalStateChange)
1747	newModulesCh := make(chan []*moduleInfo)
1748	done := make(chan bool)
1749
1750	c.depsModified = 0
1751
1752	visit := func(module *moduleInfo) bool {
1753		if module.splitModules != nil {
1754			panic("split module found in sorted module list")
1755		}
1756
1757		mctx := &mutatorContext{
1758			baseModuleContext: baseModuleContext{
1759				context: c,
1760				config:  config,
1761				module:  module,
1762			},
1763			name: mutator.name,
1764		}
1765
1766		func() {
1767			defer func() {
1768				if r := recover(); r != nil {
1769					in := fmt.Sprintf("%s %q for %s", direction, mutator.name, module)
1770					if err, ok := r.(panicError); ok {
1771						err.addIn(in)
1772						mctx.error(err)
1773					} else {
1774						mctx.error(newPanicErrorf(r, in))
1775					}
1776				}
1777			}()
1778			direction.run(mutator, mctx)
1779		}()
1780
1781		if len(mctx.errs) > 0 {
1782			errsCh <- mctx.errs
1783			return true
1784		}
1785
1786		if len(mctx.newModules) > 0 {
1787			newModulesCh <- mctx.newModules
1788		}
1789
1790		if len(mctx.reverseDeps) > 0 || len(mctx.replace) > 0 || len(mctx.rename) > 0 {
1791			globalStateCh <- globalStateChange{
1792				reverse: mctx.reverseDeps,
1793				replace: mctx.replace,
1794				rename:  mctx.rename,
1795			}
1796		}
1797
1798		return false
1799	}
1800
1801	// Process errs and reverseDeps in a single goroutine
1802	go func() {
1803		for {
1804			select {
1805			case newErrs := <-errsCh:
1806				errs = append(errs, newErrs...)
1807			case globalStateChange := <-globalStateCh:
1808				for _, r := range globalStateChange.reverse {
1809					reverseDeps[r.module] = append(reverseDeps[r.module], r.dep)
1810				}
1811				replace = append(replace, globalStateChange.replace...)
1812				rename = append(rename, globalStateChange.rename...)
1813			case newModules := <-newModulesCh:
1814				for _, m := range newModules {
1815					newModuleInfo[m.logicModule] = m
1816				}
1817			case <-done:
1818				return
1819			}
1820		}
1821	}()
1822
1823	if mutator.parallel {
1824		c.parallelVisit(direction.orderer(), visit)
1825	} else {
1826		direction.orderer().visit(c.modulesSorted, visit)
1827	}
1828
1829	done <- true
1830
1831	if len(errs) > 0 {
1832		return errs
1833	}
1834
1835	c.moduleInfo = newModuleInfo
1836
1837	for _, group := range c.moduleGroups {
1838		for i := 0; i < len(group.modules); i++ {
1839			module := group.modules[i]
1840
1841			// Update module group to contain newly split variants
1842			if module.splitModules != nil {
1843				group.modules, i = spliceModules(group.modules, i, module.splitModules)
1844			}
1845
1846			// Fix up any remaining dependencies on modules that were split into variants
1847			// by replacing them with the first variant
1848			for j, dep := range module.directDeps {
1849				if dep.module.logicModule == nil {
1850					module.directDeps[j].module = dep.module.splitModules[0]
1851				}
1852			}
1853		}
1854	}
1855
1856	for module, deps := range reverseDeps {
1857		sort.Sort(depSorter(deps))
1858		module.directDeps = append(module.directDeps, deps...)
1859		c.depsModified++
1860	}
1861
1862	errs = c.handleRenames(rename)
1863	if len(errs) > 0 {
1864		return errs
1865	}
1866
1867	errs = c.handleReplacements(replace)
1868	if len(errs) > 0 {
1869		return errs
1870	}
1871
1872	if c.depsModified > 0 {
1873		errs = c.updateDependencies()
1874		if len(errs) > 0 {
1875			return errs
1876		}
1877	}
1878
1879	return errs
1880}
1881
1882// Replaces every build logic module with a clone of itself.  Prevents introducing problems where
1883// a mutator sets a non-property member variable on a module, which works until a later mutator
1884// creates variants of that module.
1885func (c *Context) cloneModules() {
1886	type update struct {
1887		orig  Module
1888		clone *moduleInfo
1889	}
1890	ch := make(chan update, 100)
1891
1892	for _, m := range c.modulesSorted {
1893		go func(m *moduleInfo) {
1894			origLogicModule := m.logicModule
1895			m.logicModule, m.moduleProperties = c.cloneLogicModule(m)
1896			ch <- update{origLogicModule, m}
1897		}(m)
1898	}
1899
1900	for i := 0; i < len(c.modulesSorted); i++ {
1901		update := <-ch
1902		delete(c.moduleInfo, update.orig)
1903		c.moduleInfo[update.clone.logicModule] = update.clone
1904	}
1905}
1906
1907// Removes modules[i] from the list and inserts newModules... where it was located, returning
1908// the new slice and the index of the last inserted element
1909func spliceModules(modules []*moduleInfo, i int, newModules []*moduleInfo) ([]*moduleInfo, int) {
1910	spliceSize := len(newModules)
1911	newLen := len(modules) + spliceSize - 1
1912	var dest []*moduleInfo
1913	if cap(modules) >= len(modules)-1+len(newModules) {
1914		// We can fit the splice in the existing capacity, do everything in place
1915		dest = modules[:newLen]
1916	} else {
1917		dest = make([]*moduleInfo, newLen)
1918		copy(dest, modules[:i])
1919	}
1920
1921	// Move the end of the slice over by spliceSize-1
1922	copy(dest[i+spliceSize:], modules[i+1:])
1923
1924	// Copy the new modules into the slice
1925	copy(dest[i:], newModules)
1926
1927	return dest, i + spliceSize - 1
1928}
1929
1930func (c *Context) initSpecialVariables() {
1931	c.ninjaBuildDir = nil
1932	c.requiredNinjaMajor = 1
1933	c.requiredNinjaMinor = 7
1934	c.requiredNinjaMicro = 0
1935}
1936
1937func (c *Context) generateModuleBuildActions(config interface{},
1938	liveGlobals *liveTracker) ([]string, []error) {
1939
1940	var deps []string
1941	var errs []error
1942
1943	cancelCh := make(chan struct{})
1944	errsCh := make(chan []error)
1945	depsCh := make(chan []string)
1946
1947	go func() {
1948		for {
1949			select {
1950			case <-cancelCh:
1951				close(cancelCh)
1952				return
1953			case newErrs := <-errsCh:
1954				errs = append(errs, newErrs...)
1955			case newDeps := <-depsCh:
1956				deps = append(deps, newDeps...)
1957
1958			}
1959		}
1960	}()
1961
1962	c.parallelVisit(bottomUpVisitor, func(module *moduleInfo) bool {
1963		// The parent scope of the moduleContext's local scope gets overridden to be that of the
1964		// calling Go package on a per-call basis.  Since the initial parent scope doesn't matter we
1965		// just set it to nil.
1966		prefix := moduleNamespacePrefix(module.group.ninjaName + "_" + module.variantName)
1967		scope := newLocalScope(nil, prefix)
1968
1969		mctx := &moduleContext{
1970			baseModuleContext: baseModuleContext{
1971				context: c,
1972				config:  config,
1973				module:  module,
1974			},
1975			scope:              scope,
1976			handledMissingDeps: module.missingDeps == nil,
1977		}
1978
1979		func() {
1980			defer func() {
1981				if r := recover(); r != nil {
1982					in := fmt.Sprintf("GenerateBuildActions for %s", module)
1983					if err, ok := r.(panicError); ok {
1984						err.addIn(in)
1985						mctx.error(err)
1986					} else {
1987						mctx.error(newPanicErrorf(r, in))
1988					}
1989				}
1990			}()
1991			mctx.module.logicModule.GenerateBuildActions(mctx)
1992		}()
1993
1994		if len(mctx.errs) > 0 {
1995			errsCh <- mctx.errs
1996			return true
1997		}
1998
1999		if module.missingDeps != nil && !mctx.handledMissingDeps {
2000			var errs []error
2001			for _, depName := range module.missingDeps {
2002				errs = append(errs, &BlueprintError{
2003					Err: fmt.Errorf("%q depends on undefined module %q",
2004						module.Name(), depName),
2005					Pos: module.pos,
2006				})
2007			}
2008			errsCh <- errs
2009			return true
2010		}
2011
2012		depsCh <- mctx.ninjaFileDeps
2013
2014		newErrs := c.processLocalBuildActions(&module.actionDefs,
2015			&mctx.actionDefs, liveGlobals)
2016		if len(newErrs) > 0 {
2017			errsCh <- newErrs
2018			return true
2019		}
2020		return false
2021	})
2022
2023	cancelCh <- struct{}{}
2024	<-cancelCh
2025
2026	return deps, errs
2027}
2028
2029func (c *Context) generateSingletonBuildActions(config interface{},
2030	liveGlobals *liveTracker) ([]string, []error) {
2031
2032	var deps []string
2033	var errs []error
2034
2035	for _, info := range c.singletonInfo {
2036		// The parent scope of the singletonContext's local scope gets overridden to be that of the
2037		// calling Go package on a per-call basis.  Since the initial parent scope doesn't matter we
2038		// just set it to nil.
2039		scope := newLocalScope(nil, singletonNamespacePrefix(info.name))
2040
2041		sctx := &singletonContext{
2042			context: c,
2043			config:  config,
2044			scope:   scope,
2045			globals: liveGlobals,
2046		}
2047
2048		func() {
2049			defer func() {
2050				if r := recover(); r != nil {
2051					in := fmt.Sprintf("GenerateBuildActions for singleton %s", info.name)
2052					if err, ok := r.(panicError); ok {
2053						err.addIn(in)
2054						sctx.error(err)
2055					} else {
2056						sctx.error(newPanicErrorf(r, in))
2057					}
2058				}
2059			}()
2060			info.singleton.GenerateBuildActions(sctx)
2061		}()
2062
2063		if len(sctx.errs) > 0 {
2064			errs = append(errs, sctx.errs...)
2065			if len(errs) > maxErrors {
2066				break
2067			}
2068			continue
2069		}
2070
2071		deps = append(deps, sctx.ninjaFileDeps...)
2072
2073		newErrs := c.processLocalBuildActions(&info.actionDefs,
2074			&sctx.actionDefs, liveGlobals)
2075		errs = append(errs, newErrs...)
2076		if len(errs) > maxErrors {
2077			break
2078		}
2079	}
2080
2081	return deps, errs
2082}
2083
2084func (c *Context) processLocalBuildActions(out, in *localBuildActions,
2085	liveGlobals *liveTracker) []error {
2086
2087	var errs []error
2088
2089	// First we go through and add everything referenced by the module's
2090	// buildDefs to the live globals set.  This will end up adding the live
2091	// locals to the set as well, but we'll take them out after.
2092	for _, def := range in.buildDefs {
2093		err := liveGlobals.AddBuildDefDeps(def)
2094		if err != nil {
2095			errs = append(errs, err)
2096		}
2097	}
2098
2099	if len(errs) > 0 {
2100		return errs
2101	}
2102
2103	out.buildDefs = append(out.buildDefs, in.buildDefs...)
2104
2105	// We use the now-incorrect set of live "globals" to determine which local
2106	// definitions are live.  As we go through copying those live locals to the
2107	// moduleGroup we remove them from the live globals set.
2108	for _, v := range in.variables {
2109		isLive := liveGlobals.RemoveVariableIfLive(v)
2110		if isLive {
2111			out.variables = append(out.variables, v)
2112		}
2113	}
2114
2115	for _, r := range in.rules {
2116		isLive := liveGlobals.RemoveRuleIfLive(r)
2117		if isLive {
2118			out.rules = append(out.rules, r)
2119		}
2120	}
2121
2122	return nil
2123}
2124
2125func (c *Context) walkDeps(topModule *moduleInfo,
2126	visitDown func(depInfo, *moduleInfo) bool, visitUp func(depInfo, *moduleInfo)) {
2127
2128	visited := make(map[*moduleInfo]bool)
2129	var visiting *moduleInfo
2130
2131	defer func() {
2132		if r := recover(); r != nil {
2133			panic(newPanicErrorf(r, "WalkDeps(%s, %s, %s) for dependency %s",
2134				topModule, funcName(visitDown), funcName(visitUp), visiting))
2135		}
2136	}()
2137
2138	var walk func(module *moduleInfo)
2139	walk = func(module *moduleInfo) {
2140		for _, dep := range module.directDeps {
2141			if !visited[dep.module] {
2142				visited[dep.module] = true
2143				visiting = dep.module
2144				recurse := true
2145				if visitDown != nil {
2146					recurse = visitDown(dep, module)
2147				}
2148				if recurse {
2149					walk(dep.module)
2150				}
2151				if visitUp != nil {
2152					visitUp(dep, module)
2153				}
2154			}
2155		}
2156	}
2157
2158	walk(topModule)
2159}
2160
2161type replace struct {
2162	from, to *moduleInfo
2163}
2164
2165type rename struct {
2166	group *moduleGroup
2167	name  string
2168}
2169
2170func (c *Context) moduleMatchingVariant(module *moduleInfo, name string) *moduleInfo {
2171	targets := c.modulesFromName(name)
2172
2173	if targets == nil {
2174		return nil
2175	}
2176
2177	for _, m := range targets {
2178		if module.variantName == m.variantName {
2179			return m
2180		}
2181	}
2182
2183	return nil
2184}
2185
2186func (c *Context) handleRenames(renames []rename) []error {
2187	var errs []error
2188	for _, rename := range renames {
2189		group, name := rename.group, rename.name
2190		if name == group.name {
2191			continue
2192		}
2193
2194		existing := c.moduleNames[name]
2195		if existing != nil {
2196			errs = append(errs,
2197				&BlueprintError{
2198					Err: fmt.Errorf("renaming module %q to %q conflicts with existing module",
2199						group.name, name),
2200					Pos: group.modules[0].pos,
2201				},
2202				&BlueprintError{
2203					Err: fmt.Errorf("<-- existing module defined here"),
2204					Pos: existing.modules[0].pos,
2205				},
2206			)
2207			continue
2208		}
2209
2210		c.moduleNames[name] = group
2211		delete(c.moduleNames, group.name)
2212		group.name = name
2213	}
2214
2215	return errs
2216}
2217
2218func (c *Context) handleReplacements(replacements []replace) []error {
2219	var errs []error
2220	for _, replace := range replacements {
2221		for _, m := range replace.from.reverseDeps {
2222			for i, d := range m.directDeps {
2223				if d.module == replace.from {
2224					m.directDeps[i].module = replace.to
2225				}
2226			}
2227		}
2228
2229		atomic.AddUint32(&c.depsModified, 1)
2230	}
2231
2232	return errs
2233}
2234
2235func (c *Context) modulesFromName(name string) []*moduleInfo {
2236	if group := c.moduleNames[name]; group != nil {
2237		return group.modules
2238	}
2239	return nil
2240}
2241
2242func (c *Context) sortedModuleNames() []string {
2243	if c.cachedSortedModuleNames == nil {
2244		c.cachedSortedModuleNames = make([]string, 0, len(c.moduleNames))
2245		for moduleName := range c.moduleNames {
2246			c.cachedSortedModuleNames = append(c.cachedSortedModuleNames,
2247				moduleName)
2248		}
2249		sort.Strings(c.cachedSortedModuleNames)
2250	}
2251
2252	return c.cachedSortedModuleNames
2253}
2254
2255func (c *Context) visitAllModules(visit func(Module)) {
2256	var module *moduleInfo
2257
2258	defer func() {
2259		if r := recover(); r != nil {
2260			panic(newPanicErrorf(r, "VisitAllModules(%s) for %s",
2261				funcName(visit), module))
2262		}
2263	}()
2264
2265	for _, moduleName := range c.sortedModuleNames() {
2266		modules := c.modulesFromName(moduleName)
2267		for _, module = range modules {
2268			visit(module.logicModule)
2269		}
2270	}
2271}
2272
2273func (c *Context) visitAllModulesIf(pred func(Module) bool,
2274	visit func(Module)) {
2275
2276	var module *moduleInfo
2277
2278	defer func() {
2279		if r := recover(); r != nil {
2280			panic(newPanicErrorf(r, "VisitAllModulesIf(%s, %s) for %s",
2281				funcName(pred), funcName(visit), module))
2282		}
2283	}()
2284
2285	for _, moduleName := range c.sortedModuleNames() {
2286		modules := c.modulesFromName(moduleName)
2287		for _, module := range modules {
2288			if pred(module.logicModule) {
2289				visit(module.logicModule)
2290			}
2291		}
2292	}
2293}
2294
2295func (c *Context) visitAllModuleVariants(module *moduleInfo,
2296	visit func(Module)) {
2297
2298	var variant *moduleInfo
2299
2300	defer func() {
2301		if r := recover(); r != nil {
2302			panic(newPanicErrorf(r, "VisitAllModuleVariants(%s, %s) for %s",
2303				module, funcName(visit), variant))
2304		}
2305	}()
2306
2307	for _, variant = range module.group.modules {
2308		visit(variant.logicModule)
2309	}
2310}
2311
2312func (c *Context) requireNinjaVersion(major, minor, micro int) {
2313	if major != 1 {
2314		panic("ninja version with major version != 1 not supported")
2315	}
2316	if c.requiredNinjaMinor < minor {
2317		c.requiredNinjaMinor = minor
2318		c.requiredNinjaMicro = micro
2319	}
2320	if c.requiredNinjaMinor == minor && c.requiredNinjaMicro < micro {
2321		c.requiredNinjaMicro = micro
2322	}
2323}
2324
2325func (c *Context) setNinjaBuildDir(value *ninjaString) {
2326	if c.ninjaBuildDir == nil {
2327		c.ninjaBuildDir = value
2328	}
2329}
2330
2331func (c *Context) makeUniquePackageNames(
2332	liveGlobals *liveTracker) (map[*packageContext]string, []string) {
2333
2334	pkgs := make(map[string]*packageContext)
2335	pkgNames := make(map[*packageContext]string)
2336	longPkgNames := make(map[*packageContext]bool)
2337
2338	processPackage := func(pctx *packageContext) {
2339		if pctx == nil {
2340			// This is a built-in rule and has no package.
2341			return
2342		}
2343		if _, ok := pkgNames[pctx]; ok {
2344			// We've already processed this package.
2345			return
2346		}
2347
2348		otherPkg, present := pkgs[pctx.shortName]
2349		if present {
2350			// Short name collision.  Both this package and the one that's
2351			// already there need to use their full names.  We leave the short
2352			// name in pkgNames for now so future collisions still get caught.
2353			longPkgNames[pctx] = true
2354			longPkgNames[otherPkg] = true
2355		} else {
2356			// No collision so far.  Tentatively set the package's name to be
2357			// its short name.
2358			pkgNames[pctx] = pctx.shortName
2359			pkgs[pctx.shortName] = pctx
2360		}
2361	}
2362
2363	// We try to give all packages their short name, but when we get collisions
2364	// we need to use the full unique package name.
2365	for v, _ := range liveGlobals.variables {
2366		processPackage(v.packageContext())
2367	}
2368	for p, _ := range liveGlobals.pools {
2369		processPackage(p.packageContext())
2370	}
2371	for r, _ := range liveGlobals.rules {
2372		processPackage(r.packageContext())
2373	}
2374
2375	// Add the packages that had collisions using their full unique names.  This
2376	// will overwrite any short names that were added in the previous step.
2377	for pctx := range longPkgNames {
2378		pkgNames[pctx] = pctx.fullName
2379	}
2380
2381	// Create deps list from calls to PackageContext.AddNinjaFileDeps
2382	deps := []string{}
2383	for _, pkg := range pkgs {
2384		deps = append(deps, pkg.ninjaFileDeps...)
2385	}
2386
2387	return pkgNames, deps
2388}
2389
2390func (c *Context) checkForVariableReferenceCycles(
2391	variables map[Variable]*ninjaString, pkgNames map[*packageContext]string) {
2392
2393	visited := make(map[Variable]bool)  // variables that were already checked
2394	checking := make(map[Variable]bool) // variables actively being checked
2395
2396	var check func(v Variable) []Variable
2397
2398	check = func(v Variable) []Variable {
2399		visited[v] = true
2400		checking[v] = true
2401		defer delete(checking, v)
2402
2403		value := variables[v]
2404		for _, dep := range value.variables {
2405			if checking[dep] {
2406				// This is a cycle.
2407				return []Variable{dep, v}
2408			}
2409
2410			if !visited[dep] {
2411				cycle := check(dep)
2412				if cycle != nil {
2413					if cycle[0] == v {
2414						// We are the "start" of the cycle, so we're responsible
2415						// for generating the errors.  The cycle list is in
2416						// reverse order because all the 'check' calls append
2417						// their own module to the list.
2418						msgs := []string{"detected variable reference cycle:"}
2419
2420						// Iterate backwards through the cycle list.
2421						curName := v.fullName(pkgNames)
2422						curValue := value.Value(pkgNames)
2423						for i := len(cycle) - 1; i >= 0; i-- {
2424							next := cycle[i]
2425							nextName := next.fullName(pkgNames)
2426							nextValue := variables[next].Value(pkgNames)
2427
2428							msgs = append(msgs, fmt.Sprintf(
2429								"    %q depends on %q", curName, nextName))
2430							msgs = append(msgs, fmt.Sprintf(
2431								"    [%s = %s]", curName, curValue))
2432
2433							curName = nextName
2434							curValue = nextValue
2435						}
2436
2437						// Variable reference cycles are a programming error,
2438						// not the fault of the Blueprint file authors.
2439						panic(strings.Join(msgs, "\n"))
2440					} else {
2441						// We're not the "start" of the cycle, so we just append
2442						// our module to the list and return it.
2443						return append(cycle, v)
2444					}
2445				}
2446			}
2447		}
2448
2449		return nil
2450	}
2451
2452	for v := range variables {
2453		if !visited[v] {
2454			cycle := check(v)
2455			if cycle != nil {
2456				panic("inconceivable!")
2457			}
2458		}
2459	}
2460}
2461
2462// AllTargets returns a map all the build target names to the rule used to build
2463// them.  This is the same information that is output by running 'ninja -t
2464// targets all'.  If this is called before PrepareBuildActions successfully
2465// completes then ErrbuildActionsNotReady is returned.
2466func (c *Context) AllTargets() (map[string]string, error) {
2467	if !c.buildActionsReady {
2468		return nil, ErrBuildActionsNotReady
2469	}
2470
2471	targets := map[string]string{}
2472
2473	// Collect all the module build targets.
2474	for _, module := range c.moduleInfo {
2475		for _, buildDef := range module.actionDefs.buildDefs {
2476			ruleName := buildDef.Rule.fullName(c.pkgNames)
2477			for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
2478				outputValue, err := output.Eval(c.globalVariables)
2479				if err != nil {
2480					return nil, err
2481				}
2482				targets[outputValue] = ruleName
2483			}
2484		}
2485	}
2486
2487	// Collect all the singleton build targets.
2488	for _, info := range c.singletonInfo {
2489		for _, buildDef := range info.actionDefs.buildDefs {
2490			ruleName := buildDef.Rule.fullName(c.pkgNames)
2491			for _, output := range append(buildDef.Outputs, buildDef.ImplicitOutputs...) {
2492				outputValue, err := output.Eval(c.globalVariables)
2493				if err != nil {
2494					return nil, err
2495				}
2496				targets[outputValue] = ruleName
2497			}
2498		}
2499	}
2500
2501	return targets, nil
2502}
2503
2504func (c *Context) NinjaBuildDir() (string, error) {
2505	if c.ninjaBuildDir != nil {
2506		return c.ninjaBuildDir.Eval(c.globalVariables)
2507	} else {
2508		return "", nil
2509	}
2510}
2511
2512// ModuleTypePropertyStructs returns a mapping from module type name to a list of pointers to
2513// property structs returned by the factory for that module type.
2514func (c *Context) ModuleTypePropertyStructs() map[string][]interface{} {
2515	ret := make(map[string][]interface{})
2516	for moduleType, factory := range c.moduleFactories {
2517		_, ret[moduleType] = factory()
2518	}
2519
2520	return ret
2521}
2522
2523func (c *Context) ModuleName(logicModule Module) string {
2524	module := c.moduleInfo[logicModule]
2525	return module.Name()
2526}
2527
2528func (c *Context) ModuleDir(logicModule Module) string {
2529	module := c.moduleInfo[logicModule]
2530	return filepath.Dir(module.relBlueprintsFile)
2531}
2532
2533func (c *Context) ModuleSubDir(logicModule Module) string {
2534	module := c.moduleInfo[logicModule]
2535	return module.variantName
2536}
2537
2538func (c *Context) ModuleType(logicModule Module) string {
2539	module := c.moduleInfo[logicModule]
2540	return module.typeName
2541}
2542
2543func (c *Context) BlueprintFile(logicModule Module) string {
2544	module := c.moduleInfo[logicModule]
2545	return module.relBlueprintsFile
2546}
2547
2548func (c *Context) ModuleErrorf(logicModule Module, format string,
2549	args ...interface{}) error {
2550
2551	module := c.moduleInfo[logicModule]
2552	return &BlueprintError{
2553		Err: fmt.Errorf(format, args...),
2554		Pos: module.pos,
2555	}
2556}
2557
2558func (c *Context) VisitAllModules(visit func(Module)) {
2559	c.visitAllModules(visit)
2560}
2561
2562func (c *Context) VisitAllModulesIf(pred func(Module) bool,
2563	visit func(Module)) {
2564
2565	c.visitAllModulesIf(pred, visit)
2566}
2567
2568func (c *Context) VisitDirectDeps(module Module, visit func(Module)) {
2569	topModule := c.moduleInfo[module]
2570
2571	var visiting *moduleInfo
2572
2573	defer func() {
2574		if r := recover(); r != nil {
2575			panic(newPanicErrorf(r, "VisitDirectDeps(%s, %s) for dependency %s",
2576				topModule, funcName(visit), visiting))
2577		}
2578	}()
2579
2580	for _, dep := range topModule.directDeps {
2581		visiting = dep.module
2582		visit(dep.module.logicModule)
2583	}
2584}
2585
2586func (c *Context) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module)) {
2587	topModule := c.moduleInfo[module]
2588
2589	var visiting *moduleInfo
2590
2591	defer func() {
2592		if r := recover(); r != nil {
2593			panic(newPanicErrorf(r, "VisitDirectDepsIf(%s, %s, %s) for dependency %s",
2594				topModule, funcName(pred), funcName(visit), visiting))
2595		}
2596	}()
2597
2598	for _, dep := range topModule.directDeps {
2599		visiting = dep.module
2600		if pred(dep.module.logicModule) {
2601			visit(dep.module.logicModule)
2602		}
2603	}
2604}
2605
2606func (c *Context) VisitDepsDepthFirst(module Module, visit func(Module)) {
2607	topModule := c.moduleInfo[module]
2608
2609	var visiting *moduleInfo
2610
2611	defer func() {
2612		if r := recover(); r != nil {
2613			panic(newPanicErrorf(r, "VisitDepsDepthFirst(%s, %s) for dependency %s",
2614				topModule, funcName(visit), visiting))
2615		}
2616	}()
2617
2618	c.walkDeps(topModule, nil, func(dep depInfo, parent *moduleInfo) {
2619		visiting = dep.module
2620		visit(dep.module.logicModule)
2621	})
2622}
2623
2624func (c *Context) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module)) {
2625	topModule := c.moduleInfo[module]
2626
2627	var visiting *moduleInfo
2628
2629	defer func() {
2630		if r := recover(); r != nil {
2631			panic(newPanicErrorf(r, "VisitDepsDepthFirstIf(%s, %s, %s) for dependency %s",
2632				topModule, funcName(pred), funcName(visit), visiting))
2633		}
2634	}()
2635
2636	c.walkDeps(topModule, nil, func(dep depInfo, parent *moduleInfo) {
2637		if pred(dep.module.logicModule) {
2638			visiting = dep.module
2639			visit(dep.module.logicModule)
2640		}
2641	})
2642}
2643
2644func (c *Context) PrimaryModule(module Module) Module {
2645	return c.moduleInfo[module].group.modules[0].logicModule
2646}
2647
2648func (c *Context) FinalModule(module Module) Module {
2649	modules := c.moduleInfo[module].group.modules
2650	return modules[len(modules)-1].logicModule
2651}
2652
2653func (c *Context) VisitAllModuleVariants(module Module,
2654	visit func(Module)) {
2655
2656	c.visitAllModuleVariants(c.moduleInfo[module], visit)
2657}
2658
2659// WriteBuildFile writes the Ninja manifeset text for the generated build
2660// actions to w.  If this is called before PrepareBuildActions successfully
2661// completes then ErrBuildActionsNotReady is returned.
2662func (c *Context) WriteBuildFile(w io.Writer) error {
2663	if !c.buildActionsReady {
2664		return ErrBuildActionsNotReady
2665	}
2666
2667	nw := newNinjaWriter(w)
2668
2669	err := c.writeBuildFileHeader(nw)
2670	if err != nil {
2671		return err
2672	}
2673
2674	err = c.writeNinjaRequiredVersion(nw)
2675	if err != nil {
2676		return err
2677	}
2678
2679	// TODO: Group the globals by package.
2680
2681	err = c.writeGlobalVariables(nw)
2682	if err != nil {
2683		return err
2684	}
2685
2686	err = c.writeGlobalPools(nw)
2687	if err != nil {
2688		return err
2689	}
2690
2691	err = c.writeBuildDir(nw)
2692	if err != nil {
2693		return err
2694	}
2695
2696	err = c.writeGlobalRules(nw)
2697	if err != nil {
2698		return err
2699	}
2700
2701	err = c.writeAllModuleActions(nw)
2702	if err != nil {
2703		return err
2704	}
2705
2706	err = c.writeAllSingletonActions(nw)
2707	if err != nil {
2708		return err
2709	}
2710
2711	return nil
2712}
2713
2714type pkgAssociation struct {
2715	PkgName string
2716	PkgPath string
2717}
2718
2719type pkgAssociationSorter struct {
2720	pkgs []pkgAssociation
2721}
2722
2723func (s *pkgAssociationSorter) Len() int {
2724	return len(s.pkgs)
2725}
2726
2727func (s *pkgAssociationSorter) Less(i, j int) bool {
2728	iName := s.pkgs[i].PkgName
2729	jName := s.pkgs[j].PkgName
2730	return iName < jName
2731}
2732
2733func (s *pkgAssociationSorter) Swap(i, j int) {
2734	s.pkgs[i], s.pkgs[j] = s.pkgs[j], s.pkgs[i]
2735}
2736
2737func (c *Context) writeBuildFileHeader(nw *ninjaWriter) error {
2738	headerTemplate := template.New("fileHeader")
2739	_, err := headerTemplate.Parse(fileHeaderTemplate)
2740	if err != nil {
2741		// This is a programming error.
2742		panic(err)
2743	}
2744
2745	var pkgs []pkgAssociation
2746	maxNameLen := 0
2747	for pkg, name := range c.pkgNames {
2748		pkgs = append(pkgs, pkgAssociation{
2749			PkgName: name,
2750			PkgPath: pkg.pkgPath,
2751		})
2752		if len(name) > maxNameLen {
2753			maxNameLen = len(name)
2754		}
2755	}
2756
2757	for i := range pkgs {
2758		pkgs[i].PkgName += strings.Repeat(" ", maxNameLen-len(pkgs[i].PkgName))
2759	}
2760
2761	sort.Sort(&pkgAssociationSorter{pkgs})
2762
2763	params := map[string]interface{}{
2764		"Pkgs": pkgs,
2765	}
2766
2767	buf := bytes.NewBuffer(nil)
2768	err = headerTemplate.Execute(buf, params)
2769	if err != nil {
2770		return err
2771	}
2772
2773	return nw.Comment(buf.String())
2774}
2775
2776func (c *Context) writeNinjaRequiredVersion(nw *ninjaWriter) error {
2777	value := fmt.Sprintf("%d.%d.%d", c.requiredNinjaMajor, c.requiredNinjaMinor,
2778		c.requiredNinjaMicro)
2779
2780	err := nw.Assign("ninja_required_version", value)
2781	if err != nil {
2782		return err
2783	}
2784
2785	return nw.BlankLine()
2786}
2787
2788func (c *Context) writeBuildDir(nw *ninjaWriter) error {
2789	if c.ninjaBuildDir != nil {
2790		err := nw.Assign("builddir", c.ninjaBuildDir.Value(c.pkgNames))
2791		if err != nil {
2792			return err
2793		}
2794
2795		err = nw.BlankLine()
2796		if err != nil {
2797			return err
2798		}
2799	}
2800	return nil
2801}
2802
2803type globalEntity interface {
2804	fullName(pkgNames map[*packageContext]string) string
2805}
2806
2807type globalEntitySorter struct {
2808	pkgNames map[*packageContext]string
2809	entities []globalEntity
2810}
2811
2812func (s *globalEntitySorter) Len() int {
2813	return len(s.entities)
2814}
2815
2816func (s *globalEntitySorter) Less(i, j int) bool {
2817	iName := s.entities[i].fullName(s.pkgNames)
2818	jName := s.entities[j].fullName(s.pkgNames)
2819	return iName < jName
2820}
2821
2822func (s *globalEntitySorter) Swap(i, j int) {
2823	s.entities[i], s.entities[j] = s.entities[j], s.entities[i]
2824}
2825
2826func (c *Context) writeGlobalVariables(nw *ninjaWriter) error {
2827	visited := make(map[Variable]bool)
2828
2829	var walk func(v Variable) error
2830	walk = func(v Variable) error {
2831		visited[v] = true
2832
2833		// First visit variables on which this variable depends.
2834		value := c.globalVariables[v]
2835		for _, dep := range value.variables {
2836			if !visited[dep] {
2837				err := walk(dep)
2838				if err != nil {
2839					return err
2840				}
2841			}
2842		}
2843
2844		err := nw.Assign(v.fullName(c.pkgNames), value.Value(c.pkgNames))
2845		if err != nil {
2846			return err
2847		}
2848
2849		err = nw.BlankLine()
2850		if err != nil {
2851			return err
2852		}
2853
2854		return nil
2855	}
2856
2857	globalVariables := make([]globalEntity, 0, len(c.globalVariables))
2858	for variable := range c.globalVariables {
2859		globalVariables = append(globalVariables, variable)
2860	}
2861
2862	sort.Sort(&globalEntitySorter{c.pkgNames, globalVariables})
2863
2864	for _, entity := range globalVariables {
2865		v := entity.(Variable)
2866		if !visited[v] {
2867			err := walk(v)
2868			if err != nil {
2869				return nil
2870			}
2871		}
2872	}
2873
2874	return nil
2875}
2876
2877func (c *Context) writeGlobalPools(nw *ninjaWriter) error {
2878	globalPools := make([]globalEntity, 0, len(c.globalPools))
2879	for pool := range c.globalPools {
2880		globalPools = append(globalPools, pool)
2881	}
2882
2883	sort.Sort(&globalEntitySorter{c.pkgNames, globalPools})
2884
2885	for _, entity := range globalPools {
2886		pool := entity.(Pool)
2887		name := pool.fullName(c.pkgNames)
2888		def := c.globalPools[pool]
2889		err := def.WriteTo(nw, name)
2890		if err != nil {
2891			return err
2892		}
2893
2894		err = nw.BlankLine()
2895		if err != nil {
2896			return err
2897		}
2898	}
2899
2900	return nil
2901}
2902
2903func (c *Context) writeGlobalRules(nw *ninjaWriter) error {
2904	globalRules := make([]globalEntity, 0, len(c.globalRules))
2905	for rule := range c.globalRules {
2906		globalRules = append(globalRules, rule)
2907	}
2908
2909	sort.Sort(&globalEntitySorter{c.pkgNames, globalRules})
2910
2911	for _, entity := range globalRules {
2912		rule := entity.(Rule)
2913		name := rule.fullName(c.pkgNames)
2914		def := c.globalRules[rule]
2915		err := def.WriteTo(nw, name, c.pkgNames)
2916		if err != nil {
2917			return err
2918		}
2919
2920		err = nw.BlankLine()
2921		if err != nil {
2922			return err
2923		}
2924	}
2925
2926	return nil
2927}
2928
2929type depSorter []depInfo
2930
2931func (s depSorter) Len() int {
2932	return len(s)
2933}
2934
2935func (s depSorter) Less(i, j int) bool {
2936	iName := s[i].module.Name()
2937	jName := s[j].module.Name()
2938	if iName == jName {
2939		iName = s[i].module.variantName
2940		jName = s[j].module.variantName
2941	}
2942	return iName < jName
2943}
2944
2945func (s depSorter) Swap(i, j int) {
2946	s[i], s[j] = s[j], s[i]
2947}
2948
2949type moduleSorter []*moduleInfo
2950
2951func (s moduleSorter) Len() int {
2952	return len(s)
2953}
2954
2955func (s moduleSorter) Less(i, j int) bool {
2956	iName := s[i].Name()
2957	jName := s[j].Name()
2958	if iName == jName {
2959		iName = s[i].variantName
2960		jName = s[j].variantName
2961	}
2962	return iName < jName
2963}
2964
2965func (s moduleSorter) Swap(i, j int) {
2966	s[i], s[j] = s[j], s[i]
2967}
2968
2969func (c *Context) writeAllModuleActions(nw *ninjaWriter) error {
2970	headerTemplate := template.New("moduleHeader")
2971	_, err := headerTemplate.Parse(moduleHeaderTemplate)
2972	if err != nil {
2973		// This is a programming error.
2974		panic(err)
2975	}
2976
2977	modules := make([]*moduleInfo, 0, len(c.moduleInfo))
2978	for _, module := range c.moduleInfo {
2979		modules = append(modules, module)
2980	}
2981	sort.Sort(moduleSorter(modules))
2982
2983	buf := bytes.NewBuffer(nil)
2984
2985	for _, module := range modules {
2986		if len(module.actionDefs.variables)+len(module.actionDefs.rules)+len(module.actionDefs.buildDefs) == 0 {
2987			continue
2988		}
2989
2990		buf.Reset()
2991
2992		// In order to make the bootstrap build manifest independent of the
2993		// build dir we need to output the Blueprints file locations in the
2994		// comments as paths relative to the source directory.
2995		relPos := module.pos
2996		relPos.Filename = module.relBlueprintsFile
2997
2998		// Get the name and location of the factory function for the module.
2999		factory := c.moduleFactories[module.typeName]
3000		factoryFunc := runtime.FuncForPC(reflect.ValueOf(factory).Pointer())
3001		factoryName := factoryFunc.Name()
3002
3003		infoMap := map[string]interface{}{
3004			"name":      module.Name(),
3005			"typeName":  module.typeName,
3006			"goFactory": factoryName,
3007			"pos":       relPos,
3008			"variant":   module.variantName,
3009		}
3010		err = headerTemplate.Execute(buf, infoMap)
3011		if err != nil {
3012			return err
3013		}
3014
3015		err = nw.Comment(buf.String())
3016		if err != nil {
3017			return err
3018		}
3019
3020		err = nw.BlankLine()
3021		if err != nil {
3022			return err
3023		}
3024
3025		err = c.writeLocalBuildActions(nw, &module.actionDefs)
3026		if err != nil {
3027			return err
3028		}
3029
3030		err = nw.BlankLine()
3031		if err != nil {
3032			return err
3033		}
3034	}
3035
3036	return nil
3037}
3038
3039func (c *Context) writeAllSingletonActions(nw *ninjaWriter) error {
3040	headerTemplate := template.New("singletonHeader")
3041	_, err := headerTemplate.Parse(singletonHeaderTemplate)
3042	if err != nil {
3043		// This is a programming error.
3044		panic(err)
3045	}
3046
3047	buf := bytes.NewBuffer(nil)
3048
3049	for _, info := range c.singletonInfo {
3050		if len(info.actionDefs.variables)+len(info.actionDefs.rules)+len(info.actionDefs.buildDefs) == 0 {
3051			continue
3052		}
3053
3054		// Get the name of the factory function for the module.
3055		factory := info.factory
3056		factoryFunc := runtime.FuncForPC(reflect.ValueOf(factory).Pointer())
3057		factoryName := factoryFunc.Name()
3058
3059		buf.Reset()
3060		infoMap := map[string]interface{}{
3061			"name":      info.name,
3062			"goFactory": factoryName,
3063		}
3064		err = headerTemplate.Execute(buf, infoMap)
3065		if err != nil {
3066			return err
3067		}
3068
3069		err = nw.Comment(buf.String())
3070		if err != nil {
3071			return err
3072		}
3073
3074		err = nw.BlankLine()
3075		if err != nil {
3076			return err
3077		}
3078
3079		err = c.writeLocalBuildActions(nw, &info.actionDefs)
3080		if err != nil {
3081			return err
3082		}
3083
3084		err = nw.BlankLine()
3085		if err != nil {
3086			return err
3087		}
3088	}
3089
3090	return nil
3091}
3092
3093func (c *Context) writeLocalBuildActions(nw *ninjaWriter,
3094	defs *localBuildActions) error {
3095
3096	// Write the local variable assignments.
3097	for _, v := range defs.variables {
3098		// A localVariable doesn't need the package names or config to
3099		// determine its name or value.
3100		name := v.fullName(nil)
3101		value, err := v.value(nil)
3102		if err != nil {
3103			panic(err)
3104		}
3105		err = nw.Assign(name, value.Value(c.pkgNames))
3106		if err != nil {
3107			return err
3108		}
3109	}
3110
3111	if len(defs.variables) > 0 {
3112		err := nw.BlankLine()
3113		if err != nil {
3114			return err
3115		}
3116	}
3117
3118	// Write the local rules.
3119	for _, r := range defs.rules {
3120		// A localRule doesn't need the package names or config to determine
3121		// its name or definition.
3122		name := r.fullName(nil)
3123		def, err := r.def(nil)
3124		if err != nil {
3125			panic(err)
3126		}
3127
3128		err = def.WriteTo(nw, name, c.pkgNames)
3129		if err != nil {
3130			return err
3131		}
3132
3133		err = nw.BlankLine()
3134		if err != nil {
3135			return err
3136		}
3137	}
3138
3139	// Write the build definitions.
3140	for _, buildDef := range defs.buildDefs {
3141		err := buildDef.WriteTo(nw, c.pkgNames)
3142		if err != nil {
3143			return err
3144		}
3145
3146		if len(buildDef.Args) > 0 {
3147			err = nw.BlankLine()
3148			if err != nil {
3149				return err
3150			}
3151		}
3152	}
3153
3154	return nil
3155}
3156
3157func beforeInModuleList(a, b *moduleInfo, list []*moduleInfo) bool {
3158	found := false
3159	if a == b {
3160		return false
3161	}
3162	for _, l := range list {
3163		if l == a {
3164			found = true
3165		} else if l == b {
3166			return found
3167		}
3168	}
3169
3170	missing := a
3171	if found {
3172		missing = b
3173	}
3174	panic(fmt.Errorf("element %v not found in list %v", missing, list))
3175}
3176
3177type panicError struct {
3178	panic interface{}
3179	stack []byte
3180	in    string
3181}
3182
3183func newPanicErrorf(panic interface{}, in string, a ...interface{}) error {
3184	buf := make([]byte, 4096)
3185	count := runtime.Stack(buf, false)
3186	return panicError{
3187		panic: panic,
3188		in:    fmt.Sprintf(in, a...),
3189		stack: buf[:count],
3190	}
3191}
3192
3193func (p panicError) Error() string {
3194	return fmt.Sprintf("panic in %s\n%s\n%s\n", p.in, p.panic, p.stack)
3195}
3196
3197func (p *panicError) addIn(in string) {
3198	p.in += " in " + in
3199}
3200
3201func funcName(f interface{}) string {
3202	return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
3203}
3204
3205var fileHeaderTemplate = `******************************************************************************
3206***            This file is generated and should not be edited             ***
3207******************************************************************************
3208{{if .Pkgs}}
3209This file contains variables, rules, and pools with name prefixes indicating
3210they were generated by the following Go packages:
3211{{range .Pkgs}}
3212    {{.PkgName}} [from Go package {{.PkgPath}}]{{end}}{{end}}
3213
3214`
3215
3216var moduleHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
3217Module:  {{.name}}
3218Variant: {{.variant}}
3219Type:    {{.typeName}}
3220Factory: {{.goFactory}}
3221Defined: {{.pos}}
3222`
3223
3224var singletonHeaderTemplate = `# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
3225Singleton: {{.name}}
3226Factory:   {{.goFactory}}
3227`
3228