Merge "Only write soong_injection files if changed"

This commit is contained in:
Christopher Parsons
2023-02-06 22:23:54 +00:00
committed by Gerrit Code Review
2 changed files with 80 additions and 15 deletions

View File

@@ -183,9 +183,11 @@ type bazelPaths struct {
// and their results after the requests have been made.
type mixedBuildBazelContext struct {
bazelRunner
paths *bazelPaths
requests map[cqueryKey]bool // cquery requests that have not yet been issued to Bazel
requestMutex sync.Mutex // requests can be written in parallel
paths *bazelPaths
// cquery requests that have not yet been issued to Bazel. This list is maintained
// in a sorted state, and is guaranteed to have no duplicates.
requests []cqueryKey
requestMutex sync.Mutex // requests can be written in parallel
results map[cqueryKey]string // Results of cquery requests after Bazel invocations
@@ -296,7 +298,29 @@ func (bazelCtx *mixedBuildBazelContext) QueueBazelRequest(label string, requestT
key := makeCqueryKey(label, requestType, cfgKey)
bazelCtx.requestMutex.Lock()
defer bazelCtx.requestMutex.Unlock()
bazelCtx.requests[key] = true
// Insert key into requests, maintaining the sort, and only if it's not duplicate.
keyString := key.String()
foundEqual := false
notLessThanKeyString := func(i int) bool {
s := bazelCtx.requests[i].String()
v := strings.Compare(s, keyString)
if v == 0 {
foundEqual = true
}
return v >= 0
}
targetIndex := sort.Search(len(bazelCtx.requests), notLessThanKeyString)
if foundEqual {
return
}
if targetIndex == len(bazelCtx.requests) {
bazelCtx.requests = append(bazelCtx.requests, key)
} else {
bazelCtx.requests = append(bazelCtx.requests[:targetIndex+1], bazelCtx.requests[targetIndex:]...)
bazelCtx.requests[targetIndex] = key
}
}
func (bazelCtx *mixedBuildBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
@@ -487,7 +511,6 @@ func NewBazelContext(c *config) (BazelContext, error) {
return &mixedBuildBazelContext{
bazelRunner: &builtinBazelRunner{},
paths: &paths,
requests: make(map[cqueryKey]bool),
modulesDefaultToBazel: c.BuildMode == BazelDevMode,
bazelEnabledModules: enabledModules,
bazelDisabledModules: disabledModules,
@@ -727,14 +750,23 @@ config_node(name = "%s",
configNodesSection := ""
labelsByConfig := map[string][]string{}
for val := range context.requests {
for _, val := range context.requests {
labelString := fmt.Sprintf("\"@%s\"", val.label)
configString := getConfigString(val)
labelsByConfig[configString] = append(labelsByConfig[configString], labelString)
}
// Configs need to be sorted to maintain determinism of the BUILD file.
sortedConfigs := make([]string, 0, len(labelsByConfig))
for val := range labelsByConfig {
sortedConfigs = append(sortedConfigs, val)
}
sort.Slice(sortedConfigs, func(i, j int) bool { return sortedConfigs[i] < sortedConfigs[j] })
allLabels := []string{}
for configString, labels := range labelsByConfig {
for _, configString := range sortedConfigs {
labels := labelsByConfig[configString]
configTokens := strings.Split(configString, "|")
if len(configTokens) != 2 {
panic(fmt.Errorf("Unexpected config string format: %s", configString))
@@ -765,7 +797,7 @@ func indent(original string) string {
// request type.
func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
for val := range context.requests {
for _, val := range context.requests {
cqueryId := getCqueryId(val)
mapEntryString := fmt.Sprintf("%q : True", cqueryId)
requestTypeToCqueryIdEntries[val.requestType] =
@@ -944,7 +976,7 @@ func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx *Context)
}
// Clear requests.
context.requests = map[cqueryKey]bool{}
context.requests = []cqueryKey{}
return nil
}
@@ -961,17 +993,17 @@ func (context *mixedBuildBazelContext) runCquery(ctx *Context) error {
return err
}
}
if err := os.WriteFile(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
if err := writeFileBytesIfChanged(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
return err
}
if err := os.WriteFile(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
return err
}
if err := os.WriteFile(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
return err
}
cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
if err := os.WriteFile(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
if err := writeFileBytesIfChanged(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
return err
}
@@ -992,7 +1024,7 @@ func (context *mixedBuildBazelContext) runCquery(ctx *Context) error {
cqueryResults[splitLine[0]] = splitLine[1]
}
}
for val := range context.requests {
for _, val := range context.requests {
if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
context.results[val] = cqueryResult
} else {
@@ -1003,6 +1035,14 @@ func (context *mixedBuildBazelContext) runCquery(ctx *Context) error {
return nil
}
func writeFileBytesIfChanged(path string, contents []byte, perm os.FileMode) error {
oldContents, err := os.ReadFile(path)
if err != nil || !bytes.Equal(contents, oldContents) {
err = os.WriteFile(path, contents, perm)
}
return nil
}
func (context *mixedBuildBazelContext) runAquery(config Config, ctx *Context) error {
if ctx != nil {
ctx.EventHandler.Begin("aquery")

View File

@@ -168,6 +168,32 @@ func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
}
}
func TestBazelRequestsSorted(t *testing.T) {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Linux})
bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"otherarch", Android})
bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, configKey{"otherarch", Android})
if len(bazelContext.requests) != 7 {
t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
}
lastString := ""
for _, val := range bazelContext.requests {
thisString := val.String()
if thisString <= lastString {
t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
}
lastString = thisString
}
}
func verifyExtraFlags(t *testing.T, config Config, expected string) string {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
@@ -204,7 +230,6 @@ func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string)
return &mixedBuildBazelContext{
bazelRunner: runner,
paths: &p,
requests: map[cqueryKey]bool{},
}, p.soongOutDir
}