find bazel-related files and add them to bazel.list and ninja deps

This retriggers soong_build whenever a new bzl, WORKSPACE, or
BUILD.bazel file is changed or added.

Test: Manually verified on bionic/libc genrules with manual changes to
related BUILD/bzl/WORKSPACE files -- these all retrigger builds.
Test: Updated finder_test.go

Change-Id: I634384f88781a6b6db32f5d6bf9c07e179e14c39
This commit is contained in:
Chris Parsons 2020-10-12 23:44:08 -04:00
parent 19bc60abee
commit a798d96076
5 changed files with 126 additions and 7 deletions

View file

@ -18,11 +18,15 @@ import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
"github.com/google/blueprint/bootstrap"
)
// Map key to describe bazel cquery requests.
@ -237,3 +241,28 @@ func (context *bazelContext) InvokeBazel() error {
context.requests = map[cqueryKey]bool{}
return nil
}
// Singleton used for registering BUILD file ninja dependencies (needed
// for correctness of builds which use Bazel.
func BazelSingleton() Singleton {
return &bazelSingleton{}
}
type bazelSingleton struct{}
func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
if ctx.Config().BazelContext.BazelEnabled() {
bazelBuildList := absolutePath(filepath.Join(
filepath.Dir(bootstrap.ModuleListFile), "bazel.list"))
ctx.AddNinjaFileDeps(bazelBuildList)
data, err := ioutil.ReadFile(bazelBuildList)
if err != nil {
ctx.Errorf(err.Error())
}
files := strings.Split(strings.TrimSpace(string(data)), "\n")
for _, file := range files {
ctx.AddNinjaFileDeps(file)
}
}
}

View file

@ -104,6 +104,8 @@ func (ctx *Context) Register() {
registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(BazelSingleton))
// Register phony just before makevars so it can write out its phony rules as Make rules
ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(phonySingletonFactory))

View file

