1*333d2b36SAndroid Build Coastguard Worker// Copyright 2017 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage main 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "context" 19*333d2b36SAndroid Build Coastguard Worker "flag" 20*333d2b36SAndroid Build Coastguard Worker "fmt" 21*333d2b36SAndroid Build Coastguard Worker "os" 22*333d2b36SAndroid Build Coastguard Worker "path/filepath" 23*333d2b36SAndroid Build Coastguard Worker "strconv" 24*333d2b36SAndroid Build Coastguard Worker "strings" 25*333d2b36SAndroid Build Coastguard Worker "syscall" 26*333d2b36SAndroid Build Coastguard Worker "time" 27*333d2b36SAndroid Build Coastguard Worker 28*333d2b36SAndroid Build Coastguard Worker "android/soong/shared" 29*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/build" 30*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/logger" 31*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/metrics" 32*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/signal" 33*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/status" 34*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/terminal" 35*333d2b36SAndroid Build Coastguard Worker "android/soong/ui/tracer" 36*333d2b36SAndroid Build Coastguard Worker) 37*333d2b36SAndroid Build Coastguard Worker 38*333d2b36SAndroid Build Coastguard Worker// A command represents an operation to be executed in the soong build 39*333d2b36SAndroid Build Coastguard Worker// system. 40*333d2b36SAndroid Build Coastguard Workertype command struct { 41*333d2b36SAndroid Build Coastguard Worker // The flag name (must have double dashes). 42*333d2b36SAndroid Build Coastguard Worker flag string 43*333d2b36SAndroid Build Coastguard Worker 44*333d2b36SAndroid Build Coastguard Worker // Description for the flag (to display when running help). 45*333d2b36SAndroid Build Coastguard Worker description string 46*333d2b36SAndroid Build Coastguard Worker 47*333d2b36SAndroid Build Coastguard Worker // Stream the build status output into the simple terminal mode. 48*333d2b36SAndroid Build Coastguard Worker simpleOutput bool 49*333d2b36SAndroid Build Coastguard Worker 50*333d2b36SAndroid Build Coastguard Worker // Sets a prefix string to use for filenames of log files. 51*333d2b36SAndroid Build Coastguard Worker logsPrefix string 52*333d2b36SAndroid Build Coastguard Worker 53*333d2b36SAndroid Build Coastguard Worker // Creates the build configuration based on the args and build context. 54*333d2b36SAndroid Build Coastguard Worker config func(ctx build.Context, args ...string) build.Config 55*333d2b36SAndroid Build Coastguard Worker 56*333d2b36SAndroid Build Coastguard Worker // Returns what type of IO redirection this Command requires. 57*333d2b36SAndroid Build Coastguard Worker stdio func() terminal.StdioInterface 58*333d2b36SAndroid Build Coastguard Worker 59*333d2b36SAndroid Build Coastguard Worker // run the command 60*333d2b36SAndroid Build Coastguard Worker run func(ctx build.Context, config build.Config, args []string) 61*333d2b36SAndroid Build Coastguard Worker} 62*333d2b36SAndroid Build Coastguard Worker 63*333d2b36SAndroid Build Coastguard Worker// list of supported commands (flags) supported by soong ui 64*333d2b36SAndroid Build Coastguard Workervar commands = []command{ 65*333d2b36SAndroid Build Coastguard Worker { 66*333d2b36SAndroid Build Coastguard Worker flag: "--make-mode", 67*333d2b36SAndroid Build Coastguard Worker description: "build the modules by the target name (i.e. soong_docs)", 68*333d2b36SAndroid Build Coastguard Worker config: build.NewConfig, 69*333d2b36SAndroid Build Coastguard Worker stdio: stdio, 70*333d2b36SAndroid Build Coastguard Worker run: runMake, 71*333d2b36SAndroid Build Coastguard Worker }, { 72*333d2b36SAndroid Build Coastguard Worker flag: "--dumpvar-mode", 73*333d2b36SAndroid Build Coastguard Worker description: "print the value of the legacy make variable VAR to stdout", 74*333d2b36SAndroid Build Coastguard Worker simpleOutput: true, 75*333d2b36SAndroid Build Coastguard Worker logsPrefix: "dumpvars-", 76*333d2b36SAndroid Build Coastguard Worker config: dumpVarConfig, 77*333d2b36SAndroid Build Coastguard Worker stdio: customStdio, 78*333d2b36SAndroid Build Coastguard Worker run: dumpVar, 79*333d2b36SAndroid Build Coastguard Worker }, { 80*333d2b36SAndroid Build Coastguard Worker flag: "--dumpvars-mode", 81*333d2b36SAndroid Build Coastguard Worker description: "dump the values of one or more legacy make variables, in shell syntax", 82*333d2b36SAndroid Build Coastguard Worker simpleOutput: true, 83*333d2b36SAndroid Build Coastguard Worker logsPrefix: "dumpvars-", 84*333d2b36SAndroid Build Coastguard Worker config: dumpVarConfig, 85*333d2b36SAndroid Build Coastguard Worker stdio: customStdio, 86*333d2b36SAndroid Build Coastguard Worker run: dumpVars, 87*333d2b36SAndroid Build Coastguard Worker }, { 88*333d2b36SAndroid Build Coastguard Worker flag: "--build-mode", 89*333d2b36SAndroid Build Coastguard Worker description: "build modules based on the specified build action", 90*333d2b36SAndroid Build Coastguard Worker config: buildActionConfig, 91*333d2b36SAndroid Build Coastguard Worker stdio: stdio, 92*333d2b36SAndroid Build Coastguard Worker run: runMake, 93*333d2b36SAndroid Build Coastguard Worker }, 94*333d2b36SAndroid Build Coastguard Worker} 95*333d2b36SAndroid Build Coastguard Worker 96*333d2b36SAndroid Build Coastguard Worker// indexList returns the index of first found s. -1 is return if s is not 97*333d2b36SAndroid Build Coastguard Worker// found. 98*333d2b36SAndroid Build Coastguard Workerfunc indexList(s string, list []string) int { 99*333d2b36SAndroid Build Coastguard Worker for i, l := range list { 100*333d2b36SAndroid Build Coastguard Worker if l == s { 101*333d2b36SAndroid Build Coastguard Worker return i 102*333d2b36SAndroid Build Coastguard Worker } 103*333d2b36SAndroid Build Coastguard Worker } 104*333d2b36SAndroid Build Coastguard Worker return -1 105*333d2b36SAndroid Build Coastguard Worker} 106*333d2b36SAndroid Build Coastguard Worker 107*333d2b36SAndroid Build Coastguard Worker// inList returns true if one or more of s is in the list. 108*333d2b36SAndroid Build Coastguard Workerfunc inList(s string, list []string) bool { 109*333d2b36SAndroid Build Coastguard Worker return indexList(s, list) != -1 110*333d2b36SAndroid Build Coastguard Worker} 111*333d2b36SAndroid Build Coastguard Worker 112*333d2b36SAndroid Build Coastguard Workerfunc deleteStaleMetrics(metricsFilePathSlice []string) error { 113*333d2b36SAndroid Build Coastguard Worker for _, metricsFilePath := range metricsFilePathSlice { 114*333d2b36SAndroid Build Coastguard Worker if err := os.Remove(metricsFilePath); err != nil && !os.IsNotExist(err) { 115*333d2b36SAndroid Build Coastguard Worker return fmt.Errorf("Failed to remove %s\nError message: %w", metricsFilePath, err) 116*333d2b36SAndroid Build Coastguard Worker } 117*333d2b36SAndroid Build Coastguard Worker } 118*333d2b36SAndroid Build Coastguard Worker return nil 119*333d2b36SAndroid Build Coastguard Worker} 120*333d2b36SAndroid Build Coastguard Worker 121*333d2b36SAndroid Build Coastguard Worker// Main execution of soong_ui. The command format is as follows: 122*333d2b36SAndroid Build Coastguard Worker// 123*333d2b36SAndroid Build Coastguard Worker// soong_ui <command> [<arg 1> <arg 2> ... <arg n>] 124*333d2b36SAndroid Build Coastguard Worker// 125*333d2b36SAndroid Build Coastguard Worker// Command is the type of soong_ui execution. Only one type of 126*333d2b36SAndroid Build Coastguard Worker// execution is specified. The args are specific to the command. 127*333d2b36SAndroid Build Coastguard Workerfunc main() { 128*333d2b36SAndroid Build Coastguard Worker shared.ReexecWithDelveMaybe(os.Getenv("SOONG_UI_DELVE"), shared.ResolveDelveBinary()) 129*333d2b36SAndroid Build Coastguard Worker 130*333d2b36SAndroid Build Coastguard Worker buildStarted := time.Now() 131*333d2b36SAndroid Build Coastguard Worker 132*333d2b36SAndroid Build Coastguard Worker c, args, err := getCommand(os.Args) 133*333d2b36SAndroid Build Coastguard Worker if err != nil { 134*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(os.Stderr, "Error parsing `soong` args: %s.\n", err) 135*333d2b36SAndroid Build Coastguard Worker os.Exit(1) 136*333d2b36SAndroid Build Coastguard Worker } 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Worker // Create a terminal output that mimics Ninja's. 139*333d2b36SAndroid Build Coastguard Worker output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput, 140*333d2b36SAndroid Build Coastguard Worker build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"), 141*333d2b36SAndroid Build Coastguard Worker build.OsEnvironment().IsEnvTrue("SOONG_UI_ANSI_OUTPUT")) 142*333d2b36SAndroid Build Coastguard Worker 143*333d2b36SAndroid Build Coastguard Worker // Create and start a new metric record. 144*333d2b36SAndroid Build Coastguard Worker met := metrics.New() 145*333d2b36SAndroid Build Coastguard Worker met.SetBuildDateTime(buildStarted) 146*333d2b36SAndroid Build Coastguard Worker met.SetBuildCommand(os.Args) 147*333d2b36SAndroid Build Coastguard Worker 148*333d2b36SAndroid Build Coastguard Worker // Attach a new logger instance to the terminal output. 149*333d2b36SAndroid Build Coastguard Worker log := logger.NewWithMetrics(output, met) 150*333d2b36SAndroid Build Coastguard Worker defer log.Cleanup() 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Worker // Create a context to simplify the program termination process. 153*333d2b36SAndroid Build Coastguard Worker ctx, cancel := context.WithCancel(context.Background()) 154*333d2b36SAndroid Build Coastguard Worker defer cancel() 155*333d2b36SAndroid Build Coastguard Worker 156*333d2b36SAndroid Build Coastguard Worker // Create a new trace file writer, making it log events to the log instance. 157*333d2b36SAndroid Build Coastguard Worker trace := tracer.New(log) 158*333d2b36SAndroid Build Coastguard Worker 159*333d2b36SAndroid Build Coastguard Worker // Create a new Status instance, which manages action counts and event output channels. 160*333d2b36SAndroid Build Coastguard Worker stat := &status.Status{} 161*333d2b36SAndroid Build Coastguard Worker 162*333d2b36SAndroid Build Coastguard Worker // Hook up the terminal output and tracer to Status. 163*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(output) 164*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(trace.StatusTracer()) 165*333d2b36SAndroid Build Coastguard Worker 166*333d2b36SAndroid Build Coastguard Worker // Set up a cleanup procedure in case the normal termination process doesn't work. 167*333d2b36SAndroid Build Coastguard Worker signal.SetupSignals(log, cancel, func() { 168*333d2b36SAndroid Build Coastguard Worker trace.Close() 169*333d2b36SAndroid Build Coastguard Worker log.Cleanup() 170*333d2b36SAndroid Build Coastguard Worker stat.Finish() 171*333d2b36SAndroid Build Coastguard Worker }) 172*333d2b36SAndroid Build Coastguard Worker criticalPath := status.NewCriticalPath() 173*333d2b36SAndroid Build Coastguard Worker buildCtx := build.Context{ContextImpl: &build.ContextImpl{ 174*333d2b36SAndroid Build Coastguard Worker Context: ctx, 175*333d2b36SAndroid Build Coastguard Worker Logger: log, 176*333d2b36SAndroid Build Coastguard Worker Metrics: met, 177*333d2b36SAndroid Build Coastguard Worker Tracer: trace, 178*333d2b36SAndroid Build Coastguard Worker Writer: output, 179*333d2b36SAndroid Build Coastguard Worker Status: stat, 180*333d2b36SAndroid Build Coastguard Worker CriticalPath: criticalPath, 181*333d2b36SAndroid Build Coastguard Worker }} 182*333d2b36SAndroid Build Coastguard Worker 183*333d2b36SAndroid Build Coastguard Worker freshConfig := func() build.Config { 184*333d2b36SAndroid Build Coastguard Worker config := c.config(buildCtx, args...) 185*333d2b36SAndroid Build Coastguard Worker config.SetLogsPrefix(c.logsPrefix) 186*333d2b36SAndroid Build Coastguard Worker return config 187*333d2b36SAndroid Build Coastguard Worker } 188*333d2b36SAndroid Build Coastguard Worker config := freshConfig() 189*333d2b36SAndroid Build Coastguard Worker logsDir := config.LogsDir() 190*333d2b36SAndroid Build Coastguard Worker buildStarted = config.BuildStartedTimeOrDefault(buildStarted) 191*333d2b36SAndroid Build Coastguard Worker 192*333d2b36SAndroid Build Coastguard Worker buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error") 193*333d2b36SAndroid Build Coastguard Worker soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics") 194*333d2b36SAndroid Build Coastguard Worker rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb") 195*333d2b36SAndroid Build Coastguard Worker soongBuildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_build_metrics.pb") 196*333d2b36SAndroid Build Coastguard Worker buildTraceFile := filepath.Join(logsDir, c.logsPrefix+"build.trace.gz") 197*333d2b36SAndroid Build Coastguard Worker 198*333d2b36SAndroid Build Coastguard Worker metricsFiles := []string{ 199*333d2b36SAndroid Build Coastguard Worker buildErrorFile, // build error strings 200*333d2b36SAndroid Build Coastguard Worker rbeMetricsFile, // high level metrics related to remote build execution. 201*333d2b36SAndroid Build Coastguard Worker soongMetricsFile, // high level metrics related to this build system. 202*333d2b36SAndroid Build Coastguard Worker soongBuildMetricsFile, // high level metrics related to soong build 203*333d2b36SAndroid Build Coastguard Worker buildTraceFile, 204*333d2b36SAndroid Build Coastguard Worker } 205*333d2b36SAndroid Build Coastguard Worker 206*333d2b36SAndroid Build Coastguard Worker defer func() { 207*333d2b36SAndroid Build Coastguard Worker stat.Finish() 208*333d2b36SAndroid Build Coastguard Worker criticalPath.WriteToMetrics(met) 209*333d2b36SAndroid Build Coastguard Worker met.Dump(soongMetricsFile) 210*333d2b36SAndroid Build Coastguard Worker if !config.SkipMetricsUpload() { 211*333d2b36SAndroid Build Coastguard Worker build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, metricsFiles...) 212*333d2b36SAndroid Build Coastguard Worker } 213*333d2b36SAndroid Build Coastguard Worker }() 214*333d2b36SAndroid Build Coastguard Worker 215*333d2b36SAndroid Build Coastguard Worker // This has to come after the metrics uploading function, so that 216*333d2b36SAndroid Build Coastguard Worker // build.trace.gz is closed and ready for upload. 217*333d2b36SAndroid Build Coastguard Worker defer trace.Close() 218*333d2b36SAndroid Build Coastguard Worker 219*333d2b36SAndroid Build Coastguard Worker os.MkdirAll(logsDir, 0777) 220*333d2b36SAndroid Build Coastguard Worker 221*333d2b36SAndroid Build Coastguard Worker log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log")) 222*333d2b36SAndroid Build Coastguard Worker 223*333d2b36SAndroid Build Coastguard Worker trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace")) 224*333d2b36SAndroid Build Coastguard Worker 225*333d2b36SAndroid Build Coastguard Worker log.Verbose("Command Line: ") 226*333d2b36SAndroid Build Coastguard Worker for i, arg := range os.Args { 227*333d2b36SAndroid Build Coastguard Worker log.Verbosef(" [%d] %s", i, arg) 228*333d2b36SAndroid Build Coastguard Worker } 229*333d2b36SAndroid Build Coastguard Worker 230*333d2b36SAndroid Build Coastguard Worker // We need to call preProductConfigSetup before we can do product config, which is how we get 231*333d2b36SAndroid Build Coastguard Worker // PRODUCT_CONFIG_RELEASE_MAPS set for the final product config for the build. 232*333d2b36SAndroid Build Coastguard Worker // When product config uses a declarative language, we won't need to rerun product config. 233*333d2b36SAndroid Build Coastguard Worker preProductConfigSetup(buildCtx, config) 234*333d2b36SAndroid Build Coastguard Worker if build.SetProductReleaseConfigMaps(buildCtx, config) { 235*333d2b36SAndroid Build Coastguard Worker log.Verbose("Product release config maps found\n") 236*333d2b36SAndroid Build Coastguard Worker config = freshConfig() 237*333d2b36SAndroid Build Coastguard Worker } 238*333d2b36SAndroid Build Coastguard Worker 239*333d2b36SAndroid Build Coastguard Worker c.run(buildCtx, config, args) 240*333d2b36SAndroid Build Coastguard Worker} 241*333d2b36SAndroid Build Coastguard Worker 242*333d2b36SAndroid Build Coastguard Worker// This function must not modify config, since product config may cause us to recreate the config, 243*333d2b36SAndroid Build Coastguard Worker// and we won't call this function a second time. 244*333d2b36SAndroid Build Coastguard Workerfunc preProductConfigSetup(buildCtx build.Context, config build.Config) { 245*333d2b36SAndroid Build Coastguard Worker log := buildCtx.ContextImpl.Logger 246*333d2b36SAndroid Build Coastguard Worker logsPrefix := config.GetLogsPrefix() 247*333d2b36SAndroid Build Coastguard Worker build.SetupOutDir(buildCtx, config) 248*333d2b36SAndroid Build Coastguard Worker logsDir := config.LogsDir() 249*333d2b36SAndroid Build Coastguard Worker 250*333d2b36SAndroid Build Coastguard Worker // Common list of metric file definition. 251*333d2b36SAndroid Build Coastguard Worker buildErrorFile := filepath.Join(logsDir, logsPrefix+"build_error") 252*333d2b36SAndroid Build Coastguard Worker rbeMetricsFile := filepath.Join(logsDir, logsPrefix+"rbe_metrics.pb") 253*333d2b36SAndroid Build Coastguard Worker soongMetricsFile := filepath.Join(logsDir, logsPrefix+"soong_metrics") 254*333d2b36SAndroid Build Coastguard Worker soongBuildMetricsFile := filepath.Join(logsDir, logsPrefix+"soong_build_metrics.pb") 255*333d2b36SAndroid Build Coastguard Worker 256*333d2b36SAndroid Build Coastguard Worker //Delete the stale metrics files 257*333d2b36SAndroid Build Coastguard Worker staleFileSlice := []string{buildErrorFile, rbeMetricsFile, soongMetricsFile, soongBuildMetricsFile} 258*333d2b36SAndroid Build Coastguard Worker if err := deleteStaleMetrics(staleFileSlice); err != nil { 259*333d2b36SAndroid Build Coastguard Worker log.Fatalln(err) 260*333d2b36SAndroid Build Coastguard Worker } 261*333d2b36SAndroid Build Coastguard Worker 262*333d2b36SAndroid Build Coastguard Worker build.PrintOutDirWarning(buildCtx, config) 263*333d2b36SAndroid Build Coastguard Worker 264*333d2b36SAndroid Build Coastguard Worker stat := buildCtx.Status 265*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, logsPrefix+"verbose.log"))) 266*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, logsPrefix+"error.log"))) 267*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile)) 268*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(status.NewCriticalPathLogger(log, buildCtx.CriticalPath)) 269*333d2b36SAndroid Build Coastguard Worker stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, logsPrefix+"build_progress.pb"))) 270*333d2b36SAndroid Build Coastguard Worker 271*333d2b36SAndroid Build Coastguard Worker buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024)) 272*333d2b36SAndroid Build Coastguard Worker buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v", 273*333d2b36SAndroid Build Coastguard Worker config.Parallel(), config.RemoteParallel(), config.HighmemParallel()) 274*333d2b36SAndroid Build Coastguard Worker 275*333d2b36SAndroid Build Coastguard Worker setMaxFiles(buildCtx) 276*333d2b36SAndroid Build Coastguard Worker 277*333d2b36SAndroid Build Coastguard Worker defer build.CheckProdCreds(buildCtx, config) 278*333d2b36SAndroid Build Coastguard Worker 279*333d2b36SAndroid Build Coastguard Worker // Read the time at the starting point. 280*333d2b36SAndroid Build Coastguard Worker if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok { 281*333d2b36SAndroid Build Coastguard Worker // soong_ui.bash uses the date command's %N (nanosec) flag when getting the start time, 282*333d2b36SAndroid Build Coastguard Worker // which Darwin doesn't support. Check if it was executed properly before parsing the value. 283*333d2b36SAndroid Build Coastguard Worker if !strings.HasSuffix(start, "N") { 284*333d2b36SAndroid Build Coastguard Worker if start_time, err := strconv.ParseUint(start, 10, 64); err == nil { 285*333d2b36SAndroid Build Coastguard Worker log.Verbosef("Took %dms to start up.", 286*333d2b36SAndroid Build Coastguard Worker time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds()) 287*333d2b36SAndroid Build Coastguard Worker buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano())) 288*333d2b36SAndroid Build Coastguard Worker } 289*333d2b36SAndroid Build Coastguard Worker } 290*333d2b36SAndroid Build Coastguard Worker 291*333d2b36SAndroid Build Coastguard Worker if executable, err := os.Executable(); err == nil { 292*333d2b36SAndroid Build Coastguard Worker buildCtx.ContextImpl.Tracer.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace")) 293*333d2b36SAndroid Build Coastguard Worker } 294*333d2b36SAndroid Build Coastguard Worker } 295*333d2b36SAndroid Build Coastguard Worker 296*333d2b36SAndroid Build Coastguard Worker // Create a source finder. 297*333d2b36SAndroid Build Coastguard Worker f := build.NewSourceFinder(buildCtx, config) 298*333d2b36SAndroid Build Coastguard Worker defer f.Shutdown() 299*333d2b36SAndroid Build Coastguard Worker build.FindSources(buildCtx, config, f) 300*333d2b36SAndroid Build Coastguard Worker} 301*333d2b36SAndroid Build Coastguard Worker 302*333d2b36SAndroid Build Coastguard Workerfunc dumpVar(ctx build.Context, config build.Config, args []string) { 303*333d2b36SAndroid Build Coastguard Worker flags := flag.NewFlagSet("dumpvar", flag.ExitOnError) 304*333d2b36SAndroid Build Coastguard Worker flags.SetOutput(ctx.Writer) 305*333d2b36SAndroid Build Coastguard Worker 306*333d2b36SAndroid Build Coastguard Worker flags.Usage = func() { 307*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0]) 308*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout") 309*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 310*333d2b36SAndroid Build Coastguard Worker 311*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner") 312*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "from the beginning of the build.") 313*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 314*333d2b36SAndroid Build Coastguard Worker flags.PrintDefaults() 315*333d2b36SAndroid Build Coastguard Worker } 316*333d2b36SAndroid Build Coastguard Worker abs := flags.Bool("abs", false, "Print the absolute path of the value") 317*333d2b36SAndroid Build Coastguard Worker flags.Parse(args) 318*333d2b36SAndroid Build Coastguard Worker 319*333d2b36SAndroid Build Coastguard Worker if flags.NArg() != 1 { 320*333d2b36SAndroid Build Coastguard Worker flags.Usage() 321*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Invalid usage") 322*333d2b36SAndroid Build Coastguard Worker } 323*333d2b36SAndroid Build Coastguard Worker 324*333d2b36SAndroid Build Coastguard Worker varName := flags.Arg(0) 325*333d2b36SAndroid Build Coastguard Worker if varName == "report_config" { 326*333d2b36SAndroid Build Coastguard Worker varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars) 327*333d2b36SAndroid Build Coastguard Worker if err != nil { 328*333d2b36SAndroid Build Coastguard Worker ctx.Fatal(err) 329*333d2b36SAndroid Build Coastguard Worker } 330*333d2b36SAndroid Build Coastguard Worker 331*333d2b36SAndroid Build Coastguard Worker fmt.Println(build.Banner(varData)) 332*333d2b36SAndroid Build Coastguard Worker } else { 333*333d2b36SAndroid Build Coastguard Worker varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName}) 334*333d2b36SAndroid Build Coastguard Worker if err != nil { 335*333d2b36SAndroid Build Coastguard Worker ctx.Fatal(err) 336*333d2b36SAndroid Build Coastguard Worker } 337*333d2b36SAndroid Build Coastguard Worker 338*333d2b36SAndroid Build Coastguard Worker if *abs { 339*333d2b36SAndroid Build Coastguard Worker var res []string 340*333d2b36SAndroid Build Coastguard Worker for _, path := range strings.Fields(varData[varName]) { 341*333d2b36SAndroid Build Coastguard Worker if abs, err := filepath.Abs(path); err == nil { 342*333d2b36SAndroid Build Coastguard Worker res = append(res, abs) 343*333d2b36SAndroid Build Coastguard Worker } else { 344*333d2b36SAndroid Build Coastguard Worker ctx.Fatalln("Failed to get absolute path of", path, err) 345*333d2b36SAndroid Build Coastguard Worker } 346*333d2b36SAndroid Build Coastguard Worker } 347*333d2b36SAndroid Build Coastguard Worker fmt.Println(strings.Join(res, " ")) 348*333d2b36SAndroid Build Coastguard Worker } else { 349*333d2b36SAndroid Build Coastguard Worker fmt.Println(varData[varName]) 350*333d2b36SAndroid Build Coastguard Worker } 351*333d2b36SAndroid Build Coastguard Worker } 352*333d2b36SAndroid Build Coastguard Worker} 353*333d2b36SAndroid Build Coastguard Worker 354*333d2b36SAndroid Build Coastguard Workerfunc dumpVars(ctx build.Context, config build.Config, args []string) { 355*333d2b36SAndroid Build Coastguard Worker 356*333d2b36SAndroid Build Coastguard Worker flags := flag.NewFlagSet("dumpvars", flag.ExitOnError) 357*333d2b36SAndroid Build Coastguard Worker flags.SetOutput(ctx.Writer) 358*333d2b36SAndroid Build Coastguard Worker 359*333d2b36SAndroid Build Coastguard Worker flags.Usage = func() { 360*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0]) 361*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in") 362*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to") 363*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "set corresponding shell variables.") 364*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 365*333d2b36SAndroid Build Coastguard Worker 366*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the") 367*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.") 368*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 369*333d2b36SAndroid Build Coastguard Worker flags.PrintDefaults() 370*333d2b36SAndroid Build Coastguard Worker } 371*333d2b36SAndroid Build Coastguard Worker 372*333d2b36SAndroid Build Coastguard Worker varsStr := flags.String("vars", "", "Space-separated list of variables to dump") 373*333d2b36SAndroid Build Coastguard Worker absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)") 374*333d2b36SAndroid Build Coastguard Worker 375*333d2b36SAndroid Build Coastguard Worker varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping") 376*333d2b36SAndroid Build Coastguard Worker absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping") 377*333d2b36SAndroid Build Coastguard Worker 378*333d2b36SAndroid Build Coastguard Worker flags.Parse(args) 379*333d2b36SAndroid Build Coastguard Worker 380*333d2b36SAndroid Build Coastguard Worker if flags.NArg() != 0 { 381*333d2b36SAndroid Build Coastguard Worker flags.Usage() 382*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Invalid usage") 383*333d2b36SAndroid Build Coastguard Worker } 384*333d2b36SAndroid Build Coastguard Worker 385*333d2b36SAndroid Build Coastguard Worker vars := strings.Fields(*varsStr) 386*333d2b36SAndroid Build Coastguard Worker absVars := strings.Fields(*absVarsStr) 387*333d2b36SAndroid Build Coastguard Worker 388*333d2b36SAndroid Build Coastguard Worker allVars := append([]string{}, vars...) 389*333d2b36SAndroid Build Coastguard Worker allVars = append(allVars, absVars...) 390*333d2b36SAndroid Build Coastguard Worker 391*333d2b36SAndroid Build Coastguard Worker if i := indexList("report_config", allVars); i != -1 { 392*333d2b36SAndroid Build Coastguard Worker allVars = append(allVars[:i], allVars[i+1:]...) 393*333d2b36SAndroid Build Coastguard Worker allVars = append(allVars, build.BannerVars...) 394*333d2b36SAndroid Build Coastguard Worker } 395*333d2b36SAndroid Build Coastguard Worker 396*333d2b36SAndroid Build Coastguard Worker if len(allVars) == 0 { 397*333d2b36SAndroid Build Coastguard Worker return 398*333d2b36SAndroid Build Coastguard Worker } 399*333d2b36SAndroid Build Coastguard Worker 400*333d2b36SAndroid Build Coastguard Worker varData, err := build.DumpMakeVars(ctx, config, nil, allVars) 401*333d2b36SAndroid Build Coastguard Worker if err != nil { 402*333d2b36SAndroid Build Coastguard Worker ctx.Fatal(err) 403*333d2b36SAndroid Build Coastguard Worker } 404*333d2b36SAndroid Build Coastguard Worker 405*333d2b36SAndroid Build Coastguard Worker for _, name := range vars { 406*333d2b36SAndroid Build Coastguard Worker if name == "report_config" { 407*333d2b36SAndroid Build Coastguard Worker fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData)) 408*333d2b36SAndroid Build Coastguard Worker } else { 409*333d2b36SAndroid Build Coastguard Worker fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name]) 410*333d2b36SAndroid Build Coastguard Worker } 411*333d2b36SAndroid Build Coastguard Worker } 412*333d2b36SAndroid Build Coastguard Worker for _, name := range absVars { 413*333d2b36SAndroid Build Coastguard Worker var res []string 414*333d2b36SAndroid Build Coastguard Worker for _, path := range strings.Fields(varData[name]) { 415*333d2b36SAndroid Build Coastguard Worker abs, err := filepath.Abs(path) 416*333d2b36SAndroid Build Coastguard Worker if err != nil { 417*333d2b36SAndroid Build Coastguard Worker ctx.Fatalln("Failed to get absolute path of", path, err) 418*333d2b36SAndroid Build Coastguard Worker } 419*333d2b36SAndroid Build Coastguard Worker res = append(res, abs) 420*333d2b36SAndroid Build Coastguard Worker } 421*333d2b36SAndroid Build Coastguard Worker fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " ")) 422*333d2b36SAndroid Build Coastguard Worker } 423*333d2b36SAndroid Build Coastguard Worker} 424*333d2b36SAndroid Build Coastguard Worker 425*333d2b36SAndroid Build Coastguard Workerfunc stdio() terminal.StdioInterface { 426*333d2b36SAndroid Build Coastguard Worker return terminal.StdioImpl{} 427*333d2b36SAndroid Build Coastguard Worker} 428*333d2b36SAndroid Build Coastguard Worker 429*333d2b36SAndroid Build Coastguard Worker// dumpvar and dumpvars use stdout to output variable values, so use stderr instead of stdout when 430*333d2b36SAndroid Build Coastguard Worker// reporting events to keep stdout clean from noise. 431*333d2b36SAndroid Build Coastguard Workerfunc customStdio() terminal.StdioInterface { 432*333d2b36SAndroid Build Coastguard Worker return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr) 433*333d2b36SAndroid Build Coastguard Worker} 434*333d2b36SAndroid Build Coastguard Worker 435*333d2b36SAndroid Build Coastguard Worker// dumpVarConfig does not require any arguments to be parsed by the NewConfig. 436*333d2b36SAndroid Build Coastguard Workerfunc dumpVarConfig(ctx build.Context, args ...string) build.Config { 437*333d2b36SAndroid Build Coastguard Worker return build.NewConfig(ctx) 438*333d2b36SAndroid Build Coastguard Worker} 439*333d2b36SAndroid Build Coastguard Worker 440*333d2b36SAndroid Build Coastguard Workerfunc buildActionConfig(ctx build.Context, args ...string) build.Config { 441*333d2b36SAndroid Build Coastguard Worker flags := flag.NewFlagSet("build-mode", flag.ContinueOnError) 442*333d2b36SAndroid Build Coastguard Worker flags.SetOutput(ctx.Writer) 443*333d2b36SAndroid Build Coastguard Worker 444*333d2b36SAndroid Build Coastguard Worker flags.Usage = func() { 445*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0]) 446*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build") 447*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to") 448*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for") 449*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.") 450*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(ctx.Writer, "") 451*333d2b36SAndroid Build Coastguard Worker flags.PrintDefaults() 452*333d2b36SAndroid Build Coastguard Worker } 453*333d2b36SAndroid Build Coastguard Worker 454*333d2b36SAndroid Build Coastguard Worker buildActionFlags := []struct { 455*333d2b36SAndroid Build Coastguard Worker name string 456*333d2b36SAndroid Build Coastguard Worker description string 457*333d2b36SAndroid Build Coastguard Worker action build.BuildAction 458*333d2b36SAndroid Build Coastguard Worker set bool 459*333d2b36SAndroid Build Coastguard Worker }{{ 460*333d2b36SAndroid Build Coastguard Worker name: "all-modules", 461*333d2b36SAndroid Build Coastguard Worker description: "Build action: build from the top of the source tree.", 462*333d2b36SAndroid Build Coastguard Worker action: build.BUILD_MODULES, 463*333d2b36SAndroid Build Coastguard Worker }, { 464*333d2b36SAndroid Build Coastguard Worker // This is redirecting to mma build command behaviour. Once it has soaked for a 465*333d2b36SAndroid Build Coastguard Worker // while, the build command is deleted from here once it has been removed from the 466*333d2b36SAndroid Build Coastguard Worker // envsetup.sh. 467*333d2b36SAndroid Build Coastguard Worker name: "modules-in-a-dir-no-deps", 468*333d2b36SAndroid Build Coastguard Worker description: "Build action: builds all of the modules in the current directory without their dependencies.", 469*333d2b36SAndroid Build Coastguard Worker action: build.BUILD_MODULES_IN_A_DIRECTORY, 470*333d2b36SAndroid Build Coastguard Worker }, { 471*333d2b36SAndroid Build Coastguard Worker // This is redirecting to mmma build command behaviour. Once it has soaked for a 472*333d2b36SAndroid Build Coastguard Worker // while, the build command is deleted from here once it has been removed from the 473*333d2b36SAndroid Build Coastguard Worker // envsetup.sh. 474*333d2b36SAndroid Build Coastguard Worker name: "modules-in-dirs-no-deps", 475*333d2b36SAndroid Build Coastguard Worker description: "Build action: builds all of the modules in the supplied directories without their dependencies.", 476*333d2b36SAndroid Build Coastguard Worker action: build.BUILD_MODULES_IN_DIRECTORIES, 477*333d2b36SAndroid Build Coastguard Worker }, { 478*333d2b36SAndroid Build Coastguard Worker name: "modules-in-a-dir", 479*333d2b36SAndroid Build Coastguard Worker description: "Build action: builds all of the modules in the current directory and their dependencies.", 480*333d2b36SAndroid Build Coastguard Worker action: build.BUILD_MODULES_IN_A_DIRECTORY, 481*333d2b36SAndroid Build Coastguard Worker }, { 482*333d2b36SAndroid Build Coastguard Worker name: "modules-in-dirs", 483*333d2b36SAndroid Build Coastguard Worker description: "Build action: builds all of the modules in the supplied directories and their dependencies.", 484*333d2b36SAndroid Build Coastguard Worker action: build.BUILD_MODULES_IN_DIRECTORIES, 485*333d2b36SAndroid Build Coastguard Worker }} 486*333d2b36SAndroid Build Coastguard Worker for i, flag := range buildActionFlags { 487*333d2b36SAndroid Build Coastguard Worker flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description) 488*333d2b36SAndroid Build Coastguard Worker } 489*333d2b36SAndroid Build Coastguard Worker dir := flags.String("dir", "", "Directory of the executed build command.") 490*333d2b36SAndroid Build Coastguard Worker 491*333d2b36SAndroid Build Coastguard Worker // Only interested in the first two args which defines the build action and the directory. 492*333d2b36SAndroid Build Coastguard Worker // The remaining arguments are passed down to the config. 493*333d2b36SAndroid Build Coastguard Worker const numBuildActionFlags = 2 494*333d2b36SAndroid Build Coastguard Worker if len(args) < numBuildActionFlags { 495*333d2b36SAndroid Build Coastguard Worker flags.Usage() 496*333d2b36SAndroid Build Coastguard Worker ctx.Fatalln("Improper build action arguments: too few arguments") 497*333d2b36SAndroid Build Coastguard Worker } 498*333d2b36SAndroid Build Coastguard Worker parseError := flags.Parse(args[0:numBuildActionFlags]) 499*333d2b36SAndroid Build Coastguard Worker 500*333d2b36SAndroid Build Coastguard Worker // The next block of code is to validate that exactly one build action is set and the dir flag 501*333d2b36SAndroid Build Coastguard Worker // is specified. 502*333d2b36SAndroid Build Coastguard Worker buildActionFound := false 503*333d2b36SAndroid Build Coastguard Worker var buildAction build.BuildAction 504*333d2b36SAndroid Build Coastguard Worker for _, f := range buildActionFlags { 505*333d2b36SAndroid Build Coastguard Worker if f.set { 506*333d2b36SAndroid Build Coastguard Worker if buildActionFound { 507*333d2b36SAndroid Build Coastguard Worker if parseError == nil { 508*333d2b36SAndroid Build Coastguard Worker //otherwise Parse() already called Usage() 509*333d2b36SAndroid Build Coastguard Worker flags.Usage() 510*333d2b36SAndroid Build Coastguard Worker } 511*333d2b36SAndroid Build Coastguard Worker ctx.Fatalf("Build action already specified, omit: --%s\n", f.name) 512*333d2b36SAndroid Build Coastguard Worker } 513*333d2b36SAndroid Build Coastguard Worker buildActionFound = true 514*333d2b36SAndroid Build Coastguard Worker buildAction = f.action 515*333d2b36SAndroid Build Coastguard Worker } 516*333d2b36SAndroid Build Coastguard Worker } 517*333d2b36SAndroid Build Coastguard Worker if !buildActionFound { 518*333d2b36SAndroid Build Coastguard Worker if parseError == nil { 519*333d2b36SAndroid Build Coastguard Worker //otherwise Parse() already called Usage() 520*333d2b36SAndroid Build Coastguard Worker flags.Usage() 521*333d2b36SAndroid Build Coastguard Worker } 522*333d2b36SAndroid Build Coastguard Worker ctx.Fatalln("Build action not defined.") 523*333d2b36SAndroid Build Coastguard Worker } 524*333d2b36SAndroid Build Coastguard Worker if *dir == "" { 525*333d2b36SAndroid Build Coastguard Worker ctx.Fatalln("-dir not specified.") 526*333d2b36SAndroid Build Coastguard Worker } 527*333d2b36SAndroid Build Coastguard Worker 528*333d2b36SAndroid Build Coastguard Worker // Remove the build action flags from the args as they are not recognized by the config. 529*333d2b36SAndroid Build Coastguard Worker args = args[numBuildActionFlags:] 530*333d2b36SAndroid Build Coastguard Worker return build.NewBuildActionConfig(buildAction, *dir, ctx, args...) 531*333d2b36SAndroid Build Coastguard Worker} 532*333d2b36SAndroid Build Coastguard Worker 533*333d2b36SAndroid Build Coastguard Workerfunc runMake(ctx build.Context, config build.Config, _ []string) { 534*333d2b36SAndroid Build Coastguard Worker logsDir := config.LogsDir() 535*333d2b36SAndroid Build Coastguard Worker if config.IsVerbose() { 536*333d2b36SAndroid Build Coastguard Worker writer := ctx.Writer 537*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.") 538*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:") 539*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "!") 540*333d2b36SAndroid Build Coastguard Worker fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir) 541*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "!") 542*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files") 543*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "") 544*333d2b36SAndroid Build Coastguard Worker ctx.Fatal("Invalid argument") 545*333d2b36SAndroid Build Coastguard Worker } 546*333d2b36SAndroid Build Coastguard Worker 547*333d2b36SAndroid Build Coastguard Worker if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok { 548*333d2b36SAndroid Build Coastguard Worker writer := ctx.Writer 549*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.") 550*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "!") 551*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.") 552*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "!") 553*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...") 554*333d2b36SAndroid Build Coastguard Worker fmt.Fprintln(writer, "") 555*333d2b36SAndroid Build Coastguard Worker ctx.Fatal("Invalid environment") 556*333d2b36SAndroid Build Coastguard Worker } 557*333d2b36SAndroid Build Coastguard Worker 558*333d2b36SAndroid Build Coastguard Worker build.Build(ctx, config) 559*333d2b36SAndroid Build Coastguard Worker} 560*333d2b36SAndroid Build Coastguard Worker 561*333d2b36SAndroid Build Coastguard Worker// getCommand finds the appropriate command based on args[1] flag. args[0] 562*333d2b36SAndroid Build Coastguard Worker// is the soong_ui filename. 563*333d2b36SAndroid Build Coastguard Workerfunc getCommand(args []string) (*command, []string, error) { 564*333d2b36SAndroid Build Coastguard Worker listFlags := func() []string { 565*333d2b36SAndroid Build Coastguard Worker flags := make([]string, len(commands)) 566*333d2b36SAndroid Build Coastguard Worker for i, c := range commands { 567*333d2b36SAndroid Build Coastguard Worker flags[i] = c.flag 568*333d2b36SAndroid Build Coastguard Worker } 569*333d2b36SAndroid Build Coastguard Worker return flags 570*333d2b36SAndroid Build Coastguard Worker } 571*333d2b36SAndroid Build Coastguard Worker 572*333d2b36SAndroid Build Coastguard Worker if len(args) < 2 { 573*333d2b36SAndroid Build Coastguard Worker return nil, nil, fmt.Errorf("Too few arguments: %q\nUse one of these: %q", args, listFlags()) 574*333d2b36SAndroid Build Coastguard Worker } 575*333d2b36SAndroid Build Coastguard Worker 576*333d2b36SAndroid Build Coastguard Worker for _, c := range commands { 577*333d2b36SAndroid Build Coastguard Worker if c.flag == args[1] { 578*333d2b36SAndroid Build Coastguard Worker return &c, args[2:], nil 579*333d2b36SAndroid Build Coastguard Worker } 580*333d2b36SAndroid Build Coastguard Worker } 581*333d2b36SAndroid Build Coastguard Worker return nil, nil, fmt.Errorf("Command not found: %q\nDid you mean one of these: %q", args[1], listFlags()) 582*333d2b36SAndroid Build Coastguard Worker} 583*333d2b36SAndroid Build Coastguard Worker 584*333d2b36SAndroid Build Coastguard Workerfunc setMaxFiles(ctx build.Context) { 585*333d2b36SAndroid Build Coastguard Worker var limits syscall.Rlimit 586*333d2b36SAndroid Build Coastguard Worker 587*333d2b36SAndroid Build Coastguard Worker err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limits) 588*333d2b36SAndroid Build Coastguard Worker if err != nil { 589*333d2b36SAndroid Build Coastguard Worker ctx.Println("Failed to get file limit:", err) 590*333d2b36SAndroid Build Coastguard Worker return 591*333d2b36SAndroid Build Coastguard Worker } 592*333d2b36SAndroid Build Coastguard Worker 593*333d2b36SAndroid Build Coastguard Worker ctx.Verbosef("Current file limits: %d soft, %d hard", limits.Cur, limits.Max) 594*333d2b36SAndroid Build Coastguard Worker 595*333d2b36SAndroid Build Coastguard Worker // Go 1.21 modifies the file limit but restores the original when 596*333d2b36SAndroid Build Coastguard Worker // execing subprocesses if it hasn't be overridden. Call Setrlimit 597*333d2b36SAndroid Build Coastguard Worker // here even if it doesn't appear to be necessary so that the 598*333d2b36SAndroid Build Coastguard Worker // syscall package considers it set. 599*333d2b36SAndroid Build Coastguard Worker 600*333d2b36SAndroid Build Coastguard Worker limits.Cur = limits.Max 601*333d2b36SAndroid Build Coastguard Worker err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limits) 602*333d2b36SAndroid Build Coastguard Worker if err != nil { 603*333d2b36SAndroid Build Coastguard Worker ctx.Println("Failed to increase file limit:", err) 604*333d2b36SAndroid Build Coastguard Worker } 605*333d2b36SAndroid Build Coastguard Worker} 606