xref: /aosp_15_r20/build/soong/cmd/soong_ui/main.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
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