blob: 158eefbff64dec9a348b6542bab82cf096a2c668 [file] [log] [blame]
Fumitoshi Ukai119dc912015-03-30 16:52:41 +09001package main
2
3import (
4 "fmt"
5 "os"
6 "os/exec"
7 "time"
8)
9
10type Executor struct {
11 rules map[string]*Rule
12}
13
14func newExecutor() *Executor {
15 return &Executor{
16 rules: make(map[string]*Rule),
17 }
18}
19
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090020// TODO(ukai): use time.Time?
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090021func getTimestamp(filename string) int64 {
22 st, err := os.Stat(filename)
23 if err != nil {
24 return -2
25 }
26 return st.ModTime().Unix()
27}
28
29func (ex *Executor) runCommands(cmds []string) {
30 for _, cmd := range cmds {
31 fmt.Printf("%s\n", cmd)
32
33 args := []string{"/bin/sh", "-c", cmd}
34 cmd := exec.Cmd{
35 Path: args[0],
36 Args: args,
37 }
38 out, err := cmd.CombinedOutput()
39 if err != nil {
40 panic(err)
41 }
42 success := false
43 if cmd.ProcessState != nil {
44 success = cmd.ProcessState.Success()
45 }
46
47 fmt.Printf("%s", out)
48 if !success {
49 panic("Command failed")
50 }
51 }
52}
53
54func (ex *Executor) build(output string) int64 {
55 Log("Building: %s", output)
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090056 outputTs := getTimestamp(output)
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090057
58 rule, present := ex.rules[output]
59 if !present {
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090060 if outputTs >= 0 {
61 return outputTs
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090062 }
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090063 Error("No rule to make target %q", output)
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090064 }
65
66 latest := int64(-1)
67 for _, input := range rule.inputs {
68 ts := ex.build(input)
69 if latest < ts {
70 latest = ts
71 }
72 }
73
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090074 if outputTs >= latest {
75 return outputTs
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090076 }
77
78 ex.runCommands(rule.cmds)
79
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090080 outputTs = getTimestamp(output)
81 if outputTs < 0 {
82 outputTs = time.Now().Unix()
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090083 }
Fumitoshi Ukaicf2b0382015-03-30 17:48:54 +090084 return outputTs
Fumitoshi Ukai119dc912015-03-30 16:52:41 +090085}
86
87func (ex *Executor) exec(er *EvalResult) {
88 if len(er.rules) == 0 {
89 panic("No targets.")
90 }
91
92 for _, rule := range er.rules {
93 if _, present := ex.rules[rule.output]; present {
94 Warn("overiding recipie for target '%s'", rule.output)
95 }
96 ex.rules[rule.output] = rule
97 }
98
99 ex.build(er.rules[0].output)
100}
101
102func Exec(er *EvalResult) {
103 ex := newExecutor()
104 ex.exec(er)
105}