Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/scripts/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 7 kB image not shown  

Quelle  build_broken_logs.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// 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
)

type Setting struct {
 name     string
 behavior BuildBrokenBehavior
 warnings []string
}

var buildBrokenSettings = []Setting{
 {
  name:     "BUILD_BROKEN_DUP_RULES",
  behavior: DefaultFalse,
  warnings: []string{"overriding commands for target"},
 },
 {
  name:     "BUILD_BROKEN_USES_NETWORK",
  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 {
 Branch string
 Name   string
}

type ProductLog struct {
 ProductBranch
 Log
 Device string
}

type Log struct {
 WarningModuleTypes []string
 ErrorModuleTypes   []string

 BuildBroken map[string]*bool
 HasBroken   map[string]int
}

func Merge(l, l2 Log) Log {
 if l.BuildBroken == nil {
  l.BuildBroken = map[string]*bool{}
 }
 if l.HasBroken == nil {
  l.HasBroken = map[string]int{}
 }

 for n, v := range l.BuildBroken {
  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 n := range l.HasBroken {
  if l.HasBroken[n] < l2.HasBroken[n] {
   l.HasBroken[n] = l2.HasBroken[n]
  }
 }
 for n := range l2.HasBroken {
  if _, ok := l.HasBroken[n]; !ok {
   l.HasBroken[n] = l2.HasBroken[n]
  }
 }

 return l
}

func PrintResults(branch Branch) {
 products := branch.Logs
 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 _, setting := range branch.Settings {
  printed := false
  n := setting.name

  for _, device := range deviceNames {
   log := devices[device]

   if setting.behavior == DefaultTrue {
    if log.BuildBroken[n] == nil || *log.BuildBroken[n] == false {
     if log.HasBroken[n] > 0 {
      printed = true
      plural := ""
      if log.HasBroken[n] > 1 {
       plural = "s"
      }
      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
     fmt.Printf("  %s sets %s := true, but does not need it\n", device, setting.name)
    }
   } else if setting.behavior == DefaultFalse {
    if log.BuildBroken[n] == nil {
     // Nothing to be done
    } else if *log.BuildBroken[n] == 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[n] == 0 {
     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[n] != nil {
     printed = true
     if log.HasBroken[n] > 0 {
      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 {
      fmt.Printf("  %s sets %s := %v, which is deprecated and can be removed\n", device, setting.name, *log.BuildBroken[n])
     }
    }
   }
  }

  if printed {
   fmt.Println()
  }
 }
}

func ParseBranch(name string) Branch {
 products, err := filepath.Glob(filepath.Join(name, "*"))
 if err != nil {
  log.Fatal(err)
 }

 ret := Branch{Logs: []ProductLog{}}
 for _, product := range products {
  product = filepath.Base(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
}

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: map[string]*bool{},
   HasBroken:   map[string]int{},
  },
 }

 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 fields[3] == "DEFAULT_WARNING_BUILD_MODULE_TYPES" {
   ret.WarningModuleTypes = 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
}

func ScanProduct(settings []Setting, l ProductLog) {
 stdLog, err := ioutil.ReadFile(filepath.Join(l.Branch, l.Name, "std_full.log"))
 if err != nil {
  log.Fatal(err)
 }
 stdStr := string(stdLog)

 for _, setting := range settings {
  for _, warning := range setting.warnings {
   if strings.Contains(stdStr, warning) {
    l.HasBroken[setting.name] += strings.Count(stdStr, warning)
   }
  }
 }
}

func ParseBoolPtr(str string) *bool {
 var ret *bool
 if str != "" {
  b := str == "true"
  ret = &b
 }
 return ret
}

[Dauer der Verarbeitung: 0.24 Sekunden, vorverarbeitet 2026-06-28]