Add direct deps on glob result files
n2 (a reimplemntation of ninja) adds a check that depfiles only add
dependencies on source files, not generated files, because generated
files are not guaranteed to exist before an action runs if there isn't
an explicit dependency between the two.
This is the case for our glob result files. However, we can rework the
build so that they're directly depended on instead of using a depfile.
Bug: 318434287
Test: rm -rf out && m nothing && m nothing
Change-Id: I513fa5536136e6bf19c347710f0722d696199612
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 0bf8862..90c3bfc 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -36,6 +36,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/microfactory"
+ "github.com/google/blueprint/pathtools"
"google.golang.org/protobuf/proto"
)
@@ -181,7 +182,15 @@
return globPathName
}
-func (pb PrimaryBuilderFactory) primaryBuilderInvocation() bootstrap.PrimaryBuilderInvocation {
+func getGlobPathNameFromPrimaryBuilderFactory(config Config, pb PrimaryBuilderFactory) string {
+ if pb.name == soongBuildTag {
+ // Glob path for soong build would be separated per product target
+ return getGlobPathName(config)
+ }
+ return pb.name
+}
+
+func (pb PrimaryBuilderFactory) primaryBuilderInvocation(config Config) bootstrap.PrimaryBuilderInvocation {
commonArgs := make([]string, 0, 0)
if !pb.config.skipSoongTests {
@@ -215,11 +224,7 @@
var allArgs []string
allArgs = append(allArgs, pb.specificArgs...)
- globPathName := pb.name
- // Glob path for soong build would be separated per product target
- if pb.name == soongBuildTag {
- globPathName = getGlobPathName(pb.config)
- }
+ globPathName := getGlobPathNameFromPrimaryBuilderFactory(config, pb)
allArgs = append(allArgs,
"--globListDir", globPathName,
"--globFile", pb.config.NamedGlobFile(globPathName))
@@ -234,8 +239,11 @@
}
allArgs = append(allArgs, "Android.bp")
+ globfiles := bootstrap.GlobFileListFiles(bootstrap.GlobDirectory(config.SoongOutDir(), globPathName))
+
return bootstrap.PrimaryBuilderInvocation{
Inputs: []string{"Android.bp"},
+ Implicits: globfiles,
Outputs: []string{pb.output},
Args: allArgs,
Description: pb.description,
@@ -376,17 +384,10 @@
if debuggedInvocations[pbf.name] {
pbf.debugPort = delvePort
}
- pbi := pbf.primaryBuilderInvocation()
+ pbi := pbf.primaryBuilderInvocation(config)
invocations = append(invocations, pbi)
}
- // The glob .ninja files are subninja'd. However, they are generated during
- // the build itself so we write an empty file if the file does not exist yet
- // so that the subninja doesn't fail on clean builds
- for _, globFile := range bootstrapGlobFileList(config) {
- writeEmptyFile(ctx, globFile)
- }
-
blueprintArgs := bootstrap.Args{
ModuleListFile: filepath.Join(config.FileListDir(), "Android.bp.list"),
OutFile: shared.JoinPath(config.SoongOutDir(), "bootstrap.ninja"),
@@ -408,6 +409,28 @@
primaryBuilderInvocations: invocations,
}
+ // The glob ninja files are generated during the main build phase. However, the
+ // primary buildifer invocation depends on all of its glob files, even before
+ // it's been run. Generate a "empty" glob ninja file on the first run,
+ // so that the files can be there to satisfy the dependency.
+ for _, pb := range pbfs {
+ globPathName := getGlobPathNameFromPrimaryBuilderFactory(config, pb)
+ globNinjaFile := config.NamedGlobFile(globPathName)
+ if _, err := os.Stat(globNinjaFile); os.IsNotExist(err) {
+ err := bootstrap.WriteBuildGlobsNinjaFile(&bootstrap.GlobSingleton{
+ GlobLister: func() pathtools.MultipleGlobResults { return nil },
+ GlobFile: globNinjaFile,
+ GlobDir: bootstrap.GlobDirectory(config.SoongOutDir(), globPathName),
+ SrcDir: ".",
+ }, blueprintConfig)
+ if err != nil {
+ ctx.Fatal(err)
+ }
+ } else if err != nil {
+ ctx.Fatal(err)
+ }
+ }
+
// since `bootstrap.ninja` is regenerated unconditionally, we ignore the deps, i.e. little
// reason to write a `bootstrap.ninja.d` file
_, err := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)