Merge "Add BUILD_BROKEN_ENG_DEBUG_TAGS to soong.log" am: 3a984f55f6
am: 39a139493e
Change-Id: I7412deac7f39464b3ba03a5f4f6256b2e9af7d0b
This commit is contained in:
commit
0cfd68d52a
|
@ -0,0 +1,266 @@
|
|||
// Copyright 2019 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// This is a script that can be used to analyze the results from
|
||||
// build/soong/build_test.bash and recommend what devices need changes to their
|
||||
// BUILD_BROKEN_* flags.
|
||||
//
|
||||
// To use, download the logs.zip from one or more branches, and extract them
|
||||
// into subdirectories of the current directory. So for example, I have:
|
||||
//
|
||||
// ./aosp-master/aosp_arm/std_full.log
|
||||
// ./aosp-master/aosp_arm64/std_full.log
|
||||
// ./aosp-master/...
|
||||
// ./internal-master/aosp_arm/std_full.log
|
||||
// ./internal-master/aosp_arm64/std_full.log
|
||||
// ./internal-master/...
|
||||
//
|
||||
// Then I use `go run path/to/build_broken_logs.go *`
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for _, branch := range os.Args[1:] {
|
||||
fmt.Printf("\nBranch %s:\n", branch)
|
||||
PrintResults(ParseBranch(branch))
|
||||
}
|
||||
}
|
||||
|
||||
type BuildBrokenBehavior int
|
||||
|
||||
const (
|
||||
DefaultFalse BuildBrokenBehavior = iota
|
||||
DefaultTrue
|
||||
DefaultDeprecated
|
||||
)
|
||||
|
||||
var buildBrokenSettings = []struct {
|
||||
name string
|
||||
behavior BuildBrokenBehavior
|
||||
warnings []string
|
||||
}{
|
||||
{
|
||||
name: "BUILD_BROKEN_DUP_COPY_HEADERS",
|
||||
behavior: DefaultDeprecated,
|
||||
warnings: []string{"Duplicate header copy:"},
|
||||
},
|
||||
{
|
||||
name: "BUILD_BROKEN_DUP_RULES",
|
||||
behavior: DefaultFalse,
|
||||
warnings: []string{"overriding commands for target"},
|
||||
},
|
||||
{
|
||||
name: "BUILD_BROKEN_ANDROIDMK_EXPORTS",
|
||||
behavior: DefaultFalse,
|
||||
warnings: []string{"export_keyword"},
|
||||
},
|
||||
{
|
||||
name: "BUILD_BROKEN_PHONY_TARGETS",
|
||||
behavior: DefaultFalse,
|
||||
warnings: []string{
|
||||
"depends on PHONY target",
|
||||
"looks like a real file",
|
||||
"writing to readonly directory",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "BUILD_BROKEN_ENG_DEBUG_TAGS",
|
||||
behavior: DefaultTrue,
|
||||
warnings: []string{
|
||||
"Changes.md#LOCAL_MODULE_TAGS",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type ProductBranch struct {
|
||||
Branch string
|
||||
Name string
|
||||
}
|
||||
|
||||
type ProductLog struct {
|
||||
ProductBranch
|
||||
Log
|
||||
Device string
|
||||
}
|
||||
|
||||
type Log struct {
|
||||
BuildBroken []*bool
|
||||
HasBroken []bool
|
||||
}
|
||||
|
||||
func Merge(l, l2 Log) Log {
|
||||
if len(l.BuildBroken) == 0 {
|
||||
l.BuildBroken = make([]*bool, len(buildBrokenSettings))
|
||||
}
|
||||
if len(l.HasBroken) == 0 {
|
||||
l.HasBroken = make([]bool, len(buildBrokenSettings))
|
||||
}
|
||||
|
||||
if len(l.BuildBroken) != len(l2.BuildBroken) || len(l.HasBroken) != len(l2.HasBroken) {
|
||||
panic("mis-matched logs")
|
||||
}
|
||||
|
||||
for i, v := range l.BuildBroken {
|
||||
if v == nil {
|
||||
l.BuildBroken[i] = l2.BuildBroken[i]
|
||||
}
|
||||
}
|
||||
for i := range l.HasBroken {
|
||||
l.HasBroken[i] = l.HasBroken[i] || l2.HasBroken[i]
|
||||
}
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func PrintResults(products []ProductLog) {
|
||||
devices := map[string]Log{}
|
||||
deviceNames := []string{}
|
||||
|
||||
for _, product := range products {
|
||||
device := product.Device
|
||||
if _, ok := devices[device]; !ok {
|
||||
deviceNames = append(deviceNames, device)
|
||||
}
|
||||
devices[device] = Merge(devices[device], product.Log)
|
||||
}
|
||||
|
||||
sort.Strings(deviceNames)
|
||||
|
||||
for i, setting := range buildBrokenSettings {
|
||||
printed := false
|
||||
|
||||
for _, device := range deviceNames {
|
||||
log := devices[device]
|
||||
|
||||
if setting.behavior == DefaultTrue {
|
||||
if log.BuildBroken[i] == nil || *log.BuildBroken[i] == false {
|
||||
if log.HasBroken[i] {
|
||||
printed = true
|
||||
fmt.Printf(" %s needs to set %s := true\n", device, setting.name)
|
||||
}
|
||||
} else if !log.HasBroken[i] {
|
||||
printed = true
|
||||
fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name)
|
||||
}
|
||||
} else if setting.behavior == DefaultFalse {
|
||||
if log.BuildBroken[i] == nil {
|
||||
// Nothing to be done
|
||||
} else if *log.BuildBroken[i] == false {
|
||||
printed = true
|
||||
fmt.Printf(" %s sets %s := false, which is the default and can be removed\n", device, setting.name)
|
||||
} else if !log.HasBroken[i] {
|
||||
printed = true
|
||||
fmt.Printf(" %s sets %s := true, but does not need it\n", device, setting.name)
|
||||
}
|
||||
} else if setting.behavior == DefaultDeprecated {
|
||||
if log.BuildBroken[i] != nil {
|
||||
printed = true
|
||||
if log.HasBroken[i] {
|
||||
fmt.Printf(" %s sets %s := %v, which is deprecated, but has failures\n", device, setting.name, *log.BuildBroken[i])
|
||||
} else {
|
||||
fmt.Printf(" %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if printed {
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ParseBranch(name string) []ProductLog {
|
||||
products, err := filepath.Glob(filepath.Join(name, "*"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ret := []ProductLog{}
|
||||
for _, product := range products {
|
||||
product = filepath.Base(product)
|
||||
|
||||
ret = append(ret, ParseProduct(ProductBranch{Branch: name, Name: product}))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func ParseProduct(p ProductBranch) ProductLog {
|
||||
soongLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "soong.log"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
ret := ProductLog{
|
||||
ProductBranch: p,
|
||||
Log: Log{
|
||||
BuildBroken: make([]*bool, len(buildBrokenSettings)),
|
||||
HasBroken: make([]bool, len(buildBrokenSettings)),
|
||||
},
|
||||
}
|
||||
|
||||
lines := strings.Split(string(soongLog), "\n")
|
||||
for _, line := range lines {
|
||||
fields := strings.Split(line, " ")
|
||||
if len(fields) != 5 {
|
||||
continue
|
||||
}
|
||||
|
||||
if fields[3] == "TARGET_DEVICE" {
|
||||
ret.Device = fields[4]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(fields[3], "BUILD_BROKEN_") {
|
||||
for i, setting := range buildBrokenSettings {
|
||||
if setting.name == fields[3] {
|
||||
ret.BuildBroken[i] = ParseBoolPtr(fields[4])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stdLog, err := ioutil.ReadFile(filepath.Join(p.Branch, p.Name, "std_full.log"))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
stdStr := string(stdLog)
|
||||
|
||||
for i, setting := range buildBrokenSettings {
|
||||
for _, warning := range setting.warnings {
|
||||
if strings.Contains(stdStr, warning) {
|
||||
ret.HasBroken[i] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func ParseBoolPtr(str string) *bool {
|
||||
var ret *bool
|
||||
if str != "" {
|
||||
b := str == "true"
|
||||
ret = &b
|
||||
}
|
||||
return ret
|
||||
}
|
|
@ -206,6 +206,7 @@ func runMakeProductConfig(ctx Context, config Config) {
|
|||
// Not used, but useful to be in the soong.log
|
||||
"BUILD_BROKEN_ANDROIDMK_EXPORTS",
|
||||
"BUILD_BROKEN_DUP_COPY_HEADERS",
|
||||
"BUILD_BROKEN_ENG_DEBUG_TAGS",
|
||||
}, exportEnvVars...), BannerVars...)
|
||||
|
||||
make_vars, err := dumpMakeVars(ctx, config, config.Arguments(), allVars, true)
|
||||
|
|
Loading…
Reference in New Issue