Add a dependency fixer for proto deps

protoc dependency files, at least for C++ outputs, uses the form of:

  a/b.c \
  a/b.h: <dep1> <dep2>...

Ninja will fail the command when it parses a dep file and there's more
than one output file (even though it doesn't care what the output file
name is). So this tool will parse the original file, and output a
version with only a single output file.

Bug: 67329638
Test: NINJA_ARGS="-t deps ...pb.c" m
Test: NINJA_ARGS="-t deps ...srcjar" m
Test: NINJA_ARGS="-t deps ...srcszip" m
Test: Run dep_fixer across all of taimen's dep files, no failures.
Test: Run dep_fixer against the processed files, no changes.
Test: Run androidmk across all of our Android.mk files, inspect the diffs
Change-Id: I4263b7d5faea37285afa6b24dedf5964aa7d19dc
This commit is contained in:
Dan Willemsen
2018-02-21 02:10:29 -08:00
parent 470969df19
commit 4339853a20
13 changed files with 816 additions and 16 deletions

View File

@@ -90,10 +90,10 @@ func (ms *MakeString) Value(scope Scope) string {
if len(ms.Strings) == 0 {
return ""
} else {
ret := ms.Strings[0]
ret := unescape(ms.Strings[0])
for i := range ms.Strings[1:] {
ret += ms.Variables[i].Value(scope)
ret += ms.Strings[i+1]
ret += unescape(ms.Strings[i+1])
}
return ret
}
@@ -125,6 +125,16 @@ func (ms *MakeString) Split(sep string) []*MakeString {
}
func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
return ms.splitNFunc(n, func(s string, n int) []string {
return splitAnyN(s, sep, n)
})
}
func (ms *MakeString) Words() []*MakeString {
return ms.splitNFunc(-1, splitWords)
}
func (ms *MakeString) splitNFunc(n int, splitFunc func(s string, n int) []string) []*MakeString {
ret := []*MakeString{}
curMs := SimpleMakeString("", ms.Pos())
@@ -133,7 +143,7 @@ func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
var s string
for i, s = range ms.Strings {
if n != 0 {
split := splitAnyN(s, sep, n)
split := splitFunc(s, n)
if n != -1 {
if len(split) > n {
panic("oops!")
@@ -156,7 +166,9 @@ func (ms *MakeString) SplitN(sep string, n int) []*MakeString {
}
}
ret = append(ret, curMs)
if !curMs.Empty() {
ret = append(ret, curMs)
}
return ret
}
@@ -206,3 +218,64 @@ func splitAnyN(s, sep string, n int) []string {
ret = append(ret, s)
return ret
}
func splitWords(s string, n int) []string {
ret := []string{}
preserve := ""
for n == -1 || n > 1 {
index := strings.IndexAny(s, " \t")
if index == 0 && len(preserve) == 0 {
s = s[1:]
} else if index >= 0 {
escapeCount := 0
for i := index - 1; i >= 0; i-- {
if s[i] != '\\' {
break
}
escapeCount += 1
}
if escapeCount%2 == 1 {
preserve += s[0 : index+1]
s = s[index+1:]
continue
}
ret = append(ret, preserve+s[0:index])
s = s[index+1:]
preserve = ""
if n > 0 {
n--
}
} else {
break
}
}
if preserve != "" || s != "" || len(ret) == 0 {
ret = append(ret, preserve+s)
}
return ret
}
func unescape(s string) string {
ret := ""
for {
index := strings.IndexByte(s, '\\')
if index < 0 {
break
}
if index+1 == len(s) {
break
}
switch s[index+1] {
case ' ', '\\', '#', ':', '*', '[', '|', '\t', '\n', '\r':
ret += s[:index] + s[index+1:index+2]
default:
ret += s[:index+2]
}
s = s[index+2:]
}
return ret + s
}