aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dep.go74
-rw-r--r--rule_parser.go1
2 files changed, 57 insertions, 18 deletions
diff --git a/dep.go b/dep.go
index da2fb78..6f86c2b 100644
--- a/dep.go
+++ b/dep.go
@@ -3,6 +3,7 @@ package main
import (
"fmt"
"path/filepath"
+ "sort"
"strings"
)
@@ -25,16 +26,17 @@ func (n *DepNode) String() string {
}
type DepBuilder struct {
- rules map[string]*Rule
- ruleVars map[string]Vars
- implicitRules []*Rule
- suffixRules map[string][]*Rule
- firstRule *Rule
- vars Vars
- done map[string]*DepNode
- phony map[string]bool
+ rules map[string]*Rule
+ ruleVars map[string]Vars
+ irules map[string][]*Rule // output -> implicitRules
+ suffixRules map[string][]*Rule
+ firstRule *Rule
+ vars Vars
+ done map[string]*DepNode
+ phony map[string]bool
trace []string
+ nImplicitRules int
nodeCnt int
pickExplicitRuleCnt int
pickImplicitRuleCnt int
@@ -108,7 +110,7 @@ func (db *DepBuilder) pickRule(output string) (*Rule, Vars, bool) {
db.pickExplicitRuleWithoutCmdCnt++
}
- for _, irule := range db.implicitRules {
+ for _, irule := range db.irules[output] {
if !db.canPickImplicitRule(irule, output) {
continue
}
@@ -356,16 +358,18 @@ func (db *DepBuilder) populateExplicitRule(rule *Rule) {
}
}
-func (db *DepBuilder) populateImplicitRule(rule *Rule) {
+func (db *DepBuilder) populateImplicitRule(irules []*Rule, rule *Rule) []*Rule {
for _, outputPattern := range rule.outputPatterns {
r := &Rule{}
*r = *rule
r.outputPatterns = []pattern{outputPattern}
- db.implicitRules = append(db.implicitRules, r)
+ irules = append(irules, r)
}
+ return irules
}
func (db *DepBuilder) populateRules(er *EvalResult) {
+ var implicitRules []*Rule
for _, rule := range er.rules {
for i, input := range rule.inputs {
rule.inputs[i] = trimLeadingCurdir(input)
@@ -376,18 +380,51 @@ func (db *DepBuilder) populateRules(er *EvalResult) {
db.populateExplicitRule(rule)
if len(rule.outputs) == 0 {
- db.populateImplicitRule(rule)
+ implicitRules = db.populateImplicitRule(implicitRules, rule)
}
}
// Reverse the implicit rule for easier lookup.
- for i, r := range db.implicitRules {
- if i >= len(db.implicitRules)/2 {
+ for i, r := range implicitRules {
+ if i >= len(implicitRules)/2 {
break
}
- j := len(db.implicitRules) - i - 1
- db.implicitRules[i] = db.implicitRules[j]
- db.implicitRules[j] = r
+ j := len(implicitRules) - i - 1
+ implicitRules[i] = implicitRules[j]
+ implicitRules[j] = r
+ }
+ db.nImplicitRules = len(implicitRules)
+
+ var outputs []string
+ for output := range db.rules {
+ outputs = append(outputs, output)
+ }
+ sort.Strings(outputs)
+ for _, irule := range implicitRules {
+ pat := irule.outputPatterns[0]
+ if pat.prefix == "" && pat.suffix == "" {
+ // TODO(ukai): in android, it is used for turning off
+ // RCS / SCCS implicit rules of GNU make, so we could
+ // ignore such implicit rules(?)
+ for _, output := range outputs {
+ db.irules[output] = append(db.irules[output], irule)
+ }
+ continue
+ }
+ if pat.prefix != "" {
+ i := sort.SearchStrings(outputs, pat.prefix)
+ for i < len(outputs) && strings.HasPrefix(outputs[i], pat.prefix) {
+ if strings.HasSuffix(outputs[i], pat.suffix) {
+ db.irules[outputs[i]] = append(db.irules[outputs[i]], irule)
+ }
+ i++
+ }
+ continue
+ }
+ if pat.suffix != "" {
+ // TODO(ukai): handle this. no such rule in android build?
+ panic(fmt.Sprintf("suffix rule found: %s at %s:%d", pat, irule.filename, irule.lineno))
+ }
}
}
@@ -407,6 +444,7 @@ func NewDepBuilder(er *EvalResult, vars Vars) *DepBuilder {
db := &DepBuilder{
rules: make(map[string]*Rule),
ruleVars: er.ruleVars,
+ irules: make(map[string][]*Rule),
suffixRules: make(map[string][]*Rule),
vars: vars,
done: make(map[string]*DepNode),
@@ -433,7 +471,7 @@ func (db *DepBuilder) Eval(targets []string) ([]*DepNode, error) {
LogStats("%d variables", len(db.vars))
LogStats("%d explicit rules", len(db.rules))
- LogStats("%d implicit rules", len(db.implicitRules))
+ LogStats("%d implicit rules", db.nImplicitRules)
LogStats("%d suffix rules", len(db.suffixRules))
var nodes []*DepNode
diff --git a/rule_parser.go b/rule_parser.go
index 7a6a8f9..3b485af 100644
--- a/rule_parser.go
+++ b/rule_parser.go
@@ -55,6 +55,7 @@ type Rule struct {
}
func isPatternRule(s []byte) (pattern, bool) {
+ s = trimSpaceBytes(s)
i := bytes.IndexByte(s, '%')
if i < 0 {
return pattern{}, false