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