aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--exec.go13
-rw-r--r--rule_parser.go39
-rw-r--r--rule_parser_test.go8
-rw-r--r--test/order_only.mk14
4 files changed, 57 insertions, 17 deletions
diff --git a/exec.go b/exec.go
index 4cd612e..af4a191 100644
--- a/exec.go
+++ b/exec.go
@@ -177,6 +177,19 @@ func (ex *Executor) build(vars map[string]string, output string) (int64, error)
}
}
+ for _, input := range rule.orderOnlyInputs {
+ if exists(input) {
+ continue
+ }
+ ts, err := ex.build(vars, input)
+ if err != nil {
+ return outputTs, err
+ }
+ if latest < ts {
+ latest = ts
+ }
+ }
+
if outputTs >= latest {
return outputTs, nil
}
diff --git a/rule_parser.go b/rule_parser.go
index b560876..c7ee1bd 100644
--- a/rule_parser.go
+++ b/rule_parser.go
@@ -5,21 +5,38 @@ import (
)
type Rule struct {
- outputs []string
- inputs []string
- outputPatterns []string
- isDoubleColon bool
- isSuffixRule bool
- cmds []string
- filename string
- lineno int
- cmdLineno int
+ outputs []string
+ inputs []string
+ orderOnlyInputs []string
+ outputPatterns []string
+ isDoubleColon bool
+ isSuffixRule bool
+ cmds []string
+ filename string
+ lineno int
+ cmdLineno int
}
func isPatternRule(s string) bool {
return strings.IndexByte(s, '%') >= 0
}
+func (r *Rule) parseInputs(s string) {
+ inputs := splitSpaces(s)
+ isOrderOnly := false
+ for _, input := range inputs {
+ if input == "|" {
+ isOrderOnly = true
+ continue
+ }
+ if isOrderOnly {
+ r.orderOnlyInputs = append(r.orderOnlyInputs, input)
+ } else {
+ r.inputs = append(r.inputs, input)
+ }
+ }
+}
+
func (r *Rule) parse(line string) string {
index := strings.IndexByte(line, ':')
if index < 0 {
@@ -47,7 +64,7 @@ func (r *Rule) parse(line string) string {
rest := line[index:]
index = strings.IndexByte(rest, ':')
if index < 0 {
- r.inputs = splitSpaces(rest)
+ r.parseInputs(rest)
return ""
}
@@ -70,7 +87,7 @@ func (r *Rule) parse(line string) string {
if !isPatternRule(r.outputPatterns[0]) {
return "*** target pattern contains no '%'."
}
- r.inputs = splitSpaces(third)
+ r.parseInputs(third)
return ""
}
diff --git a/rule_parser_test.go b/rule_parser_test.go
index dbc166e..f44c589 100644
--- a/rule_parser_test.go
+++ b/rule_parser_test.go
@@ -72,6 +72,14 @@ func TestRuleParser(t *testing.T) {
in: "foo.o: foo.o: %.c",
err: "*** target pattern contains no '%'.",
},
+ {
+ in: "foo: bar | baz",
+ want: Rule{
+ outputs: []string{"foo"},
+ inputs: []string{"bar"},
+ orderOnlyInputs: []string{"baz"},
+ },
+ },
/* TODO
{
in: "foo.o: %.c: %.c",
diff --git a/test/order_only.mk b/test/order_only.mk
index 90fc831..b8e0cfd 100644
--- a/test/order_only.mk
+++ b/test/order_only.mk
@@ -1,11 +1,13 @@
-# TODO(hamaji): Fix.
-
test1:
- touch foo
+ touch -t 197101010000 foo
touch bar
-test2: foo
- echo PASS
+# Note order-only dependency will not appear in $^
+test2: foo | bar
+ echo PASS_$^
+
+# bar is newer than foo but we should not rebuild it.
+foo: | bar baz
-foo: | bar
+baz:
touch $@