prune out empty bazel depsets
Instead of using a sentinel file that was created under bazel_workspace
prune them out. The sentinel file was being created under bazel_workspace,
which would be deleted and thus rendered useless from the perspective of
not retriggering a build.
Test: `touch Android.bp` then `NINJA_ARGS="-d explain" m --bazel-mode-staging adbd_test`
Bug: 265155778
Change-Id: If5d8f0ea7f3b8828fda0646faafd1a621f0cb27c
diff --git a/bazel/aquery.go b/bazel/aquery.go
index bc823b3..80cf70a 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -118,12 +118,11 @@
// A helper type for aquery processing which facilitates retrieval of path IDs from their
// less readable Bazel structures (depset and path fragment).
type aqueryArtifactHandler struct {
- // Switches to true if any depset contains only `bazelToolsDependencySentinel`
- bazelToolsDependencySentinelNeeded bool
// Maps depset id to AqueryDepset, a representation of depset which is
// post-processed for middleman artifact handling, unhandled artifact
// dropping, content hashing, etc.
depsetIdToAqueryDepset map[depsetId]AqueryDepset
+ emptyDepsetIds map[depsetId]struct{}
// Maps content hash to AqueryDepset.
depsetHashToAqueryDepset map[string]AqueryDepset
@@ -145,9 +144,6 @@
// The file name of py3wrapper.sh, which is used by py_binary targets.
const py3wrapperFileName = "/py3wrapper.sh"
-// A file to be put into depsets that are otherwise empty
-const bazelToolsDependencySentinel = "BAZEL_TOOLS_DEPENDENCY_SENTINEL"
-
func indexBy[K comparable, V any](values []V, keyFn func(v V) K) map[K]V {
m := map[K]V{}
for _, v := range values {
@@ -192,6 +188,7 @@
depsetIdToAqueryDepset: map[depsetId]AqueryDepset{},
depsetHashToAqueryDepset: map[string]AqueryDepset{},
depsetHashToArtifactPathsCache: map[string][]string{},
+ emptyDepsetIds: make(map[depsetId]struct{}, 0),
artifactIdToPath: artifactIdToPath,
}
@@ -208,16 +205,16 @@
// Ensures that the handler's depsetIdToAqueryDepset map contains an entry for the given
// depset.
-func (a *aqueryArtifactHandler) populateDepsetMaps(depset depSetOfFiles, middlemanIdToDepsetIds map[artifactId][]depsetId, depsetIdToDepset map[depsetId]depSetOfFiles) (AqueryDepset, error) {
+func (a *aqueryArtifactHandler) populateDepsetMaps(depset depSetOfFiles, middlemanIdToDepsetIds map[artifactId][]depsetId, depsetIdToDepset map[depsetId]depSetOfFiles) (*AqueryDepset, error) {
if aqueryDepset, containsDepset := a.depsetIdToAqueryDepset[depset.Id]; containsDepset {
- return aqueryDepset, nil
+ return &aqueryDepset, nil
}
transitiveDepsetIds := depset.TransitiveDepSetIds
var directArtifactPaths []string
for _, artifactId := range depset.DirectArtifactIds {
path, pathExists := a.artifactIdToPath[artifactId]
if !pathExists {
- return AqueryDepset{}, fmt.Errorf("undefined input artifactId %d", artifactId)
+ return nil, fmt.Errorf("undefined input artifactId %d", artifactId)
}
// Filter out any inputs which are universally dropped, and swap middleman
// artifacts with their corresponding depsets.
@@ -226,6 +223,7 @@
transitiveDepsetIds = append(transitiveDepsetIds, depsetsToUse...)
} else if strings.HasSuffix(path, py3wrapperFileName) ||
strings.HasPrefix(path, "../bazel_tools") {
+ continue
// Drop these artifacts.
// See go/python-binary-host-mixed-build for more details.
// 1) Drop py3wrapper.sh, just use python binary, the launcher script generated by the
@@ -241,20 +239,23 @@
for _, childDepsetId := range transitiveDepsetIds {
childDepset, exists := depsetIdToDepset[childDepsetId]
if !exists {
- return AqueryDepset{}, fmt.Errorf("undefined input depsetId %d (referenced by depsetId %d)", childDepsetId, depset.Id)
+ if _, empty := a.emptyDepsetIds[childDepsetId]; empty {
+ continue
+ } else {
+ return nil, fmt.Errorf("undefined input depsetId %d (referenced by depsetId %d)", childDepsetId, depset.Id)
+ }
}
- childAqueryDepset, err := a.populateDepsetMaps(childDepset, middlemanIdToDepsetIds, depsetIdToDepset)
- if err != nil {
- return AqueryDepset{}, err
+ if childAqueryDepset, err := a.populateDepsetMaps(childDepset, middlemanIdToDepsetIds, depsetIdToDepset); err != nil {
+ return nil, err
+ } else if childAqueryDepset == nil {
+ continue
+ } else {
+ childDepsetHashes = append(childDepsetHashes, childAqueryDepset.ContentHash)
}
- childDepsetHashes = append(childDepsetHashes, childAqueryDepset.ContentHash)
}
if len(directArtifactPaths) == 0 && len(childDepsetHashes) == 0 {
- // We could omit this depset altogether but that requires cleanup on
- // transitive dependents.
- // As a simpler alternative, we use this sentinel file as a dependency.
- directArtifactPaths = append(directArtifactPaths, bazelToolsDependencySentinel)
- a.bazelToolsDependencySentinelNeeded = true
+ a.emptyDepsetIds[depset.Id] = struct{}{}
+ return nil, nil
}
aqueryDepset := AqueryDepset{
ContentHash: depsetContentHash(directArtifactPaths, childDepsetHashes),
@@ -263,7 +264,7 @@
}
a.depsetIdToAqueryDepset[depset.Id] = aqueryDepset
a.depsetHashToAqueryDepset[aqueryDepset.ContentHash] = aqueryDepset
- return aqueryDepset, nil
+ return &aqueryDepset, nil
}
// getInputPaths flattens the depsets of the given IDs and returns all transitive
@@ -392,14 +393,6 @@
}
var buildStatements []BuildStatement
- if aqueryHandler.bazelToolsDependencySentinelNeeded {
- buildStatements = append(buildStatements, BuildStatement{
- Command: fmt.Sprintf("touch '%s'", bazelToolsDependencySentinel),
- OutputPaths: []string{bazelToolsDependencySentinel},
- Mnemonic: bazelToolsDependencySentinel,
- })
- }
-
for _, actionEntry := range aqueryResult.Actions {
if shouldSkipAction(actionEntry) {
continue
@@ -484,7 +477,9 @@
var hashes []string
for _, depsetId := range inputDepsetIds {
if aqueryDepset, exists := a.depsetIdToAqueryDepset[depsetId]; !exists {
- return nil, fmt.Errorf("undefined input depsetId %d", depsetId)
+ if _, empty := a.emptyDepsetIds[depsetId]; !empty {
+ return nil, fmt.Errorf("undefined (not even empty) input depsetId %d", depsetId)
+ }
} else {
hashes = append(hashes, aqueryDepset.ContentHash)
}