blob: d3802f9aef21ab5a9470b3f53ac1785f0894238f [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 {
38 // the flag name (must have double dashes)
39 flag string
40
41 // description for the flag (to display when running help)
42 description string
43
Colin Crossc0b9f6b2019-09-23 12:44:54 -070044 // Forces the status output into dumb terminal mode.
45 forceDumbOutput bool
46
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 }, {
Colin Crossc0b9f6b2019-09-23 12:44:54 -070073 flag: "--dumpvar-mode",
74 description: "print the value of the legacy make variable VAR to stdout",
75 forceDumbOutput: true,
76 logsPrefix: "dumpvars-",
77 config: dumpVarConfig,
78 stdio: customStdio,
79 run: dumpVar,
Patrice Arrudaa5c25422019-04-09 18:49:49 -070080 }, {
Colin Crossc0b9f6b2019-09-23 12:44:54 -070081 flag: "--dumpvars-mode",
82 description: "dump the values of one or more legacy make variables, in shell syntax",
83 forceDumbOutput: 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 Arruda219eef32020-06-01 17:29:30 +0000120 buildStartedMilli := time.Now().UnixNano() / int64(time.Millisecond)
121
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700122 c, args := getCommand(os.Args)
123 if c == nil {
124 fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
125 os.Exit(1)
Dan Willemsenc35b3812018-07-16 19:59:10 -0700126 }
127
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700128 output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput,
Colin Crosse0df1a32019-06-09 19:40:08 -0700129 build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700130
Colin Crosse0df1a32019-06-09 19:40:08 -0700131 log := logger.New(output)
Dan Willemsen1e704462016-08-21 15:17:17 -0700132 defer log.Cleanup()
133
Dan Willemsen1e704462016-08-21 15:17:17 -0700134 ctx, cancel := context.WithCancel(context.Background())
135 defer cancel()
136
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700137 trace := tracer.New(log)
138 defer trace.Close()
Dan Willemsen1e704462016-08-21 15:17:17 -0700139
Nan Zhang17f27672018-12-12 16:01:49 -0800140 met := metrics.New()
141
Dan Willemsenb82471a2018-05-17 16:37:09 -0700142 stat := &status.Status{}
143 defer stat.Finish()
Colin Crosse0df1a32019-06-09 19:40:08 -0700144 stat.AddOutput(output)
Dan Willemsenb82471a2018-05-17 16:37:09 -0700145 stat.AddOutput(trace.StatusTracer())
146
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700147 build.SetupSignals(log, cancel, func() {
148 trace.Close()
149 log.Cleanup()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700150 stat.Finish()
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700151 })
152
Dan Willemsen59339a22018-07-22 21:18:45 -0700153 buildCtx := build.Context{ContextImpl: &build.ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -0700154 Context: ctx,
155 Logger: log,
Nan Zhang17f27672018-12-12 16:01:49 -0800156 Metrics: met,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700157 Tracer: trace,
Colin Crosse0df1a32019-06-09 19:40:08 -0700158 Writer: output,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700159 Status: stat,
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700160 }}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700161
162 config := c.config(buildCtx, args...)
Dan Willemsen1e704462016-08-21 15:17:17 -0700163
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700164 build.SetupOutDir(buildCtx, config)
Dan Willemsen8a073a82017-02-04 17:30:44 -0800165
Dan Willemsenb82471a2018-05-17 16:37:09 -0700166 logsDir := config.OutDir()
Dan Willemsen8a073a82017-02-04 17:30:44 -0800167 if config.Dist() {
Dan Willemsenb82471a2018-05-17 16:37:09 -0700168 logsDir = filepath.Join(config.DistDir(), "logs")
Dan Willemsen8a073a82017-02-04 17:30:44 -0800169 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700170
Patrice Arruda219eef32020-06-01 17:29:30 +0000171 buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
172 rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
173 soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
Patrice Arruda7cc20742020-06-10 18:48:01 +0000174 defer build.UploadMetrics(buildCtx, config, c.forceDumbOutput, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
Patrice Arruda219eef32020-06-01 17:29:30 +0000175
Dan Willemsenb82471a2018-05-17 16:37:09 -0700176 os.MkdirAll(logsDir, 0777)
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700177 log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
178 trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
179 stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
180 stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
Patrice Arruda219eef32020-06-01 17:29:30 +0000181 stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
Colin Cross7b624532019-06-21 15:08:30 -0700182 stat.AddOutput(status.NewCriticalPath(log))
Patrice Arruda74b43992020-03-11 08:21:05 -0700183 stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700184
Colin Cross8b8bec32019-11-15 13:18:43 -0800185 buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
186 buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
187 config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
188
Patrice Arruda219eef32020-06-01 17:29:30 +0000189 defer met.Dump(soongMetricsFile)
Patrice Arruda62f1bf22020-07-07 12:48:26 +0000190 defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
Nan Zhangd50f53b2019-01-07 20:26:51 -0800191
Dan Willemsen1e704462016-08-21 15:17:17 -0700192 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
193 if !strings.HasSuffix(start, "N") {
194 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
195 log.Verbosef("Took %dms to start up.",
196 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800197 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700198 }
199 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700200
201 if executable, err := os.Executable(); err == nil {
202 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
203 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700204 }
205
Dan Willemsen6b783c82019-03-08 11:42:28 -0800206 // Fix up the source tree due to a repo bug where it doesn't remove
207 // linkfiles that have been removed
208 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
209 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
210
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700211 f := build.NewSourceFinder(buildCtx, config)
212 defer f.Shutdown()
213 build.FindSources(buildCtx, config, f)
214
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700215 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700216}
217
Dan Willemsen6b783c82019-03-08 11:42:28 -0800218func fixBadDanglingLink(ctx build.Context, name string) {
219 _, err := os.Lstat(name)
220 if err != nil {
221 return
222 }
223 _, err = os.Stat(name)
224 if os.IsNotExist(err) {
225 err = os.Remove(name)
226 if err != nil {
227 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
228 }
229 }
230}
231
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700232func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700233 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
234 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700235 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
236 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
237 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700238
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700239 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
240 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
241 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700242 flags.PrintDefaults()
243 }
244 abs := flags.Bool("abs", false, "Print the absolute path of the value")
245 flags.Parse(args)
246
247 if flags.NArg() != 1 {
248 flags.Usage()
249 os.Exit(1)
250 }
251
252 varName := flags.Arg(0)
253 if varName == "report_config" {
254 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
255 if err != nil {
256 ctx.Fatal(err)
257 }
258
259 fmt.Println(build.Banner(varData))
260 } else {
261 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
262 if err != nil {
263 ctx.Fatal(err)
264 }
265
266 if *abs {
267 var res []string
268 for _, path := range strings.Fields(varData[varName]) {
269 if abs, err := filepath.Abs(path); err == nil {
270 res = append(res, abs)
271 } else {
272 ctx.Fatalln("Failed to get absolute path of", path, err)
273 }
274 }
275 fmt.Println(strings.Join(res, " "))
276 } else {
277 fmt.Println(varData[varName])
278 }
279 }
280}
281
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700282func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700283 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
284 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700285 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
286 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
287 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
288 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
289 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700290
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700291 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
292 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
293 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700294 flags.PrintDefaults()
295 }
296
297 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
298 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
299
300 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
301 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
302
303 flags.Parse(args)
304
305 if flags.NArg() != 0 {
306 flags.Usage()
307 os.Exit(1)
308 }
309
310 vars := strings.Fields(*varsStr)
311 absVars := strings.Fields(*absVarsStr)
312
313 allVars := append([]string{}, vars...)
314 allVars = append(allVars, absVars...)
315
316 if i := indexList("report_config", allVars); i != -1 {
317 allVars = append(allVars[:i], allVars[i+1:]...)
318 allVars = append(allVars, build.BannerVars...)
319 }
320
321 if len(allVars) == 0 {
322 return
323 }
324
325 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
326 if err != nil {
327 ctx.Fatal(err)
328 }
329
330 for _, name := range vars {
331 if name == "report_config" {
332 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
333 } else {
334 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
335 }
336 }
337 for _, name := range absVars {
338 var res []string
339 for _, path := range strings.Fields(varData[name]) {
340 abs, err := filepath.Abs(path)
341 if err != nil {
342 ctx.Fatalln("Failed to get absolute path of", path, err)
343 }
344 res = append(res, abs)
345 }
346 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
347 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700348}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700349
Patrice Arrudab7b22822019-05-21 17:46:23 -0700350func stdio() terminal.StdioInterface {
351 return terminal.StdioImpl{}
352}
353
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700354func customStdio() terminal.StdioInterface {
355 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
356}
357
358// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
359func dumpVarConfig(ctx build.Context, args ...string) build.Config {
360 return build.NewConfig(ctx)
361}
362
Patrice Arrudab7b22822019-05-21 17:46:23 -0700363func buildActionConfig(ctx build.Context, args ...string) build.Config {
364 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
365 flags.Usage = func() {
366 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
367 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
368 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
369 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
370 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
371 fmt.Fprintln(ctx.Writer, "")
372 flags.PrintDefaults()
373 }
374
375 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700376 name string
377 description string
378 action build.BuildAction
379 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700380 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700381 name: "all-modules",
382 description: "Build action: build from the top of the source tree.",
383 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700384 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700385 // This is redirecting to mma build command behaviour. Once it has soaked for a
386 // while, the build command is deleted from here once it has been removed from the
387 // envsetup.sh.
388 name: "modules-in-a-dir-no-deps",
389 description: "Build action: builds all of the modules in the current directory without their dependencies.",
390 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700391 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700392 // This is redirecting to mmma build command behaviour. Once it has soaked for a
393 // while, the build command is deleted from here once it has been removed from the
394 // envsetup.sh.
395 name: "modules-in-dirs-no-deps",
396 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
397 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700398 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700399 name: "modules-in-a-dir",
400 description: "Build action: builds all of the modules in the current directory and their dependencies.",
401 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700402 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700403 name: "modules-in-dirs",
404 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
405 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700406 }}
407 for i, flag := range buildActionFlags {
408 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
409 }
410 dir := flags.String("dir", "", "Directory of the executed build command.")
411
412 // Only interested in the first two args which defines the build action and the directory.
413 // The remaining arguments are passed down to the config.
414 const numBuildActionFlags = 2
415 if len(args) < numBuildActionFlags {
416 flags.Usage()
417 ctx.Fatalln("Improper build action arguments.")
418 }
419 flags.Parse(args[0:numBuildActionFlags])
420
421 // The next block of code is to validate that exactly one build action is set and the dir flag
422 // is specified.
423 buildActionCount := 0
424 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700425 for _, flag := range buildActionFlags {
426 if flag.set {
427 buildActionCount++
428 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700429 }
430 }
431 if buildActionCount != 1 {
432 ctx.Fatalln("Build action not defined.")
433 }
434 if *dir == "" {
435 ctx.Fatalln("-dir not specified.")
436 }
437
438 // Remove the build action flags from the args as they are not recognized by the config.
439 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700440 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700441}
442
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700443func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
444 if config.IsVerbose() {
445 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700446 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
447 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
448 fmt.Fprintln(writer, "!")
449 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
450 fmt.Fprintln(writer, "!")
451 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
452 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700453 select {
454 case <-time.After(5 * time.Second):
455 case <-ctx.Done():
456 return
457 }
458 }
459
460 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
461 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700462 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700463 fmt.Fprintln(writer, "!")
464 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
465 fmt.Fprintln(writer, "!")
466 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
467 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700468 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700469 }
470
471 toBuild := build.BuildAll
472 if config.Checkbuild() {
473 toBuild |= build.RunBuildTests
474 }
475 build.Build(ctx, config, toBuild)
476}
477
478// getCommand finds the appropriate command based on args[1] flag. args[0]
479// is the soong_ui filename.
480func getCommand(args []string) (*command, []string) {
481 if len(args) < 2 {
482 return nil, args
483 }
484
485 for _, c := range commands {
486 if c.flag == args[1] {
487 return &c, args[2:]
488 }
489
490 // special case for --make-mode: if soong_ui was called from
491 // build/make/core/main.mk, the makeparallel with --ninja
492 // option specified puts the -j<num> before --make-mode.
493 // TODO: Remove this hack once it has been fixed.
494 if c.flag == makeModeFlagName {
495 if inList(makeModeFlagName, args) {
496 return &c, args[1:]
497 }
498 }
499 }
500
501 // command not found
502 return nil, args
503}