Loading cmd/soong_build/main.go +91 −93 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import ( "time" "android/soong/shared" "github.com/google/blueprint/bootstrap" "android/soong/android" Loading Loading @@ -65,16 +64,10 @@ func newNameResolver(config android.Config) *android.NameResolver { return android.NewNameResolver(exportFilter) } // bazelConversionRequested checks that the user is intending to convert // Blueprint to Bazel BUILD files. func bazelConversionRequested(configuration android.Config) bool { return configuration.IsEnvTrue("GENERATE_BAZEL_FILES") } func newContext(configuration android.Config) *android.Context { func newContext(configuration android.Config, prepareBuildActions bool) *android.Context { ctx := android.NewContext(configuration) ctx.Register() if !shouldPrepareBuildActions(configuration) { if !prepareBuildActions { configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions) } ctx.SetNameInterface(newNameResolver(configuration)) Loading @@ -91,49 +84,12 @@ func newConfig(srcDir string) android.Config { return configuration } func main() { flag.Parse() shared.ReexecWithDelveMaybe(delveListen, delvePath) android.InitSandbox(topDir) android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available")) usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used") // The top-level Blueprints file is passed as the first argument. srcDir := filepath.Dir(flag.Arg(0)) var ctx *android.Context configuration := newConfig(srcDir) extraNinjaDeps := []string{ configuration.ProductVariablesFileName, shared.JoinPath(outDir, "soong.environment.used"), } if configuration.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" { configuration.SetAllowMissingDependencies() } // These two are here so that we restart a non-debugged soong_build when the // user sets SOONG_DELVE the first time. configuration.Getenv("SOONG_DELVE") configuration.Getenv("SOONG_DELVE_PATH") if shared.IsDebugging() { // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is // enabled even if it completed successfully. extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve")) } bazelConversionRequested := bazelConversionRequested(configuration) if bazelConversionRequested { // Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files // before everything else. runBp2Build(srcDir, configuration, extraNinjaDeps) } else if configuration.BazelContext.BazelEnabled() { // Bazel-enabled mode. Soong runs in two passes. // First pass: Analyze the build tree, but only store all bazel commands // needed to correctly evaluate the tree in the second pass. // TODO(cparsons): Don't output any ninja file, as the second pass will overwrite // the incorrect results from the first pass, and file I/O is expensive. firstCtx := newContext(configuration) func runMixedModeBuild(configuration android.Config, firstCtx *android.Context, extraNinjaDeps []string) { configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja) bootstrap.Main(firstCtx.Context, configuration, false, extraNinjaDeps...) // Invoke bazel commands and save results for second pass. Loading @@ -147,16 +103,12 @@ func main() { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) } ctx = newContext(secondPassConfig) bootstrap.Main(ctx.Context, secondPassConfig, false, extraNinjaDeps...) } else { ctx = newContext(configuration) bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) secondCtx := newContext(secondPassConfig, true) bootstrap.Main(secondCtx.Context, secondPassConfig, false, extraNinjaDeps...) } // Convert the Soong module graph into Bazel BUILD files. if !bazelConversionRequested && bazelQueryViewDir != "" { // Run the code-generation phase to convert BazelTargetModules to BUILD files. func runQueryView(configuration android.Config, ctx *android.Context) { codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView) absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir) if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil { Loading @@ -165,16 +117,16 @@ func main() { } } if !bazelConversionRequested && docFile != "" { func runSoongDocs(configuration android.Config, extraNinjaDeps []string) { ctx := newContext(configuration, false) bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) if err := writeDocs(ctx, configuration, docFile); err != nil { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) } } // TODO(ccross): make this a command line argument. Requires plumbing through blueprint // to affect the command line of the primary builder. if !bazelConversionRequested && shouldPrepareBuildActions(configuration) { func writeMetrics(configuration android.Config) { metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb") err := android.WriteMetrics(configuration, metricsFile) if err != nil { Loading @@ -183,11 +135,74 @@ func main() { } } if docFile == "" { // Let's not overwrite the used variables file when generating // documentation writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration) func doChosenActivity(configuration android.Config, extraNinjaDeps []string) { bazelConversionRequested := configuration.IsEnvTrue("GENERATE_BAZEL_FILES") mixedModeBuild := configuration.BazelContext.BazelEnabled() generateQueryView := bazelQueryViewDir != "" if bazelConversionRequested { // Run the alternate pipeline of bp2build mutators and singleton to convert // Blueprint to BUILD files before everything else. runBp2Build(configuration, extraNinjaDeps) return } ctx := newContext(configuration, !generateQueryView) if mixedModeBuild { runMixedModeBuild(configuration, ctx, extraNinjaDeps) } else { bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) } // Convert the Soong module graph into Bazel BUILD files. if generateQueryView { runQueryView(configuration, ctx) return } writeMetrics(configuration) } func main() { flag.Parse() shared.ReexecWithDelveMaybe(delveListen, delvePath) android.InitSandbox(topDir) android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available")) usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used") // The top-level Blueprints file is passed as the first argument. srcDir := filepath.Dir(flag.Arg(0)) configuration := newConfig(srcDir) extraNinjaDeps := []string{ configuration.ProductVariablesFileName, shared.JoinPath(outDir, "soong.environment.used"), } if configuration.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" { configuration.SetAllowMissingDependencies() } // These two are here so that we restart a non-debugged soong_build when the // user sets SOONG_DELVE the first time. configuration.Getenv("SOONG_DELVE") configuration.Getenv("SOONG_DELVE_PATH") if shared.IsDebugging() { // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is // enabled even if it completed successfully. extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve")) } if docFile != "" { // We don't write an used variables file when generating documentation // because that is done from within the actual builds as a Ninja action and // thus it would overwrite the actual used variables file so this is // special-cased. runSoongDocs(configuration, extraNinjaDeps) return } doChosenActivity(configuration, extraNinjaDeps) writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration) } func writeUsedVariablesFile(path string, configuration android.Config) { Loading Loading @@ -218,7 +233,7 @@ func writeUsedVariablesFile(path string, configuration android.Config) { // Run Soong in the bp2build mode. This creates a standalone context that registers // an alternate pipeline of mutators and singletons specifically for generating // Bazel BUILD files instead of Ninja files. func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []string) { func runBp2Build(configuration android.Config, extraNinjaDeps []string) { // Register an alternate set of singletons and mutators for bazel // conversion for Bazel conversion. bp2buildCtx := android.NewContext(configuration) Loading @@ -233,7 +248,7 @@ func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []s // configurations or variables, since those will generate different BUILD // files based on how the user has configured their tree. bp2buildCtx.SetModuleListFile(bootstrap.CmdlineModuleListFile()) modulePaths, err := bp2buildCtx.ListModulePaths(srcDir) modulePaths, err := bp2buildCtx.ListModulePaths(configuration.SrcDir()) if err != nil { panic(err) } Loading Loading @@ -283,20 +298,3 @@ func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []s []byte(fmt.Sprintf("%s: \\\n %s\n", ninjaFileName, extraNinjaDepsString)), 0666) } // shouldPrepareBuildActions reads configuration and flags if build actions // should be generated. func shouldPrepareBuildActions(configuration android.Config) bool { // Generating Soong docs if docFile != "" { return false } // Generating a directory for Soong query (queryview) if bazelQueryViewDir != "" { return false } // Generating a directory for converted Bazel BUILD files return !bazelConversionRequested(configuration) } Loading
cmd/soong_build/main.go +91 −93 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import ( "time" "android/soong/shared" "github.com/google/blueprint/bootstrap" "android/soong/android" Loading Loading @@ -65,16 +64,10 @@ func newNameResolver(config android.Config) *android.NameResolver { return android.NewNameResolver(exportFilter) } // bazelConversionRequested checks that the user is intending to convert // Blueprint to Bazel BUILD files. func bazelConversionRequested(configuration android.Config) bool { return configuration.IsEnvTrue("GENERATE_BAZEL_FILES") } func newContext(configuration android.Config) *android.Context { func newContext(configuration android.Config, prepareBuildActions bool) *android.Context { ctx := android.NewContext(configuration) ctx.Register() if !shouldPrepareBuildActions(configuration) { if !prepareBuildActions { configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions) } ctx.SetNameInterface(newNameResolver(configuration)) Loading @@ -91,49 +84,12 @@ func newConfig(srcDir string) android.Config { return configuration } func main() { flag.Parse() shared.ReexecWithDelveMaybe(delveListen, delvePath) android.InitSandbox(topDir) android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available")) usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used") // The top-level Blueprints file is passed as the first argument. srcDir := filepath.Dir(flag.Arg(0)) var ctx *android.Context configuration := newConfig(srcDir) extraNinjaDeps := []string{ configuration.ProductVariablesFileName, shared.JoinPath(outDir, "soong.environment.used"), } if configuration.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" { configuration.SetAllowMissingDependencies() } // These two are here so that we restart a non-debugged soong_build when the // user sets SOONG_DELVE the first time. configuration.Getenv("SOONG_DELVE") configuration.Getenv("SOONG_DELVE_PATH") if shared.IsDebugging() { // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is // enabled even if it completed successfully. extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve")) } bazelConversionRequested := bazelConversionRequested(configuration) if bazelConversionRequested { // Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files // before everything else. runBp2Build(srcDir, configuration, extraNinjaDeps) } else if configuration.BazelContext.BazelEnabled() { // Bazel-enabled mode. Soong runs in two passes. // First pass: Analyze the build tree, but only store all bazel commands // needed to correctly evaluate the tree in the second pass. // TODO(cparsons): Don't output any ninja file, as the second pass will overwrite // the incorrect results from the first pass, and file I/O is expensive. firstCtx := newContext(configuration) func runMixedModeBuild(configuration android.Config, firstCtx *android.Context, extraNinjaDeps []string) { configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja) bootstrap.Main(firstCtx.Context, configuration, false, extraNinjaDeps...) // Invoke bazel commands and save results for second pass. Loading @@ -147,16 +103,12 @@ func main() { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) } ctx = newContext(secondPassConfig) bootstrap.Main(ctx.Context, secondPassConfig, false, extraNinjaDeps...) } else { ctx = newContext(configuration) bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) secondCtx := newContext(secondPassConfig, true) bootstrap.Main(secondCtx.Context, secondPassConfig, false, extraNinjaDeps...) } // Convert the Soong module graph into Bazel BUILD files. if !bazelConversionRequested && bazelQueryViewDir != "" { // Run the code-generation phase to convert BazelTargetModules to BUILD files. func runQueryView(configuration android.Config, ctx *android.Context) { codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView) absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir) if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil { Loading @@ -165,16 +117,16 @@ func main() { } } if !bazelConversionRequested && docFile != "" { func runSoongDocs(configuration android.Config, extraNinjaDeps []string) { ctx := newContext(configuration, false) bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) if err := writeDocs(ctx, configuration, docFile); err != nil { fmt.Fprintf(os.Stderr, "%s", err) os.Exit(1) } } // TODO(ccross): make this a command line argument. Requires plumbing through blueprint // to affect the command line of the primary builder. if !bazelConversionRequested && shouldPrepareBuildActions(configuration) { func writeMetrics(configuration android.Config) { metricsFile := filepath.Join(bootstrap.CmdlineBuildDir(), "soong_build_metrics.pb") err := android.WriteMetrics(configuration, metricsFile) if err != nil { Loading @@ -183,11 +135,74 @@ func main() { } } if docFile == "" { // Let's not overwrite the used variables file when generating // documentation writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration) func doChosenActivity(configuration android.Config, extraNinjaDeps []string) { bazelConversionRequested := configuration.IsEnvTrue("GENERATE_BAZEL_FILES") mixedModeBuild := configuration.BazelContext.BazelEnabled() generateQueryView := bazelQueryViewDir != "" if bazelConversionRequested { // Run the alternate pipeline of bp2build mutators and singleton to convert // Blueprint to BUILD files before everything else. runBp2Build(configuration, extraNinjaDeps) return } ctx := newContext(configuration, !generateQueryView) if mixedModeBuild { runMixedModeBuild(configuration, ctx, extraNinjaDeps) } else { bootstrap.Main(ctx.Context, configuration, false, extraNinjaDeps...) } // Convert the Soong module graph into Bazel BUILD files. if generateQueryView { runQueryView(configuration, ctx) return } writeMetrics(configuration) } func main() { flag.Parse() shared.ReexecWithDelveMaybe(delveListen, delvePath) android.InitSandbox(topDir) android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available")) usedVariablesFile := shared.JoinPath(outDir, "soong.environment.used") // The top-level Blueprints file is passed as the first argument. srcDir := filepath.Dir(flag.Arg(0)) configuration := newConfig(srcDir) extraNinjaDeps := []string{ configuration.ProductVariablesFileName, shared.JoinPath(outDir, "soong.environment.used"), } if configuration.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" { configuration.SetAllowMissingDependencies() } // These two are here so that we restart a non-debugged soong_build when the // user sets SOONG_DELVE the first time. configuration.Getenv("SOONG_DELVE") configuration.Getenv("SOONG_DELVE_PATH") if shared.IsDebugging() { // Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is // enabled even if it completed successfully. extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve")) } if docFile != "" { // We don't write an used variables file when generating documentation // because that is done from within the actual builds as a Ninja action and // thus it would overwrite the actual used variables file so this is // special-cased. runSoongDocs(configuration, extraNinjaDeps) return } doChosenActivity(configuration, extraNinjaDeps) writeUsedVariablesFile(shared.JoinPath(topDir, usedVariablesFile), configuration) } func writeUsedVariablesFile(path string, configuration android.Config) { Loading Loading @@ -218,7 +233,7 @@ func writeUsedVariablesFile(path string, configuration android.Config) { // Run Soong in the bp2build mode. This creates a standalone context that registers // an alternate pipeline of mutators and singletons specifically for generating // Bazel BUILD files instead of Ninja files. func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []string) { func runBp2Build(configuration android.Config, extraNinjaDeps []string) { // Register an alternate set of singletons and mutators for bazel // conversion for Bazel conversion. bp2buildCtx := android.NewContext(configuration) Loading @@ -233,7 +248,7 @@ func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []s // configurations or variables, since those will generate different BUILD // files based on how the user has configured their tree. bp2buildCtx.SetModuleListFile(bootstrap.CmdlineModuleListFile()) modulePaths, err := bp2buildCtx.ListModulePaths(srcDir) modulePaths, err := bp2buildCtx.ListModulePaths(configuration.SrcDir()) if err != nil { panic(err) } Loading Loading @@ -283,20 +298,3 @@ func runBp2Build(srcDir string, configuration android.Config, extraNinjaDeps []s []byte(fmt.Sprintf("%s: \\\n %s\n", ninjaFileName, extraNinjaDepsString)), 0666) } // shouldPrepareBuildActions reads configuration and flags if build actions // should be generated. func shouldPrepareBuildActions(configuration android.Config) bool { // Generating Soong docs if docFile != "" { return false } // Generating a directory for Soong query (queryview) if bazelQueryViewDir != "" { return false } // Generating a directory for converted Bazel BUILD files return !bazelConversionRequested(configuration) }