Don't rebuild nodes whose prereqs have been deleted.
This commit is contained in:
parent
1eb840af57
commit
dc4276690a
1 changed files with 51 additions and 30 deletions
81
mk.go
81
mk.go
|
|
@ -87,12 +87,51 @@ const (
|
||||||
ansiTermUnderline = "\033[4m"
|
ansiTermUnderline = "\033[4m"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Build a node's prereqs. Block until completed.
|
||||||
|
//
|
||||||
|
func mkNodePrereqs(g *graph, u *node, e *edge, prereqs []*node, dryrun bool,
|
||||||
|
required bool) nodeStatus {
|
||||||
|
prereqstat := make(chan nodeStatus)
|
||||||
|
pending := 0
|
||||||
|
|
||||||
|
// build prereqs that need building
|
||||||
|
for i := range prereqs {
|
||||||
|
prereqs[i].mutex.Lock()
|
||||||
|
switch prereqs[i].status {
|
||||||
|
case nodeStatusReady:
|
||||||
|
go mkNode(g, prereqs[i], dryrun, required)
|
||||||
|
fallthrough
|
||||||
|
case nodeStatusStarted:
|
||||||
|
prereqs[i].listeners = append(prereqs[i].listeners, prereqstat)
|
||||||
|
pending++
|
||||||
|
}
|
||||||
|
prereqs[i].mutex.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait until all the prereqs are built
|
||||||
|
status := nodeStatusDone
|
||||||
|
for pending > 0 {
|
||||||
|
s := <-prereqstat
|
||||||
|
pending--
|
||||||
|
if s == nodeStatusFailed {
|
||||||
|
status = nodeStatusFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
|
||||||
// Build a target in the graph.
|
// Build a target in the graph.
|
||||||
//
|
//
|
||||||
// This selects an appropriate rule (edge) and builds all prerequisites
|
// This selects an appropriate rule (edge) and builds all prerequisites
|
||||||
// concurrently.
|
// concurrently.
|
||||||
//
|
//
|
||||||
func mkNode(g *graph, u *node, dryrun bool) {
|
// Args:
|
||||||
|
// g: Graph in which the node lives.
|
||||||
|
// u: Node to (possibly) build.
|
||||||
|
// dryrun: Don't actually build anything, just pretend.
|
||||||
|
// required: Avoid building this node, unless its prereqs are out of date.
|
||||||
|
//
|
||||||
|
func mkNode(g *graph, u *node, dryrun bool, required bool) {
|
||||||
// try to claim on this node
|
// try to claim on this node
|
||||||
u.mutex.Lock()
|
u.mutex.Lock()
|
||||||
if u.status != nodeStatusReady {
|
if u.status != nodeStatusReady {
|
||||||
|
|
@ -142,43 +181,20 @@ func mkNode(g *graph, u *node, dryrun bool) {
|
||||||
mkError(fmt.Sprintf("don't know how to make %s in %s", u.name, wd))
|
mkError(fmt.Sprintf("don't know how to make %s in %s", u.name, wd))
|
||||||
}
|
}
|
||||||
|
|
||||||
prereqstat := make(chan nodeStatus)
|
|
||||||
pending := 0
|
|
||||||
|
|
||||||
// build prereqs that need building
|
|
||||||
e.r.mutex.Lock()
|
e.r.mutex.Lock()
|
||||||
for i := range prereqs {
|
prereqs_required := required && (e.r.attributes.virtual || !u.exists)
|
||||||
prereqs[i].mutex.Lock()
|
mkNodePrereqs(g, u, e, prereqs, dryrun, prereqs_required)
|
||||||
switch prereqs[i].status {
|
|
||||||
case nodeStatusReady:
|
|
||||||
go mkNode(g, prereqs[i], dryrun)
|
|
||||||
fallthrough
|
|
||||||
case nodeStatusStarted:
|
|
||||||
prereqs[i].listeners = append(prereqs[i].listeners, prereqstat)
|
|
||||||
pending++
|
|
||||||
}
|
|
||||||
prereqs[i].mutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait until all the prereqs are built
|
|
||||||
for pending > 0 {
|
|
||||||
s := <-prereqstat
|
|
||||||
pending--
|
|
||||||
if s == nodeStatusFailed {
|
|
||||||
finalstatus = nodeStatusFailed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uptodate := true
|
uptodate := true
|
||||||
if !e.r.attributes.virtual {
|
if !e.r.attributes.virtual {
|
||||||
u.updateTimestamp()
|
u.updateTimestamp()
|
||||||
if u.exists {
|
if u.exists || required {
|
||||||
for i := range prereqs {
|
for i := range prereqs {
|
||||||
if u.t.Before(prereqs[i].t) || prereqs[i].status == nodeStatusDone {
|
if u.t.Before(prereqs[i].t) || prereqs[i].status == nodeStatusDone {
|
||||||
uptodate = false
|
uptodate = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if required {
|
||||||
uptodate = false
|
uptodate = false
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -189,6 +205,11 @@ func mkNode(g *graph, u *node, dryrun bool) {
|
||||||
uptodate = false
|
uptodate = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make another pass on the prereqs, since we know we need them now
|
||||||
|
if !uptodate {
|
||||||
|
mkNodePrereqs(g, u, e, prereqs, dryrun, true)
|
||||||
|
}
|
||||||
|
|
||||||
// execute the recipe, unless the prereqs failed
|
// execute the recipe, unless the prereqs failed
|
||||||
if !uptodate && finalstatus != nodeStatusFailed && len(e.r.recipe) > 0 {
|
if !uptodate && finalstatus != nodeStatusFailed && len(e.r.recipe) > 0 {
|
||||||
if e.r.attributes.exclusive {
|
if e.r.attributes.exclusive {
|
||||||
|
|
@ -313,7 +334,7 @@ func main() {
|
||||||
|
|
||||||
if interactive {
|
if interactive {
|
||||||
g := buildgraph(rs, "")
|
g := buildgraph(rs, "")
|
||||||
mkNode(g, g.root, true)
|
mkNode(g, g.root, true, true)
|
||||||
fmt.Print("Proceed? ")
|
fmt.Print("Proceed? ")
|
||||||
in := bufio.NewReader(os.Stdin)
|
in := bufio.NewReader(os.Stdin)
|
||||||
for {
|
for {
|
||||||
|
|
@ -331,5 +352,5 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
g := buildgraph(rs, "")
|
g := buildgraph(rs, "")
|
||||||
mkNode(g, g.root, dryrun)
|
mkNode(g, g.root, dryrun, true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue