aboutsummaryrefslogtreecommitdiff
path: root/exec.go
diff options
context:
space:
mode:
authorShinichiro Hamaji <shinichiro.hamaji@gmail.com>2015-04-16 17:33:44 +0900
committerShinichiro Hamaji <shinichiro.hamaji@gmail.com>2015-04-16 18:12:47 +0900
commit11b918323c587598718c6e51df8366eb9f514363 (patch)
tree71aa0d325e683026b6bccce862c41f8396168853 /exec.go
parent9f6b6359921314d73a83993a49c5b465daede26b (diff)
downloadkati-11b918323c587598718c6e51df8366eb9f514363.tar.gz
Split exec.go into exec.go and eval_command.go
Diffstat (limited to 'exec.go')
-rw-r--r--exec.go188
1 files changed, 36 insertions, 152 deletions
diff --git a/exec.go b/exec.go
index 6048224..7bc8610 100644
--- a/exec.go
+++ b/exec.go
@@ -1,13 +1,9 @@
package main
import (
- "bytes"
"fmt"
- "io"
"os"
"os/exec"
- "path/filepath"
- "strings"
"syscall"
"time"
)
@@ -24,22 +20,15 @@ type Executor struct {
// currently being processed.
done map[string]int64
- currentOutput string
- currentInputs []string
- currentStem string
-
- trace []string
- buildCnt int
- alreadyDoneCnt int
- noRuleCnt int
- upToDateCnt int
- runCommandCnt int
- pickExplicitRuleCnt int
- pickImplicitRuleCnt int
- pickSuffixRuleCnt int
- pickExplicitRuleWithoutCmdCnt int
+ trace []string
+ buildCnt int
+ alreadyDoneCnt int
+ noRuleCnt int
+ upToDateCnt int
+ runCommandCnt int
}
+/*
type AutoVar struct{ ex *Executor }
func (v AutoVar) Flavor() string { return "undefined" }
@@ -149,6 +138,7 @@ func newExecutor(vars Vars, ruleVars map[string]Vars) *Executor {
return ex
}
+*/
// TODO(ukai): use time.Time?
func getTimestamp(filename string) int64 {
@@ -159,22 +149,7 @@ func getTimestamp(filename string) int64 {
return st.ModTime().Unix()
}
-func (ex *Executor) exists(target string) bool {
- _, present := ex.rules[target]
- if present {
- return true
- }
- rule, present := ex.rules[".PHONY"]
- if present {
- for _, input := range rule.inputs {
- if target == input {
- return true
- }
- }
- }
- return exists(target)
-}
-
+/*
type runner struct {
output string
cmd string
@@ -226,12 +201,13 @@ func newRunner(r runner, s string) runner {
r.cmd = s
return r
}
+*/
-func (r runner) run() error {
- if r.echo {
+func (r Runner) run(output string) error {
+ if r.echo || dryRunFlag {
fmt.Printf("%s\n", r.cmd)
}
- if r.dryRun {
+ if dryRunFlag {
return nil
}
args := []string{r.shell, "-c", r.cmd}
@@ -243,7 +219,7 @@ func (r runner) run() error {
fmt.Printf("%s", out)
exit := exitStatus(err)
if r.ignoreError && exit != 0 {
- fmt.Printf("[%s] Error %d (ignored)\n", r.output, exit)
+ fmt.Printf("[%s] Error %d (ignored)\n", output, exit)
err = nil
}
return err
@@ -262,6 +238,7 @@ func exitStatus(err error) int {
return exit
}
+/*
func replaceSuffix(s string, newsuf string) string {
// TODO: Factor out the logic around suffix rules and use
// it from substitution references.
@@ -374,8 +351,10 @@ func (ex *Executor) pickRule(output string) (*Rule, Vars, bool) {
}
return rule, vars, rule != nil
}
+*/
-func (ex *Executor) build(output string, neededBy string) (int64, error) {
+func (ex *Executor) build(n *DepNode, neededBy string) (int64, error) {
+ output := n.Output
Log("Building: %s", output)
ex.buildCnt++
if ex.buildCnt%100 == 0 {
@@ -394,8 +373,7 @@ func (ex *Executor) build(output string, neededBy string) (int64, error) {
ex.done[output] = -1
outputTs = getTimestamp(output)
- rule, vars, present := ex.pickRule(output)
- if !present {
+ if !n.HasRule {
if outputTs >= 0 {
ex.done[output] = outputTs
ex.noRuleCnt++
@@ -409,66 +387,15 @@ func (ex *Executor) build(output string, neededBy string) (int64, error) {
return outputTs, fmt.Errorf("no rule to make target %q", output)
}
- var restores []func()
- if vars != nil {
- for name, v := range vars {
- tsv := v.(TargetSpecificVar)
- restores = append(restores, ex.vars.save(name))
- switch tsv.op {
- case ":=", "=":
- ex.vars[name] = tsv
- case "+=":
- oldVar, present := ex.vars[name]
- if !present || oldVar.String() == "" {
- ex.vars[name] = tsv
- } else {
- ex.vars[name] = oldVar.AppendVar(newEvaluator(ex.vars), tsv)
- }
- case "?=":
- if _, present := ex.vars[name]; !present {
- ex.vars[name] = tsv
- }
- }
- }
- defer func() {
- for _, restore := range restores {
- restore()
- }
- }()
- }
-
latest := int64(-1)
- var actualInputs []string
- Log("Building: %s inputs:%q", output, rule.inputs)
- for _, input := range rule.inputs {
- if len(rule.outputPatterns) > 0 {
- if len(rule.outputPatterns) > 1 {
- panic("TODO: multiple output pattern is not supported yet")
- }
- input = substPattern(rule.outputPatterns[0], input, output)
- } else if rule.isSuffixRule {
- input = replaceSuffix(output, input)
- }
- actualInputs = append(actualInputs, input)
-
- ex.trace = append(ex.trace, input)
- ts, err := ex.build(input, output)
- ex.trace = ex.trace[0 : len(ex.trace)-1]
- if err != nil {
- return outputTs, err
- }
- if latest < ts {
- latest = ts
- }
- }
-
- for _, input := range rule.orderOnlyInputs {
- if exists(input) {
+ Log("Building: %s inputs:%q", output, n.Deps)
+ for _, d := range n.Deps {
+ if d.IsOrderOnly && exists(d.Output) {
continue
}
- ex.trace = append(ex.trace, input)
- ts, err := ex.build(input, output)
+ ex.trace = append(ex.trace, d.Output)
+ ts, err := ex.build(d, output)
ex.trace = ex.trace[0 : len(ex.trace)-1]
if err != nil {
return outputTs, err
@@ -484,33 +411,11 @@ func (ex *Executor) build(output string, neededBy string) (int64, error) {
return outputTs, nil
}
- // For automatic variables.
- ex.currentOutput = output
- ex.currentInputs = actualInputs
-
- ev := newEvaluator(ex.vars)
- ev.filename = rule.filename
- ev.lineno = rule.cmdLineno
- var runners []runner
- Log("Building: %s cmds:%q", output, rule.cmds)
- r := runner{
- output: output,
- echo: true,
- dryRun: dryRunFlag,
- shell: ex.shell,
- }
- for _, cmd := range rule.cmds {
- for _, r := range evalCmd(ev, r, cmd) {
- if len(r.cmd) != 0 {
- runners = append(runners, r)
- }
- }
- }
- for _, r := range runners {
- err := r.run()
+ for _, r := range n.Runners {
+ err := r.run(output)
if err != nil {
exit := exitStatus(err)
- fmt.Printf("[%s] Error %d: %v\n", r.output, exit, err)
+ fmt.Printf("[%s] Error %d: %v\n", output, exit, err)
return outputTs, err
}
}
@@ -525,6 +430,7 @@ func (ex *Executor) build(output string, neededBy string) (int64, error) {
return outputTs, nil
}
+/*
func (ex *Executor) populateSuffixRule(rule *Rule, output string) bool {
if len(output) == 0 || output[0] != '.' {
return false
@@ -634,6 +540,7 @@ func (ex *Executor) populateRules(er *EvalResult) {
ex.implicitRules[j] = r
}
}
+*/
func (ex *Executor) reportStats() {
if !katiLogFlag && !katiStatsFlag {
@@ -642,44 +549,21 @@ func (ex *Executor) reportStats() {
LogStats("build=%d alreadyDone=%d noRule=%d, upToDate=%d runCommand=%d",
ex.buildCnt, ex.alreadyDoneCnt, ex.noRuleCnt, ex.upToDateCnt, ex.runCommandCnt)
- LogStats("explicit=%d implicit=%d suffix=%d explicitWOCmd=%d",
- ex.pickExplicitRuleCnt, ex.pickImplicitRuleCnt, ex.pickSuffixRuleCnt, ex.pickExplicitRuleWithoutCmdCnt)
if len(ex.trace) > 1 {
LogStats("trace=%q", ex.trace)
}
}
-func NewExecutor(er *EvalResult, vars Vars) *Executor {
- ex := newExecutor(vars, er.ruleVars)
- // TODO: We should move this to somewhere around evalCmd so that
- // we can handle SHELL in target specific variables.
- shellVar := ex.vars.Lookup("SHELL")
- ex.shell = shellVar.String()
-
- ex.populateRules(er)
+func NewExecutor() *Executor {
+ ex := &Executor{
+ done: make(map[string]int64),
+ }
return ex
}
-func (ex *Executor) Exec(targets []string) error {
- if len(targets) == 0 {
- if ex.firstRule == nil {
- ErrorNoLocation("*** No targets.")
- }
- targets = append(targets, ex.firstRule.outputs[0])
- }
-
- LogStats("%d variables", len(ex.vars))
- LogStats("%d explicit rules", len(ex.rules))
- LogStats("%d implicit rules", len(ex.implicitRules))
- LogStats("%d suffix rules", len(ex.suffixRules))
-
- for _, target := range targets {
- ex.trace = []string{target}
- _, err := ex.build(target, "")
- if err != nil {
- return err
- }
+func (ex *Executor) Exec(roots []*DepNode) error {
+ for _, root := range roots {
+ ex.build(root, "")
}
- ex.reportStats()
return nil
}