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