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