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