Loading scripts/build_broken_logs.go +114 −44 Original line number Original line Diff line number Diff line Loading @@ -54,11 +54,13 @@ const ( DefaultDeprecated DefaultDeprecated ) ) var buildBrokenSettings = []struct { type Setting struct { name string name string behavior BuildBrokenBehavior behavior BuildBrokenBehavior warnings []string warnings []string }{ } var buildBrokenSettings = []Setting{ { { name: "BUILD_BROKEN_DUP_RULES", name: "BUILD_BROKEN_DUP_RULES", behavior: DefaultFalse, behavior: DefaultFalse, Loading @@ -68,6 +70,19 @@ var buildBrokenSettings = []struct { name: "BUILD_BROKEN_USES_NETWORK", name: "BUILD_BROKEN_USES_NETWORK", behavior: DefaultDeprecated, behavior: DefaultDeprecated, }, }, { name: "BUILD_BROKEN_USES_BUILD_COPY_HEADERS", behavior: DefaultTrue, warnings: []string{ "COPY_HEADERS has been deprecated", "COPY_HEADERS is deprecated", }, }, } type Branch struct { Settings []Setting Logs []ProductLog } } type ProductBranch struct { type ProductBranch struct { Loading @@ -82,35 +97,48 @@ type ProductLog struct { } } type Log struct { type Log struct { BuildBroken []*bool WarningModuleTypes []string HasBroken []bool ErrorModuleTypes []string BuildBroken map[string]*bool HasBroken map[string]int } } func Merge(l, l2 Log) Log { func Merge(l, l2 Log) Log { if len(l.BuildBroken) == 0 { if l.BuildBroken == nil { l.BuildBroken = make([]*bool, len(buildBrokenSettings)) l.BuildBroken = map[string]*bool{} } } if len(l.HasBroken) == 0 { if l.HasBroken == nil { l.HasBroken = make([]bool, len(buildBrokenSettings)) l.HasBroken = map[string]int{} } } if len(l.BuildBroken) != len(l2.BuildBroken) || len(l.HasBroken) != len(l2.HasBroken) { for n, v := range l.BuildBroken { panic("mis-matched logs") if v == nil { l.BuildBroken[n] = l2.BuildBroken[n] } } for n, v := range l2.BuildBroken { if _, ok := l.BuildBroken[n]; !ok { l.BuildBroken[n] = v } } } for i, v := range l.BuildBroken { for n := range l.HasBroken { if v == nil { if l.HasBroken[n] < l2.HasBroken[n] { l.BuildBroken[i] = l2.BuildBroken[i] l.HasBroken[n] = l2.HasBroken[n] } } } for n := range l2.HasBroken { if _, ok := l.HasBroken[n]; !ok { l.HasBroken[n] = l2.HasBroken[n] } } for i := range l.HasBroken { l.HasBroken[i] = l.HasBroken[i] || l2.HasBroken[i] } } return l return l } } func PrintResults(products []ProductLog) { func PrintResults(branch Branch) { products := branch.Logs devices := map[string]Log{} devices := map[string]Log{} deviceNames := []string{} deviceNames := []string{} Loading @@ -124,39 +152,48 @@ func PrintResults(products []ProductLog) { sort.Strings(deviceNames) sort.Strings(deviceNames) for i, setting := range buildBrokenSettings { for _, setting := range branch.Settings { printed := false printed := false n := setting.name for _, device := range deviceNames { for _, device := range deviceNames { log := devices[device] log := devices[device] if setting.behavior == DefaultTrue { if setting.behavior == DefaultTrue { if log.BuildBroken[i] == nil || *log.BuildBroken[i] == false { if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false { if log.HasBroken[i] { if log.HasBroken[n] > 0 { printed = true printed = true fmt.Printf(" %s needs to set %s := true\n", device, setting.name) plural := "" if log.HasBroken[n] > 1 { plural = "s" } } } else if !log.HasBroken[i] { fmt.Printf(" %s needs to set %s := true (%d instance%s)\n", device, setting.name, log.HasBroken[n], plural) } } else if log.HasBroken[n] == 0 { printed = true printed = true fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) } } } else if setting.behavior == DefaultFalse { } else if setting.behavior == DefaultFalse { if log.BuildBroken[i] == nil { if log.BuildBroken[n] == nil { // Nothing to be done // Nothing to be done } else if *log.BuildBroken[i] == false { } else if *log.BuildBroken[n] == false { printed = true printed = true fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name) fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name) } else if !log.HasBroken[i] { } else if log.HasBroken[n] == 0 { printed = true printed = true fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) } } } else if setting.behavior == DefaultDeprecated { } else if setting.behavior == DefaultDeprecated { if log.BuildBroken[i] != nil { if log.BuildBroken[n] != nil { printed = true printed = true if log.HasBroken[i] { if log.HasBroken[n] > 0 { fmt.Printf(" %s sets %s := %v, which is deprecated, but has failures\n", device, setting.name, *log.BuildBroken[i]) plural := "" if log.HasBroken[n] > 1 { plural = "s" } fmt.Printf(" %s sets %s := %v, which is deprecated, but has %d failure%s\n", device, setting.name, *log.BuildBroken[n], log.HasBroken[n], plural) } else { } else { fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[i]) fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n]) } } } } } } Loading @@ -168,17 +205,45 @@ func PrintResults(products []ProductLog) { } } } } func ParseBranch(name string) []ProductLog { func ParseBranch(name string) Branch { products, err := filepath.Glob(filepath.Join(name, "*")) products, err := filepath.Glob(filepath.Join(name, "*")) if err != nil { if err != nil { log.Fatal(err) log.Fatal(err) } } ret := []ProductLog{} ret := Branch{Logs: []ProductLog{}} for _, product := range products { for _, product := range products { product = filepath.Base(product) product = filepath.Base(product) ret = append(ret, ParseProduct(ProductBranch{Branch: name, Name: product})) ret.Logs = append(ret.Logs, ParseProduct(ProductBranch{Branch: name, Name: product})) } ret.Settings = append(ret.Settings, buildBrokenSettings...) if len(ret.Logs) > 0 { for _, mtype := range ret.Logs[0].WarningModuleTypes { if mtype == "BUILD_COPY_HEADERS" || mtype == "" { continue } ret.Settings = append(ret.Settings, Setting{ name: "BUILD_BROKEN_USES_" + mtype, behavior: DefaultTrue, warnings: []string{mtype + " has been deprecated"}, }) } for _, mtype := range ret.Logs[0].ErrorModuleTypes { if mtype == "BUILD_COPY_HEADERS" || mtype == "" { continue } ret.Settings = append(ret.Settings, Setting{ name: "BUILD_BROKEN_USES_" + mtype, behavior: DefaultFalse, warnings: []string{mtype + " has been deprecated"}, }) } } for _, productLog := range ret.Logs { ScanProduct(ret.Settings, productLog) } } return ret return ret } } Loading @@ -192,15 +257,15 @@ func ParseProduct(p ProductBranch) ProductLog { ret := ProductLog{ ret := ProductLog{ ProductBranch: p, ProductBranch: p, Log: Log{ Log: Log{ BuildBroken: make([]*bool, len(buildBrokenSettings)), BuildBroken: map[string]*bool{}, HasBroken: make([]bool, len(buildBrokenSettings)), HasBroken: map[string]int{}, }, }, } } lines := strings.Split(string(soongLog), "\n") lines := strings.Split(string(soongLog), "\n") for _, line := range lines { for _, line := range lines { fields := strings.Split(line, " ") fields := strings.Split(line, " ") if len(fields) != 5 { if len(fields) < 5 { continue continue } } Loading @@ -208,30 +273,35 @@ func ParseProduct(p ProductBranch) ProductLog { ret.Device = fields[4] ret.Device = fields[4] } } if strings.HasPrefix(fields[3], "BUILD_BROKEN_") { if fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" { for i, setting := range buildBrokenSettings { ret.WarningModuleTypes = fields[4:] if setting.name == fields[3] { } ret.BuildBroken[i] = ParseBoolPtr(fields[4]) if fields[3] == "DEFAULT_ERROR_BUILD_MODULE_TYPES" { ret.ErrorModuleTypes = fields[4:] } } if strings.HasPrefix(fields[3], "BUILD_BROKEN_") { ret.BuildBroken[fields[3]] = ParseBoolPtr(fields[4]) } } } } return ret } } stdLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "std_full.log")) func ScanProduct(settings []Setting, l ProductLog) { stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log")) if err != nil { if err != nil { log.Fatal(err) log.Fatal(err) } } stdStr := string(stdLog) stdStr := string(stdLog) for i, setting := range buildBrokenSettings { for _, setting := range settings { for _, warning := range setting.warnings { for _, warning := range setting.warnings { if strings.Contains(stdStr, warning) { if strings.Contains(stdStr, warning) { ret.HasBroken[i] = true l.HasBroken[setting.name] += strings.Count(stdStr, warning) } } } } } } return ret } } func ParseBoolPtr(str string) *bool { func ParseBoolPtr(str string) *bool { Loading Loading
scripts/build_broken_logs.go +114 −44 Original line number Original line Diff line number Diff line Loading @@ -54,11 +54,13 @@ const ( DefaultDeprecated DefaultDeprecated ) ) var buildBrokenSettings = []struct { type Setting struct { name string name string behavior BuildBrokenBehavior behavior BuildBrokenBehavior warnings []string warnings []string }{ } var buildBrokenSettings = []Setting{ { { name: "BUILD_BROKEN_DUP_RULES", name: "BUILD_BROKEN_DUP_RULES", behavior: DefaultFalse, behavior: DefaultFalse, Loading @@ -68,6 +70,19 @@ var buildBrokenSettings = []struct { name: "BUILD_BROKEN_USES_NETWORK", name: "BUILD_BROKEN_USES_NETWORK", behavior: DefaultDeprecated, behavior: DefaultDeprecated, }, }, { name: "BUILD_BROKEN_USES_BUILD_COPY_HEADERS", behavior: DefaultTrue, warnings: []string{ "COPY_HEADERS has been deprecated", "COPY_HEADERS is deprecated", }, }, } type Branch struct { Settings []Setting Logs []ProductLog } } type ProductBranch struct { type ProductBranch struct { Loading @@ -82,35 +97,48 @@ type ProductLog struct { } } type Log struct { type Log struct { BuildBroken []*bool WarningModuleTypes []string HasBroken []bool ErrorModuleTypes []string BuildBroken map[string]*bool HasBroken map[string]int } } func Merge(l, l2 Log) Log { func Merge(l, l2 Log) Log { if len(l.BuildBroken) == 0 { if l.BuildBroken == nil { l.BuildBroken = make([]*bool, len(buildBrokenSettings)) l.BuildBroken = map[string]*bool{} } } if len(l.HasBroken) == 0 { if l.HasBroken == nil { l.HasBroken = make([]bool, len(buildBrokenSettings)) l.HasBroken = map[string]int{} } } if len(l.BuildBroken) != len(l2.BuildBroken) || len(l.HasBroken) != len(l2.HasBroken) { for n, v := range l.BuildBroken { panic("mis-matched logs") if v == nil { l.BuildBroken[n] = l2.BuildBroken[n] } } for n, v := range l2.BuildBroken { if _, ok := l.BuildBroken[n]; !ok { l.BuildBroken[n] = v } } } for i, v := range l.BuildBroken { for n := range l.HasBroken { if v == nil { if l.HasBroken[n] < l2.HasBroken[n] { l.BuildBroken[i] = l2.BuildBroken[i] l.HasBroken[n] = l2.HasBroken[n] } } } for n := range l2.HasBroken { if _, ok := l.HasBroken[n]; !ok { l.HasBroken[n] = l2.HasBroken[n] } } for i := range l.HasBroken { l.HasBroken[i] = l.HasBroken[i] || l2.HasBroken[i] } } return l return l } } func PrintResults(products []ProductLog) { func PrintResults(branch Branch) { products := branch.Logs devices := map[string]Log{} devices := map[string]Log{} deviceNames := []string{} deviceNames := []string{} Loading @@ -124,39 +152,48 @@ func PrintResults(products []ProductLog) { sort.Strings(deviceNames) sort.Strings(deviceNames) for i, setting := range buildBrokenSettings { for _, setting := range branch.Settings { printed := false printed := false n := setting.name for _, device := range deviceNames { for _, device := range deviceNames { log := devices[device] log := devices[device] if setting.behavior == DefaultTrue { if setting.behavior == DefaultTrue { if log.BuildBroken[i] == nil || *log.BuildBroken[i] == false { if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false { if log.HasBroken[i] { if log.HasBroken[n] > 0 { printed = true printed = true fmt.Printf(" %s needs to set %s := true\n", device, setting.name) plural := "" if log.HasBroken[n] > 1 { plural = "s" } } } else if !log.HasBroken[i] { fmt.Printf(" %s needs to set %s := true (%d instance%s)\n", device, setting.name, log.HasBroken[n], plural) } } else if log.HasBroken[n] == 0 { printed = true printed = true fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) } } } else if setting.behavior == DefaultFalse { } else if setting.behavior == DefaultFalse { if log.BuildBroken[i] == nil { if log.BuildBroken[n] == nil { // Nothing to be done // Nothing to be done } else if *log.BuildBroken[i] == false { } else if *log.BuildBroken[n] == false { printed = true printed = true fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name) fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name) } else if !log.HasBroken[i] { } else if log.HasBroken[n] == 0 { printed = true printed = true fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name) } } } else if setting.behavior == DefaultDeprecated { } else if setting.behavior == DefaultDeprecated { if log.BuildBroken[i] != nil { if log.BuildBroken[n] != nil { printed = true printed = true if log.HasBroken[i] { if log.HasBroken[n] > 0 { fmt.Printf(" %s sets %s := %v, which is deprecated, but has failures\n", device, setting.name, *log.BuildBroken[i]) plural := "" if log.HasBroken[n] > 1 { plural = "s" } fmt.Printf(" %s sets %s := %v, which is deprecated, but has %d failure%s\n", device, setting.name, *log.BuildBroken[n], log.HasBroken[n], plural) } else { } else { fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[i]) fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n]) } } } } } } Loading @@ -168,17 +205,45 @@ func PrintResults(products []ProductLog) { } } } } func ParseBranch(name string) []ProductLog { func ParseBranch(name string) Branch { products, err := filepath.Glob(filepath.Join(name, "*")) products, err := filepath.Glob(filepath.Join(name, "*")) if err != nil { if err != nil { log.Fatal(err) log.Fatal(err) } } ret := []ProductLog{} ret := Branch{Logs: []ProductLog{}} for _, product := range products { for _, product := range products { product = filepath.Base(product) product = filepath.Base(product) ret = append(ret, ParseProduct(ProductBranch{Branch: name, Name: product})) ret.Logs = append(ret.Logs, ParseProduct(ProductBranch{Branch: name, Name: product})) } ret.Settings = append(ret.Settings, buildBrokenSettings...) if len(ret.Logs) > 0 { for _, mtype := range ret.Logs[0].WarningModuleTypes { if mtype == "BUILD_COPY_HEADERS" || mtype == "" { continue } ret.Settings = append(ret.Settings, Setting{ name: "BUILD_BROKEN_USES_" + mtype, behavior: DefaultTrue, warnings: []string{mtype + " has been deprecated"}, }) } for _, mtype := range ret.Logs[0].ErrorModuleTypes { if mtype == "BUILD_COPY_HEADERS" || mtype == "" { continue } ret.Settings = append(ret.Settings, Setting{ name: "BUILD_BROKEN_USES_" + mtype, behavior: DefaultFalse, warnings: []string{mtype + " has been deprecated"}, }) } } for _, productLog := range ret.Logs { ScanProduct(ret.Settings, productLog) } } return ret return ret } } Loading @@ -192,15 +257,15 @@ func ParseProduct(p ProductBranch) ProductLog { ret := ProductLog{ ret := ProductLog{ ProductBranch: p, ProductBranch: p, Log: Log{ Log: Log{ BuildBroken: make([]*bool, len(buildBrokenSettings)), BuildBroken: map[string]*bool{}, HasBroken: make([]bool, len(buildBrokenSettings)), HasBroken: map[string]int{}, }, }, } } lines := strings.Split(string(soongLog), "\n") lines := strings.Split(string(soongLog), "\n") for _, line := range lines { for _, line := range lines { fields := strings.Split(line, " ") fields := strings.Split(line, " ") if len(fields) != 5 { if len(fields) < 5 { continue continue } } Loading @@ -208,30 +273,35 @@ func ParseProduct(p ProductBranch) ProductLog { ret.Device = fields[4] ret.Device = fields[4] } } if strings.HasPrefix(fields[3], "BUILD_BROKEN_") { if fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" { for i, setting := range buildBrokenSettings { ret.WarningModuleTypes = fields[4:] if setting.name == fields[3] { } ret.BuildBroken[i] = ParseBoolPtr(fields[4]) if fields[3] == "DEFAULT_ERROR_BUILD_MODULE_TYPES" { ret.ErrorModuleTypes = fields[4:] } } if strings.HasPrefix(fields[3], "BUILD_BROKEN_") { ret.BuildBroken[fields[3]] = ParseBoolPtr(fields[4]) } } } } return ret } } stdLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "std_full.log")) func ScanProduct(settings []Setting, l ProductLog) { stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log")) if err != nil { if err != nil { log.Fatal(err) log.Fatal(err) } } stdStr := string(stdLog) stdStr := string(stdLog) for i, setting := range buildBrokenSettings { for _, setting := range settings { for _, warning := range setting.warnings { for _, warning := range setting.warnings { if strings.Contains(stdStr, warning) { if strings.Contains(stdStr, warning) { ret.HasBroken[i] = true l.HasBroken[setting.name] += strings.Count(stdStr, warning) } } } } } } return ret } } func ParseBoolPtr(str string) *bool { func ParseBoolPtr(str string) *bool { Loading