blob: d0cad78260a635ea28ae0fa89a9a362c66e90d76 [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")
174 defer build.UploadMetrics(buildCtx, config, buildStartedMilli, buildErrorFile, rbeMetricsFile, soongMetricsFile)
175
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)
Nan Zhangd50f53b2019-01-07 20:26:51 -0800190
Dan Willemsen1e704462016-08-21 15:17:17 -0700191 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
192 if !strings.HasSuffix(start, "N") {
193 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
194 log.Verbosef("Took %dms to start up.",
195 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800196 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700197 }
198 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700199
200 if executable, err := os.Executable(); err == nil {
201 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
202 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700203 }
204
Dan Willemsen6b783c82019-03-08 11:42:28 -0800205 // Fix up the source tree due to a repo bug where it doesn't remove
206 // linkfiles that have been removed
207 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
208 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
209
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700210 f := build.NewSourceFinder(buildCtx, config)
211 defer f.Shutdown()
212 build.FindSources(buildCtx, config, f)
213
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700214 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700215}
216
Dan Willemsen6b783c82019-03-08 11:42:28 -0800217func fixBadDanglingLink(ctx build.Context, name string) {
218 _, err := os.Lstat(name)
219 if err != nil {
220 return
221 }
222 _, err = os.Stat(name)
223 if os.IsNotExist(err) {
224 err = os.Remove(name)
225 if err != nil {
226 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
227 }
228 }
229}
230
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700231func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700232 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
233 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700234 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
235 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
236 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700237
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700238 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
239 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
240 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700241 flags.PrintDefaults()
242 }
243 abs := flags.Bool("abs", false, "Print the absolute path of the value")
244 flags.Parse(args)
245
246 if flags.NArg() != 1 {
247 flags.Usage()
248 os.Exit(1)
249 }
250
251 varName := flags.Arg(0)
252 if varName == "report_config" {
253 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
254 if err != nil {
255 ctx.Fatal(err)
256 }
257
258 fmt.Println(build.Banner(varData))
259 } else {
260 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
261 if err != nil {
262 ctx.Fatal(err)
263 }
264
265 if *abs {
266 var res []string
267 for _, path := range strings.Fields(varData[varName]) {
268 if abs, err := filepath.Abs(path); err == nil {
269 res = append(res, abs)
270 } else {
271 ctx.Fatalln("Failed to get absolute path of", path, err)
272 }
273 }
274 fmt.Println(strings.Join(res, " "))
275 } else {
276 fmt.Println(varData[varName])
277 }
278 }
279}
280
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700281func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700282 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
283 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700284 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
285 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
286 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
287 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
288 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700289
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700290 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
291 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
292 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700293 flags.PrintDefaults()
294 }
295
296 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
297 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
298
299 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
300 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
301
302 flags.Parse(args)
303
304 if flags.NArg() != 0 {
305 flags.Usage()
306 os.Exit(1)
307 }
308
309 vars := strings.Fields(*varsStr)
310 absVars := strings.Fields(*absVarsStr)
311
312 allVars := append([]string{}, vars...)
313 allVars = append(allVars, absVars...)
314
315 if i := indexList("report_config", allVars); i != -1 {
316 allVars = append(allVars[:i], allVars[i+1:]...)
317 allVars = append(allVars, build.BannerVars...)
318 }
319
320 if len(allVars) == 0 {
321 return
322 }
323
324 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
325 if err != nil {
326 ctx.Fatal(err)
327 }
328
329 for _, name := range vars {
330 if name == "report_config" {
331 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
332 } else {
333 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
334 }
335 }
336 for _, name := range absVars {
337 var res []string
338 for _, path := range strings.Fields(varData[name]) {
339 abs, err := filepath.Abs(path)
340 if err != nil {
341 ctx.Fatalln("Failed to get absolute path of", path, err)
342 }
343 res = append(res, abs)
344 }
345 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
346 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700347}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700348
Patrice Arrudab7b22822019-05-21 17:46:23 -0700349func stdio() terminal.StdioInterface {
350 return terminal.StdioImpl{}
351}
352
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700353func customStdio() terminal.StdioInterface {
354 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
355}
356
357// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
358func dumpVarConfig(ctx build.Context, args ...string) build.Config {
359 return build.NewConfig(ctx)
360}
361
Patrice Arrudab7b22822019-05-21 17:46:23 -0700362func buildActionConfig(ctx build.Context, args ...string) build.Config {
363 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
364 flags.Usage = func() {
365 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
366 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
367 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
368 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
369 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
370 fmt.Fprintln(ctx.Writer, "")
371 flags.PrintDefaults()
372 }
373
374 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700375 name string
376 description string
377 action build.BuildAction
378 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700379 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700380 name: "all-modules",
381 description: "Build action: build from the top of the source tree.",
382 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700383 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700384 // This is redirecting to mma build command behaviour. Once it has soaked for a
385 // while, the build command is deleted from here once it has been removed from the
386 // envsetup.sh.
387 name: "modules-in-a-dir-no-deps",
388 description: "Build action: builds all of the modules in the current directory without their dependencies.",
389 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700390 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700391 // This is redirecting to mmma build command behaviour. Once it has soaked for a
392 // while, the build command is deleted from here once it has been removed from the
393 // envsetup.sh.
394 name: "modules-in-dirs-no-deps",
395 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
396 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700397 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700398 name: "modules-in-a-dir",
399 description: "Build action: builds all of the modules in the current directory and their dependencies.",
400 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700401 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700402 name: "modules-in-dirs",
403 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
404 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700405 }}
406 for i, flag := range buildActionFlags {
407 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
408 }
409 dir := flags.String("dir", "", "Directory of the executed build command.")
410
411 // Only interested in the first two args which defines the build action and the directory.
412 // The remaining arguments are passed down to the config.
413 const numBuildActionFlags = 2
414 if len(args) < numBuildActionFlags {
415 flags.Usage()
416 ctx.Fatalln("Improper build action arguments.")
417 }
418 flags.Parse(args[0:numBuildActionFlags])
419
420 // The next block of code is to validate that exactly one build action is set and the dir flag
421 // is specified.
422 buildActionCount := 0
423 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700424 for _, flag := range buildActionFlags {
425 if flag.set {
426 buildActionCount++
427 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700428 }
429 }
430 if buildActionCount != 1 {
431 ctx.Fatalln("Build action not defined.")
432 }
433 if *dir == "" {
434 ctx.Fatalln("-dir not specified.")
435 }
436
437 // Remove the build action flags from the args as they are not recognized by the config.
438 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700439 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700440}
441
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700442func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
443 if config.IsVerbose() {
444 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700445 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
446 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
447 fmt.Fprintln(writer, "!")
448 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
449 fmt.Fprintln(writer, "!")
450 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
451 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700452 select {
453 case <-time.After(5 * time.Second):
454 case <-ctx.Done():
455 return
456 }
457 }
458
459 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
460 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700461 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700462 fmt.Fprintln(writer, "!")
463 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
464 fmt.Fprintln(writer, "!")
465 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
466 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700467 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700468 }
469
470 toBuild := build.BuildAll
471 if config.Checkbuild() {
472 toBuild |= build.RunBuildTests
473 }
474 build.Build(ctx, config, toBuild)
475}
476
477// getCommand finds the appropriate command based on args[1] flag. args[0]
478// is the soong_ui filename.
479func getCommand(args []string) (*command, []string) {
480 if len(args) < 2 {
481 return nil, args
482 }
483
484 for _, c := range commands {
485 if c.flag == args[1] {
486 return &c, args[2:]
487 }
488
489 // special case for --make-mode: if soong_ui was called from
490 // build/make/core/main.mk, the makeparallel with --ninja
491 // option specified puts the -j<num> before --make-mode.
492 // TODO: Remove this hack once it has been fixed.
493 if c.flag == makeModeFlagName {
494 if inList(makeModeFlagName, args) {
495 return &c, args[1:]
496 }
497 }
498 }
499
500 // command not found
501 return nil, args
502}