blob: 532e879e275d76e9d9f8e6feb2f61cf905e50ffc [file] [log] [blame]
Dan Willemsen1e704462016-08-21 15:17:17 -07001// Copyright 2017 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18 "context"
Dan Willemsen051133b2017-07-14 11:29:29 -070019 "flag"
20 "fmt"
Dan Willemsen1e704462016-08-21 15:17:17 -070021 "os"
22 "path/filepath"
23 "strconv"
24 "strings"
25 "time"
26
27 "android/soong/ui/build"
28 "android/soong/ui/logger"
Nan Zhang17f27672018-12-12 16:01:49 -080029 "android/soong/ui/metrics"
Dan Willemsenb82471a2018-05-17 16:37:09 -070030 "android/soong/ui/status"
31 "android/soong/ui/terminal"
Dan Willemsend9f6fa22016-08-21 15:17:17 -070032 "android/soong/ui/tracer"
Dan Willemsen1e704462016-08-21 15:17:17 -070033)
34
Patrice Arrudaa5c25422019-04-09 18:49:49 -070035// A command represents an operation to be executed in the soong build
36// system.
37type command struct {
Patrice Arrudaf445ba12020-07-28 17:49:01 +000038 // The flag name (must have double dashes).
Patrice Arrudaa5c25422019-04-09 18:49:49 -070039 flag string
40
Patrice Arrudaf445ba12020-07-28 17:49:01 +000041 // Description for the flag (to display when running help).
Patrice Arrudaa5c25422019-04-09 18:49:49 -070042 description string
43
Patrice Arrudaf445ba12020-07-28 17:49:01 +000044 // Stream the build status output into the simple terminal mode.
45 simpleOutput bool
Colin Crossc0b9f6b2019-09-23 12:44:54 -070046
47 // Sets a prefix string to use for filenames of log files.
48 logsPrefix string
49
Patrice Arrudaa5c25422019-04-09 18:49:49 -070050 // Creates the build configuration based on the args and build context.
51 config func(ctx build.Context, args ...string) build.Config
52
53 // Returns what type of IO redirection this Command requires.
54 stdio func() terminal.StdioInterface
55
56 // run the command
57 run func(ctx build.Context, config build.Config, args []string, logsDir string)
58}
59
60const makeModeFlagName = "--make-mode"
61
62// list of supported commands (flags) supported by soong ui
63var commands []command = []command{
64 {
65 flag: makeModeFlagName,
66 description: "build the modules by the target name (i.e. soong_docs)",
67 config: func(ctx build.Context, args ...string) build.Config {
68 return build.NewConfig(ctx, args...)
69 },
Patrice Arrudab7b22822019-05-21 17:46:23 -070070 stdio: stdio,
71 run: make,
Patrice Arrudaa5c25422019-04-09 18:49:49 -070072 }, {
Patrice Arrudaf445ba12020-07-28 17:49:01 +000073 flag: "--dumpvar-mode",
74 description: "print the value of the legacy make variable VAR to stdout",
75 simpleOutput: true,
76 logsPrefix: "dumpvars-",
77 config: dumpVarConfig,
78 stdio: customStdio,
79 run: dumpVar,
Patrice Arrudaa5c25422019-04-09 18:49:49 -070080 }, {
Patrice Arrudaf445ba12020-07-28 17:49:01 +000081 flag: "--dumpvars-mode",
82 description: "dump the values of one or more legacy make variables, in shell syntax",
83 simpleOutput: true,
84 logsPrefix: "dumpvars-",
85 config: dumpVarConfig,
86 stdio: customStdio,
87 run: dumpVars,
Patrice Arrudab7b22822019-05-21 17:46:23 -070088 }, {
89 flag: "--build-mode",
90 description: "build modules based on the specified build action",
91 config: buildActionConfig,
92 stdio: stdio,
93 run: make,
Patrice Arrudaa5c25422019-04-09 18:49:49 -070094 },
95}
96
97// indexList returns the index of first found s. -1 is return if s is not
98// found.
Dan Willemsen1e704462016-08-21 15:17:17 -070099func indexList(s string, list []string) int {
100 for i, l := range list {
101 if l == s {
102 return i
103 }
104 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700105 return -1
106}
107
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700108// inList returns true if one or more of s is in the list.
Dan Willemsen1e704462016-08-21 15:17:17 -0700109func inList(s string, list []string) bool {
110 return indexList(s, list) != -1
111}
112
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700113// Main execution of soong_ui. The command format is as follows:
114//
115// soong_ui <command> [<arg 1> <arg 2> ... <arg n>]
116//
117// Command is the type of soong_ui execution. Only one type of
118// execution is specified. The args are specific to the command.
Dan Willemsen1e704462016-08-21 15:17:17 -0700119func main() {
Patrice Arruda73c790f2020-07-13 23:01:18 +0000120 buildStarted := time.Now()
Patrice Arruda219eef32020-06-01 17:29:30 +0000121
Liz Kammer0e7993e2020-10-15 11:07:13 -0700122 c, args, err := getCommand(os.Args)
123 if err != nil {
124 fmt.Fprintf(os.Stderr, "Error parsing `soong` args: %s.\n", err)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700125 os.Exit(1)
Dan Willemsenc35b3812018-07-16 19:59:10 -0700126 }
127
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800128 // Create a terminal output that mimics Ninja's.
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000129 output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
Colin Crosse0df1a32019-06-09 19:40:08 -0700130 build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700131
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800132 // Attach a new logger instance to the terminal output.
Colin Crosse0df1a32019-06-09 19:40:08 -0700133 log := logger.New(output)
Dan Willemsen1e704462016-08-21 15:17:17 -0700134 defer log.Cleanup()
135
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800136 // Create a context to simplify the program termination process.
Dan Willemsen1e704462016-08-21 15:17:17 -0700137 ctx, cancel := context.WithCancel(context.Background())
138 defer cancel()
139
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800140 // Create a new trace file writer, making it log events to the log instance.
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700141 trace := tracer.New(log)
142 defer trace.Close()
Dan Willemsen1e704462016-08-21 15:17:17 -0700143
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800144 // Create and start a new metric record.
Nan Zhang17f27672018-12-12 16:01:49 -0800145 met := metrics.New()
Patrice Arruda73c790f2020-07-13 23:01:18 +0000146 met.SetBuildDateTime(buildStarted)
Patrice Arrudae92c30d2020-10-29 11:01:32 -0700147 met.SetBuildCommand(os.Args)
Nan Zhang17f27672018-12-12 16:01:49 -0800148
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800149 // Create a new Status instance, which manages action counts and event output channels.
Dan Willemsenb82471a2018-05-17 16:37:09 -0700150 stat := &status.Status{}
151 defer stat.Finish()
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800152 // Hook up the terminal output and tracer to Status.
Colin Crosse0df1a32019-06-09 19:40:08 -0700153 stat.AddOutput(output)
Dan Willemsenb82471a2018-05-17 16:37:09 -0700154 stat.AddOutput(trace.StatusTracer())
155
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800156 // Set up a cleanup procedure in case the normal termination process doesn't work.
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700157 build.SetupSignals(log, cancel, func() {
158 trace.Close()
159 log.Cleanup()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700160 stat.Finish()
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700161 })
162
Dan Willemsen59339a22018-07-22 21:18:45 -0700163 buildCtx := build.Context{ContextImpl: &build.ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -0700164 Context: ctx,
165 Logger: log,
Nan Zhang17f27672018-12-12 16:01:49 -0800166 Metrics: met,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700167 Tracer: trace,
Colin Crosse0df1a32019-06-09 19:40:08 -0700168 Writer: output,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700169 Status: stat,
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700170 }}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700171
172 config := c.config(buildCtx, args...)
Dan Willemsen1e704462016-08-21 15:17:17 -0700173
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700174 build.SetupOutDir(buildCtx, config)
Dan Willemsen8a073a82017-02-04 17:30:44 -0800175
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800176 // Set up files to be outputted in the log directory.
Patrice Arruda83842d72020-12-08 19:42:08 +0000177 logsDir := config.LogsDir()
Dan Willemsen1e704462016-08-21 15:17:17 -0700178
Patrice Arruda40564022020-12-10 00:42:58 +0000179 // Common list of metric file definition.
Patrice Arruda219eef32020-06-01 17:29:30 +0000180 buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
181 rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
182 soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
Patrice Arruda40564022020-12-10 00:42:58 +0000183
Kousik Kumara0a44a82020-10-08 02:33:29 -0400184 build.PrintOutDirWarning(buildCtx, config)
Patrice Arruda219eef32020-06-01 17:29:30 +0000185
Dan Willemsenb82471a2018-05-17 16:37:09 -0700186 os.MkdirAll(logsDir, 0777)
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700187 log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
188 trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
189 stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
190 stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
Patrice Arruda219eef32020-06-01 17:29:30 +0000191 stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
Colin Cross7b624532019-06-21 15:08:30 -0700192 stat.AddOutput(status.NewCriticalPath(log))
Patrice Arruda74b43992020-03-11 08:21:05 -0700193 stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700194
Colin Cross8b8bec32019-11-15 13:18:43 -0800195 buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
196 buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
197 config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
198
Patrice Arruda40564022020-12-10 00:42:58 +0000199 {
200 // The order of the function calls is important. The last defer function call
201 // is the first one that is executed to save the rbe metrics to a protobuf
202 // file. The soong metrics file is then next. Bazel profiles are written
203 // before the uploadMetrics is invoked. The written files are then uploaded
204 // if the uploading of the metrics is enabled.
205 files := []string{
206 buildErrorFile, // build error strings
207 rbeMetricsFile, // high level metrics related to remote build execution.
208 soongMetricsFile, // high level metrics related to this build system.
209 config.BazelMetricsDir(), // directory that contains a set of bazel metrics.
210 }
211 defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, files...)
212 defer met.Dump(soongMetricsFile)
213 defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
214 }
Nan Zhangd50f53b2019-01-07 20:26:51 -0800215
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800216 // Read the time at the starting point.
Dan Willemsen1e704462016-08-21 15:17:17 -0700217 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800218 // soong_ui.bash uses the date command's %N (nanosec) flag when getting the start time,
219 // which Darwin doesn't support. Check if it was executed properly before parsing the value.
Dan Willemsen1e704462016-08-21 15:17:17 -0700220 if !strings.HasSuffix(start, "N") {
221 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
222 log.Verbosef("Took %dms to start up.",
223 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800224 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700225 }
226 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700227
228 if executable, err := os.Executable(); err == nil {
229 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
230 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700231 }
232
Dan Willemsen6b783c82019-03-08 11:42:28 -0800233 // Fix up the source tree due to a repo bug where it doesn't remove
234 // linkfiles that have been removed
235 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
236 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
237
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800238 // Create a source finder.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700239 f := build.NewSourceFinder(buildCtx, config)
240 defer f.Shutdown()
241 build.FindSources(buildCtx, config, f)
242
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700243 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700244}
245
Dan Willemsen6b783c82019-03-08 11:42:28 -0800246func fixBadDanglingLink(ctx build.Context, name string) {
247 _, err := os.Lstat(name)
248 if err != nil {
249 return
250 }
251 _, err = os.Stat(name)
252 if os.IsNotExist(err) {
253 err = os.Remove(name)
254 if err != nil {
255 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
256 }
257 }
258}
259
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700260func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700261 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
262 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700263 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
264 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
265 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700266
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700267 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
268 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
269 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700270 flags.PrintDefaults()
271 }
272 abs := flags.Bool("abs", false, "Print the absolute path of the value")
273 flags.Parse(args)
274
275 if flags.NArg() != 1 {
276 flags.Usage()
277 os.Exit(1)
278 }
279
280 varName := flags.Arg(0)
281 if varName == "report_config" {
282 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
283 if err != nil {
284 ctx.Fatal(err)
285 }
286
287 fmt.Println(build.Banner(varData))
288 } else {
289 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
290 if err != nil {
291 ctx.Fatal(err)
292 }
293
294 if *abs {
295 var res []string
296 for _, path := range strings.Fields(varData[varName]) {
297 if abs, err := filepath.Abs(path); err == nil {
298 res = append(res, abs)
299 } else {
300 ctx.Fatalln("Failed to get absolute path of", path, err)
301 }
302 }
303 fmt.Println(strings.Join(res, " "))
304 } else {
305 fmt.Println(varData[varName])
306 }
307 }
308}
309
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700310func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700311 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
312 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700313 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
314 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
315 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
316 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
317 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700318
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700319 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
320 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
321 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700322 flags.PrintDefaults()
323 }
324
325 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
326 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
327
328 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
329 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
330
331 flags.Parse(args)
332
333 if flags.NArg() != 0 {
334 flags.Usage()
335 os.Exit(1)
336 }
337
338 vars := strings.Fields(*varsStr)
339 absVars := strings.Fields(*absVarsStr)
340
341 allVars := append([]string{}, vars...)
342 allVars = append(allVars, absVars...)
343
344 if i := indexList("report_config", allVars); i != -1 {
345 allVars = append(allVars[:i], allVars[i+1:]...)
346 allVars = append(allVars, build.BannerVars...)
347 }
348
349 if len(allVars) == 0 {
350 return
351 }
352
353 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
354 if err != nil {
355 ctx.Fatal(err)
356 }
357
358 for _, name := range vars {
359 if name == "report_config" {
360 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
361 } else {
362 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
363 }
364 }
365 for _, name := range absVars {
366 var res []string
367 for _, path := range strings.Fields(varData[name]) {
368 abs, err := filepath.Abs(path)
369 if err != nil {
370 ctx.Fatalln("Failed to get absolute path of", path, err)
371 }
372 res = append(res, abs)
373 }
374 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
375 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700376}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700377
Patrice Arrudab7b22822019-05-21 17:46:23 -0700378func stdio() terminal.StdioInterface {
379 return terminal.StdioImpl{}
380}
381
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800382// dumpvar and dumpvars use stdout to output variable values, so use stderr instead of stdout when
383// reporting events to keep stdout clean from noise.
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700384func customStdio() terminal.StdioInterface {
385 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
386}
387
388// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
389func dumpVarConfig(ctx build.Context, args ...string) build.Config {
390 return build.NewConfig(ctx)
391}
392
Patrice Arrudab7b22822019-05-21 17:46:23 -0700393func buildActionConfig(ctx build.Context, args ...string) build.Config {
394 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
395 flags.Usage = func() {
396 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
397 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
398 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
399 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
400 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
401 fmt.Fprintln(ctx.Writer, "")
402 flags.PrintDefaults()
403 }
404
405 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700406 name string
407 description string
408 action build.BuildAction
409 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700410 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700411 name: "all-modules",
412 description: "Build action: build from the top of the source tree.",
413 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700414 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700415 // This is redirecting to mma build command behaviour. Once it has soaked for a
416 // while, the build command is deleted from here once it has been removed from the
417 // envsetup.sh.
418 name: "modules-in-a-dir-no-deps",
419 description: "Build action: builds all of the modules in the current directory without their dependencies.",
420 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700421 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700422 // This is redirecting to mmma build command behaviour. Once it has soaked for a
423 // while, the build command is deleted from here once it has been removed from the
424 // envsetup.sh.
425 name: "modules-in-dirs-no-deps",
426 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
427 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700428 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700429 name: "modules-in-a-dir",
430 description: "Build action: builds all of the modules in the current directory and their dependencies.",
431 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700432 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700433 name: "modules-in-dirs",
434 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
435 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700436 }}
437 for i, flag := range buildActionFlags {
438 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
439 }
440 dir := flags.String("dir", "", "Directory of the executed build command.")
441
442 // Only interested in the first two args which defines the build action and the directory.
443 // The remaining arguments are passed down to the config.
444 const numBuildActionFlags = 2
445 if len(args) < numBuildActionFlags {
446 flags.Usage()
447 ctx.Fatalln("Improper build action arguments.")
448 }
449 flags.Parse(args[0:numBuildActionFlags])
450
451 // The next block of code is to validate that exactly one build action is set and the dir flag
452 // is specified.
453 buildActionCount := 0
454 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700455 for _, flag := range buildActionFlags {
456 if flag.set {
457 buildActionCount++
458 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700459 }
460 }
461 if buildActionCount != 1 {
462 ctx.Fatalln("Build action not defined.")
463 }
464 if *dir == "" {
465 ctx.Fatalln("-dir not specified.")
466 }
467
468 // Remove the build action flags from the args as they are not recognized by the config.
469 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700470 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700471}
472
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700473func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
474 if config.IsVerbose() {
475 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700476 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
477 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
478 fmt.Fprintln(writer, "!")
479 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
480 fmt.Fprintln(writer, "!")
481 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
482 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700483 select {
484 case <-time.After(5 * time.Second):
485 case <-ctx.Done():
486 return
487 }
488 }
489
490 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
491 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700492 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700493 fmt.Fprintln(writer, "!")
494 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
495 fmt.Fprintln(writer, "!")
496 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
497 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700498 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700499 }
500
Patrice Arruda0c1c4562020-11-11 13:01:25 -0800501 toBuild := build.BuildAll
502 if config.UseBazel() {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000503 toBuild = build.BuildAllWithBazel
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000504 }
505
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700506 if config.Checkbuild() {
507 toBuild |= build.RunBuildTests
508 }
509 build.Build(ctx, config, toBuild)
510}
511
512// getCommand finds the appropriate command based on args[1] flag. args[0]
513// is the soong_ui filename.
Liz Kammer0e7993e2020-10-15 11:07:13 -0700514func getCommand(args []string) (*command, []string, error) {
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700515 if len(args) < 2 {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700516 return nil, nil, fmt.Errorf("Too few arguments: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700517 }
518
519 for _, c := range commands {
520 if c.flag == args[1] {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700521 return &c, args[2:], nil
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700522 }
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700523 }
524
525 // command not found
Liz Kammer0e7993e2020-10-15 11:07:13 -0700526 return nil, nil, fmt.Errorf("Command not found: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700527}