// Build user's requested targets according to the dependency graph in // self.dag (as constructed by runMainPhase()). func (self *Runtime) runBuildPhase() []error { var errs []error errs = self.dag.ExpandNodes(self.stack) if len(errs) > 0 { return errs } self.dag.MarkSources() log.Debug(log.DAG, "dependency graph:") log.DebugDump(log.DAG, self.dag) goal, errs := self.dag.MatchTargets(self.options.Targets) if len(errs) > 0 { return errs } bdb, err := openBuildDB() if err != nil { errs = append(errs, err) return errs } defer bdb.Close() bstate := build.NewBuildState(self.dag, bdb, self.options) err = bstate.BuildTargets(goal) if err != nil { errs = append(errs, err) } return errs }
func main() { if filepath.Base(os.Args[0]) == "fubsydebug" { debugmain() return } args := parseArgs() script, err := findScript(args.scriptFile) if err != nil { fmt.Fprintln(os.Stderr, "fubsy: error: "+err.Error()) os.Exit(2) } log.SetVerbosity(args.verbosity) err = log.EnableDebugTopics(args.debugTopics) if err != nil { fmt.Fprintln(os.Stderr, "fubsy: error: "+err.Error()) os.Exit(2) } ast, errors := dsl.Parse(script) if ast == nil && len(errors) == 0 { panic("ast == nil && len(errors) == 0") } checkErrors("parse error:", errors) log.Debug(log.AST, "ast:\n") log.DebugDump(log.AST, ast) rt := runtime.NewRuntime(args.options, script, ast) errors = rt.RunScript() checkErrors("error:", errors) }
func (self *BuildRule) Execute() ([]dag.Node, []error) { stack := self.runtime.stack locals := types.NewValueMap() stack.Push(locals) defer stack.Pop() self.setLocals(locals) log.Debug(log.BUILD, "value stack:") log.DebugDump(log.BUILD, stack) err := self.action.Execute(self.runtime) return self.targets.Nodes(), err }
// Inspect node and its parents to see if we need to build it. Return // build=true if we should build it, tainted=true if we should skip // building this node due to upstream failure. Return non-nil err if // there were unexpected node errors (error checking existence or // change status). func (self *BuildState) considerNode(node dag.Node) ( build bool, tainted bool, err error) { var exists, changed bool exists, err = node.Exists() // obvious rebuild (unless tainted) if err != nil { return } missing := !exists var record *db.BuildRecord if !missing { // skip DB lookup for missing nodes: the only thing that will // stop us from rebuilding them is a failed parent, and that // check comes later record, err = self.db.LookupNode(node.Name()) if err != nil { return } if record != nil { log.Debug(log.BUILD, "old parents of %s:", node) log.DebugDump(log.BUILD, record) } } build = missing parents := self.graph.ParentNodes(node) // Check if any of node's former parents have been removed. if !build && record != nil { build = parentsRemoved(parents, record) } for _, parent := range parents { pstate := parent.State() if pstate == dag.FAILED || pstate == dag.TAINTED { build = false tainted = true return // no further inspection required } var oldsig []byte if record != nil { oldsig = record.SourceSignature(parent.Name()) } if oldsig == nil { // New parent for this node: rebuild unless another // parent is failed/tainted. build = true } if build { continue } changed, err = self.parentChanged(parent, pstate, oldsig) if err != nil { return } if changed { // Do NOT return here: we need to continue inspecting // parents to make sure they don't taint this node with // upstream failure. build = true } } return }