@ -103,6 +103,9 @@ type CacheParams struct {
// IncludeFiles are file names to include as matches
IncludeFiles []string
// IncludeSuffixes are filename suffixes to include as matches.
IncludeSuffixes []string
}
// a cacheConfig stores the inputs that determine what should be included in the cache
@ -1310,6 +1313,20 @@ func (f *Finder) statDirSync(path string) statResponse {
return stats
}
func (f *Finder) shouldIncludeFile(fileName string) bool {
for _, includedName := range f.cacheMetadata.Config.IncludeFiles {
if fileName == includedName {
return true
}
}
for _, includeSuffix := range f.cacheMetadata.Config.IncludeSuffixes {
if strings.HasSuffix(fileName, includeSuffix) {
return true
}
}
return false
}
// pruneCacheCandidates removes the items that we don't want to include in our persistent cache
func (f *Finder) pruneCacheCandidates(items *DirEntries) {
@ -1326,13 +1343,9 @@ func (f *Finder) pruneCacheCandidates(items *DirEntries) {
// remove any files that aren't the ones we want to include
writeIndex := 0
for _, fileName := range items.FileNames {
// include only these files
for _, includedName := range f.cacheMetadata.Config.IncludeFiles {
if fileName == includedName {
items.FileNames[writeIndex] = fileName
writeIndex++
break
}
if f.shouldIncludeFile(fileName) {
items.FileNames[writeIndex] = fileName
writeIndex++
}
}
// resize

View file

@ -21,6 +21,7 @@ import (
"os"
"path/filepath"
"sort"
"strings"
"testing"
"android/soong/finder/fs"
@ -92,6 +93,7 @@ func runSimpleTest(t *testing.T, existentPaths []string, expectedMatches []strin
nil,
nil,
[]string{"findme.txt", "skipme.txt"},
nil,
},
)
defer finder.Shutdown()
@ -104,6 +106,46 @@ func runSimpleTest(t *testing.T, existentPaths []string, expectedMatches []strin
fs.AssertSameResponse(t, foundPaths, absoluteMatches)
}
// runTestWithSuffixes creates a few files, searches for findme.txt or any file
// with suffix `.findme_ext` and checks for the expected matches
func runTestWithSuffixes(t *testing.T, existentPaths []string, expectedMatches []string) {
filesystem := newFs()
root := "/tmp"
filesystem.MkDirs(root)
for _, path := range existentPaths {
fs.Create(t, filepath.Join(root, path), filesystem)
}
finder := newFinder(t,
filesystem,
CacheParams{
"/cwd",
[]string{root},
nil,
nil,
[]string{"findme.txt", "skipme.txt"},
[]string{".findme_ext"},
},
)
defer finder.Shutdown()
foundPaths := finder.FindMatching(root,
func(entries DirEntries) (dirs []string, files []string) {
matches := []string{}
for _, foundName := range entries.FileNames {
if foundName == "findme.txt" || strings.HasSuffix(foundName, ".findme_ext") {
matches = append(matches, foundName)
}
}
return entries.DirNames, matches
})
absoluteMatches := []string{}
for i := range expectedMatches {
absoluteMatches = append(absoluteMatches, filepath.Join(root, expectedMatches[i]))
}
fs.AssertSameResponse(t, foundPaths, absoluteMatches)
}
// testAgainstSeveralThreadcounts runs the given test for each threadcount that we care to test
func testAgainstSeveralThreadcounts(t *testing.T, tester func(t *testing.T, numThreads int)) {
// test singlethreaded, multithreaded, and also using the same number of threads as
@ -135,6 +177,13 @@ func TestIncludeFiles(t *testing.T) {
)
}
func TestIncludeFilesAndSuffixes(t *testing.T) {
runTestWithSuffixes(t,
[]string{"findme.txt", "skipme.txt", "alsome.findme_ext"},
[]string{"findme.txt", "alsome.findme_ext"},
)
}
func TestNestedDirectories(t *testing.T) {
runSimpleTest(t,
[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt"},
@ -142,6 +191,13 @@ func TestNestedDirectories(t *testing.T) {
)
}
func TestNestedDirectoriesWithSuffixes(t *testing.T) {
runTestWithSuffixes(t,
[]string{"findme.txt", "skipme.txt", "subdir/findme.txt", "subdir/skipme.txt", "subdir/alsome.findme_ext"},
[]string{"findme.txt", "subdir/findme.txt", "subdir/alsome.findme_ext"},
)
}
func TestEmptyDirectory(t *testing.T) {
runSimpleTest(t,
[]string{},

View file

@ -63,10 +63,13 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
"AndroidProducts.mk",
"Android.bp",
"Blueprints",
"BUILD.bazel",
"CleanSpec.mk",
"OWNERS",
"TEST_MAPPING",
"WORKSPACE",
},
IncludeSuffixes: []string{".bzl"},
}
dumpDir := config.FileListDir()
f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
@ -77,6 +80,16 @@ func NewSourceFinder(ctx Context, config Config) (f *finder.Finder) {
return f
}
func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
matches := []string{}
for _, foundName := range entries.FileNames {
if foundName == "BUILD.bazel" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
matches = append(matches, foundName)
}
}
return entries.DirNames, matches
}
// FindSources searches for source files known to <f> and writes them to the filesystem for
// use later.
func FindSources(ctx Context, config Config, f *finder.Finder) {
@ -99,6 +112,12 @@ func FindSources(ctx Context, config Config, f *finder.Finder) {
ctx.Fatalf("Could not export product list: %v", err)
}
bazelFiles := f.FindMatching(".", findBazelFiles)
err = dumpListToFile(ctx, config, bazelFiles, filepath.Join(dumpDir, "bazel.list"))
if err != nil {
ctx.Fatalf("Could not export bazel BUILD list: %v", err)
}
cleanSpecs := f.FindFirstNamedAt(".", "CleanSpec.mk")
err = dumpListToFile(ctx, config, cleanSpecs, filepath.Join(dumpDir, "CleanSpec.mk.list"))
if err != nil {