| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 1 | // Copyright 2019 Google Inc. All rights reserved. | 
|  | 2 | // | 
|  | 3 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 4 | // you may not use this file except in compliance with the License. | 
|  | 5 | // You may obtain a copy of the License at | 
|  | 6 | // | 
|  | 7 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 8 | // | 
|  | 9 | // Unless required by applicable law or agreed to in writing, software | 
|  | 10 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 12 | // See the License for the specific language governing permissions and | 
|  | 13 | // limitations under the License. | 
|  | 14 |  | 
|  | 15 | // This is a script that can be used to analyze the results from | 
|  | 16 | // build/soong/build_test.bash and recommend what devices need changes to their | 
|  | 17 | // BUILD_BROKEN_* flags. | 
|  | 18 | // | 
|  | 19 | // To use, download the logs.zip from one or more branches, and extract them | 
|  | 20 | // into subdirectories of the current directory. So for example, I have: | 
|  | 21 | // | 
| Colin Cross | d079e0b | 2022-08-16 10:27:33 -0700 | [diff] [blame] | 22 | //	./aosp-master/aosp_arm/std_full.log | 
|  | 23 | //	./aosp-master/aosp_arm64/std_full.log | 
|  | 24 | //	./aosp-master/... | 
|  | 25 | //	./internal-master/aosp_arm/std_full.log | 
|  | 26 | //	./internal-master/aosp_arm64/std_full.log | 
|  | 27 | //	./internal-master/... | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 28 | // | 
|  | 29 | // Then I use `go run path/to/build_broken_logs.go *` | 
|  | 30 | package main | 
|  | 31 |  | 
|  | 32 | import ( | 
|  | 33 | "fmt" | 
|  | 34 | "io/ioutil" | 
|  | 35 | "log" | 
|  | 36 | "os" | 
|  | 37 | "path/filepath" | 
|  | 38 | "sort" | 
|  | 39 | "strings" | 
|  | 40 | ) | 
|  | 41 |  | 
|  | 42 | func main() { | 
|  | 43 | for _, branch := range os.Args[1:] { | 
|  | 44 | fmt.Printf("\nBranch %s:\n", branch) | 
|  | 45 | PrintResults(ParseBranch(branch)) | 
|  | 46 | } | 
|  | 47 | } | 
|  | 48 |  | 
|  | 49 | type BuildBrokenBehavior int | 
|  | 50 |  | 
|  | 51 | const ( | 
|  | 52 | DefaultFalse BuildBrokenBehavior = iota | 
|  | 53 | DefaultTrue | 
|  | 54 | DefaultDeprecated | 
|  | 55 | ) | 
|  | 56 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 57 | type Setting struct { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 58 | name     string | 
|  | 59 | behavior BuildBrokenBehavior | 
|  | 60 | warnings []string | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 61 | } | 
|  | 62 |  | 
|  | 63 | var buildBrokenSettings = []Setting{ | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 64 | { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 65 | name:     "BUILD_BROKEN_DUP_RULES", | 
|  | 66 | behavior: DefaultFalse, | 
|  | 67 | warnings: []string{"overriding commands for target"}, | 
|  | 68 | }, | 
|  | 69 | { | 
| Dan Willemsen | 25e6f09 | 2019-04-09 10:22:43 -0700 | [diff] [blame] | 70 | name:     "BUILD_BROKEN_USES_NETWORK", | 
|  | 71 | behavior: DefaultDeprecated, | 
|  | 72 | }, | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 73 | { | 
|  | 74 | name:     "BUILD_BROKEN_USES_BUILD_COPY_HEADERS", | 
|  | 75 | behavior: DefaultTrue, | 
|  | 76 | warnings: []string{ | 
|  | 77 | "COPY_HEADERS has been deprecated", | 
|  | 78 | "COPY_HEADERS is deprecated", | 
|  | 79 | }, | 
|  | 80 | }, | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | type Branch struct { | 
|  | 84 | Settings []Setting | 
|  | 85 | Logs     []ProductLog | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 86 | } | 
|  | 87 |  | 
|  | 88 | type ProductBranch struct { | 
|  | 89 | Branch string | 
|  | 90 | Name   string | 
|  | 91 | } | 
|  | 92 |  | 
|  | 93 | type ProductLog struct { | 
|  | 94 | ProductBranch | 
|  | 95 | Log | 
|  | 96 | Device string | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | type Log struct { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 100 | WarningModuleTypes []string | 
|  | 101 | ErrorModuleTypes   []string | 
|  | 102 |  | 
|  | 103 | BuildBroken map[string]*bool | 
|  | 104 | HasBroken   map[string]int | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 105 | } | 
|  | 106 |  | 
|  | 107 | func Merge(l, l2 Log) Log { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 108 | if l.BuildBroken == nil { | 
|  | 109 | l.BuildBroken = map[string]*bool{} | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 110 | } | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 111 | if l.HasBroken == nil { | 
|  | 112 | l.HasBroken = map[string]int{} | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 113 | } | 
|  | 114 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 115 | for n, v := range l.BuildBroken { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 116 | if v == nil { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 117 | l.BuildBroken[n] = l2.BuildBroken[n] | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 118 | } | 
|  | 119 | } | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 120 | for n, v := range l2.BuildBroken { | 
|  | 121 | if _, ok := l.BuildBroken[n]; !ok { | 
|  | 122 | l.BuildBroken[n] = v | 
|  | 123 | } | 
|  | 124 | } | 
|  | 125 |  | 
|  | 126 | for n := range l.HasBroken { | 
|  | 127 | if l.HasBroken[n] < l2.HasBroken[n] { | 
|  | 128 | l.HasBroken[n] = l2.HasBroken[n] | 
|  | 129 | } | 
|  | 130 | } | 
|  | 131 | for n := range l2.HasBroken { | 
|  | 132 | if _, ok := l.HasBroken[n]; !ok { | 
|  | 133 | l.HasBroken[n] = l2.HasBroken[n] | 
|  | 134 | } | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 135 | } | 
|  | 136 |  | 
|  | 137 | return l | 
|  | 138 | } | 
|  | 139 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 140 | func PrintResults(branch Branch) { | 
|  | 141 | products := branch.Logs | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 142 | devices := map[string]Log{} | 
|  | 143 | deviceNames := []string{} | 
|  | 144 |  | 
|  | 145 | for _, product := range products { | 
|  | 146 | device := product.Device | 
|  | 147 | if _, ok := devices[device]; !ok { | 
|  | 148 | deviceNames = append(deviceNames, device) | 
|  | 149 | } | 
|  | 150 | devices[device] = Merge(devices[device], product.Log) | 
|  | 151 | } | 
|  | 152 |  | 
|  | 153 | sort.Strings(deviceNames) | 
|  | 154 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 155 | for _, setting := range branch.Settings { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 156 | printed := false | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 157 | n := setting.name | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 158 |  | 
|  | 159 | for _, device := range deviceNames { | 
|  | 160 | log := devices[device] | 
|  | 161 |  | 
|  | 162 | if setting.behavior == DefaultTrue { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 163 | if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false { | 
|  | 164 | if log.HasBroken[n] > 0 { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 165 | printed = true | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 166 | plural := "" | 
|  | 167 | if log.HasBroken[n] > 1 { | 
|  | 168 | plural = "s" | 
|  | 169 | } | 
|  | 170 | fmt.Printf("  %s needs to set %s := true  (%d instance%s)\n", device, setting.name, log.HasBroken[n], plural) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 171 | } | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 172 | } else if log.HasBroken[n] == 0 { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 173 | printed = true | 
|  | 174 | fmt.Printf("  %s sets %s := true, but does not need it\n", device, setting.name) | 
|  | 175 | } | 
|  | 176 | } else if setting.behavior == DefaultFalse { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 177 | if log.BuildBroken[n] == nil { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 178 | // Nothing to be done | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 179 | } else if *log.BuildBroken[n] == false { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 180 | printed = true | 
|  | 181 | fmt.Printf("  %s sets %s := false, which is the default and can be removed\n", device, setting.name) | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 182 | } else if log.HasBroken[n] == 0 { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 183 | printed = true | 
|  | 184 | fmt.Printf("  %s sets %s := true, but does not need it\n", device, setting.name) | 
|  | 185 | } | 
|  | 186 | } else if setting.behavior == DefaultDeprecated { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 187 | if log.BuildBroken[n] != nil { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 188 | printed = true | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 189 | if log.HasBroken[n] > 0 { | 
|  | 190 | plural := "" | 
|  | 191 | if log.HasBroken[n] > 1 { | 
|  | 192 | plural = "s" | 
|  | 193 | } | 
|  | 194 | 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) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 195 | } else { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 196 | fmt.Printf("  %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n]) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 197 | } | 
|  | 198 | } | 
|  | 199 | } | 
|  | 200 | } | 
|  | 201 |  | 
|  | 202 | if printed { | 
|  | 203 | fmt.Println() | 
|  | 204 | } | 
|  | 205 | } | 
|  | 206 | } | 
|  | 207 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 208 | func ParseBranch(name string) Branch { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 209 | products, err := filepath.Glob(filepath.Join(name, "*")) | 
|  | 210 | if err != nil { | 
|  | 211 | log.Fatal(err) | 
|  | 212 | } | 
|  | 213 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 214 | ret := Branch{Logs: []ProductLog{}} | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 215 | for _, product := range products { | 
|  | 216 | product = filepath.Base(product) | 
|  | 217 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 218 | ret.Logs = append(ret.Logs, ParseProduct(ProductBranch{Branch: name, Name: product})) | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | ret.Settings = append(ret.Settings, buildBrokenSettings...) | 
|  | 222 | if len(ret.Logs) > 0 { | 
|  | 223 | for _, mtype := range ret.Logs[0].WarningModuleTypes { | 
|  | 224 | if mtype == "BUILD_COPY_HEADERS" || mtype == "" { | 
|  | 225 | continue | 
|  | 226 | } | 
|  | 227 | ret.Settings = append(ret.Settings, Setting{ | 
|  | 228 | name:     "BUILD_BROKEN_USES_" + mtype, | 
|  | 229 | behavior: DefaultTrue, | 
|  | 230 | warnings: []string{mtype + " has been deprecated"}, | 
|  | 231 | }) | 
|  | 232 | } | 
|  | 233 | for _, mtype := range ret.Logs[0].ErrorModuleTypes { | 
|  | 234 | if mtype == "BUILD_COPY_HEADERS" || mtype == "" { | 
|  | 235 | continue | 
|  | 236 | } | 
|  | 237 | ret.Settings = append(ret.Settings, Setting{ | 
|  | 238 | name:     "BUILD_BROKEN_USES_" + mtype, | 
|  | 239 | behavior: DefaultFalse, | 
|  | 240 | warnings: []string{mtype + " has been deprecated"}, | 
|  | 241 | }) | 
|  | 242 | } | 
|  | 243 | } | 
|  | 244 |  | 
|  | 245 | for _, productLog := range ret.Logs { | 
|  | 246 | ScanProduct(ret.Settings, productLog) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 247 | } | 
|  | 248 | return ret | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | func ParseProduct(p ProductBranch) ProductLog { | 
|  | 252 | soongLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "soong.log")) | 
|  | 253 | if err != nil { | 
|  | 254 | log.Fatal(err) | 
|  | 255 | } | 
|  | 256 |  | 
|  | 257 | ret := ProductLog{ | 
|  | 258 | ProductBranch: p, | 
|  | 259 | Log: Log{ | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 260 | BuildBroken: map[string]*bool{}, | 
|  | 261 | HasBroken:   map[string]int{}, | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 262 | }, | 
|  | 263 | } | 
|  | 264 |  | 
|  | 265 | lines := strings.Split(string(soongLog), "\n") | 
|  | 266 | for _, line := range lines { | 
|  | 267 | fields := strings.Split(line, " ") | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 268 | if len(fields) < 5 { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 269 | continue | 
|  | 270 | } | 
|  | 271 |  | 
|  | 272 | if fields[3] == "TARGET_DEVICE" { | 
|  | 273 | ret.Device = fields[4] | 
|  | 274 | } | 
|  | 275 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 276 | if fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" { | 
|  | 277 | ret.WarningModuleTypes = fields[4:] | 
|  | 278 | } | 
|  | 279 | if fields[3] == "DEFAULT_ERROR_BUILD_MODULE_TYPES" { | 
|  | 280 | ret.ErrorModuleTypes = fields[4:] | 
|  | 281 | } | 
|  | 282 |  | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 283 | if strings.HasPrefix(fields[3], "BUILD_BROKEN_") { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 284 | ret.BuildBroken[fields[3]] = ParseBoolPtr(fields[4]) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 285 | } | 
|  | 286 | } | 
|  | 287 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 288 | return ret | 
|  | 289 | } | 
|  | 290 |  | 
|  | 291 | func ScanProduct(settings []Setting, l ProductLog) { | 
|  | 292 | stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log")) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 293 | if err != nil { | 
|  | 294 | log.Fatal(err) | 
|  | 295 | } | 
|  | 296 | stdStr := string(stdLog) | 
|  | 297 |  | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 298 | for _, setting := range settings { | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 299 | for _, warning := range setting.warnings { | 
|  | 300 | if strings.Contains(stdStr, warning) { | 
| Dan Willemsen | 9dfaa06 | 2020-01-29 10:09:16 -0800 | [diff] [blame] | 301 | l.HasBroken[setting.name] += strings.Count(stdStr, warning) | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 302 | } | 
|  | 303 | } | 
|  | 304 | } | 
| Dan Willemsen | 01f0a05 | 2019-02-05 13:44:20 -0800 | [diff] [blame] | 305 | } | 
|  | 306 |  | 
|  | 307 | func ParseBoolPtr(str string) *bool { | 
|  | 308 | var ret *bool | 
|  | 309 | if str != "" { | 
|  | 310 | b := str == "true" | 
|  | 311 | ret = &b | 
|  | 312 | } | 
|  | 313 | return ret | 
|  | 314 | } |