blob: 974c644aaaf3d3d2f38b9b7bef66d12e7cdbbcc0 [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 Arrudaa5c25422019-04-09 18:49:49 -0700120 c, args := getCommand(os.Args)
121 if c == nil {
122 fmt.Fprintf(os.Stderr, "The `soong` native UI is not yet available.\n")
123 os.Exit(1)
Dan Willemsenc35b3812018-07-16 19:59:10 -0700124 }
125
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700126 output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.forceDumbOutput,
Colin Crosse0df1a32019-06-09 19:40:08 -0700127 build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700128
Colin Crosse0df1a32019-06-09 19:40:08 -0700129 log := logger.New(output)
Dan Willemsen1e704462016-08-21 15:17:17 -0700130 defer log.Cleanup()
131
Dan Willemsen1e704462016-08-21 15:17:17 -0700132 ctx, cancel := context.WithCancel(context.Background())
133 defer cancel()
134
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700135 trace := tracer.New(log)
136 defer trace.Close()
Dan Willemsen1e704462016-08-21 15:17:17 -0700137
Nan Zhang17f27672018-12-12 16:01:49 -0800138 met := metrics.New()
139
Dan Willemsenb82471a2018-05-17 16:37:09 -0700140 stat := &status.Status{}
141 defer stat.Finish()
Colin Crosse0df1a32019-06-09 19:40:08 -0700142 stat.AddOutput(output)
Dan Willemsenb82471a2018-05-17 16:37:09 -0700143 stat.AddOutput(trace.StatusTracer())
144
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700145 build.SetupSignals(log, cancel, func() {
146 trace.Close()
147 log.Cleanup()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700148 stat.Finish()
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700149 })
150
Dan Willemsen59339a22018-07-22 21:18:45 -0700151 buildCtx := build.Context{ContextImpl: &build.ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -0700152 Context: ctx,
153 Logger: log,
Nan Zhang17f27672018-12-12 16:01:49 -0800154 Metrics: met,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700155 Tracer: trace,
Colin Crosse0df1a32019-06-09 19:40:08 -0700156 Writer: output,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700157 Status: stat,
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700158 }}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700159
160 config := c.config(buildCtx, args...)
Dan Willemsen1e704462016-08-21 15:17:17 -0700161
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700162 build.SetupOutDir(buildCtx, config)
Dan Willemsen8a073a82017-02-04 17:30:44 -0800163
Dan Willemsenb82471a2018-05-17 16:37:09 -0700164 logsDir := config.OutDir()
Dan Willemsen8a073a82017-02-04 17:30:44 -0800165 if config.Dist() {
Dan Willemsenb82471a2018-05-17 16:37:09 -0700166 logsDir = filepath.Join(config.DistDir(), "logs")
Dan Willemsen8a073a82017-02-04 17:30:44 -0800167 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700168
Dan Willemsenb82471a2018-05-17 16:37:09 -0700169 os.MkdirAll(logsDir, 0777)
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700170 log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
171 trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
172 stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
173 stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
174 stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"build_error")))
Colin Cross7b624532019-06-21 15:08:30 -0700175 stat.AddOutput(status.NewCriticalPath(log))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700176
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700177 defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
Nan Zhangd50f53b2019-01-07 20:26:51 -0800178
Dan Willemsen1e704462016-08-21 15:17:17 -0700179 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
180 if !strings.HasSuffix(start, "N") {
181 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
182 log.Verbosef("Took %dms to start up.",
183 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800184 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700185 }
186 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700187
188 if executable, err := os.Executable(); err == nil {
189 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
190 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700191 }
192
Dan Willemsen6b783c82019-03-08 11:42:28 -0800193 // Fix up the source tree due to a repo bug where it doesn't remove
194 // linkfiles that have been removed
195 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
196 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
197
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700198 f := build.NewSourceFinder(buildCtx, config)
199 defer f.Shutdown()
200 build.FindSources(buildCtx, config, f)
201
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700202 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700203}
204
Dan Willemsen6b783c82019-03-08 11:42:28 -0800205func fixBadDanglingLink(ctx build.Context, name string) {
206 _, err := os.Lstat(name)
207 if err != nil {
208 return
209 }
210 _, err = os.Stat(name)
211 if os.IsNotExist(err) {
212 err = os.Remove(name)
213 if err != nil {
214 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
215 }
216 }
217}
218
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700219func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700220 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
221 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700222 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
223 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
224 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700225
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700226 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
227 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
228 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700229 flags.PrintDefaults()
230 }
231 abs := flags.Bool("abs", false, "Print the absolute path of the value")
232 flags.Parse(args)
233
234 if flags.NArg() != 1 {
235 flags.Usage()
236 os.Exit(1)
237 }
238
239 varName := flags.Arg(0)
240 if varName == "report_config" {
241 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
242 if err != nil {
243 ctx.Fatal(err)
244 }
245
246 fmt.Println(build.Banner(varData))
247 } else {
248 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
249 if err != nil {
250 ctx.Fatal(err)
251 }
252
253 if *abs {
254 var res []string
255 for _, path := range strings.Fields(varData[varName]) {
256 if abs, err := filepath.Abs(path); err == nil {
257 res = append(res, abs)
258 } else {
259 ctx.Fatalln("Failed to get absolute path of", path, err)
260 }
261 }
262 fmt.Println(strings.Join(res, " "))
263 } else {
264 fmt.Println(varData[varName])
265 }
266 }
267}
268
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700269func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700270 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
271 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700272 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
273 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
274 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
275 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
276 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700277
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700278 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
279 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
280 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700281 flags.PrintDefaults()
282 }
283
284 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
285 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
286
287 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
288 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
289
290 flags.Parse(args)
291
292 if flags.NArg() != 0 {
293 flags.Usage()
294 os.Exit(1)
295 }
296
297 vars := strings.Fields(*varsStr)
298 absVars := strings.Fields(*absVarsStr)
299
300 allVars := append([]string{}, vars...)
301 allVars = append(allVars, absVars...)
302
303 if i := indexList("report_config", allVars); i != -1 {
304 allVars = append(allVars[:i], allVars[i+1:]...)
305 allVars = append(allVars, build.BannerVars...)
306 }
307
308 if len(allVars) == 0 {
309 return
310 }
311
312 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
313 if err != nil {
314 ctx.Fatal(err)
315 }
316
317 for _, name := range vars {
318 if name == "report_config" {
319 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
320 } else {
321 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
322 }
323 }
324 for _, name := range absVars {
325 var res []string
326 for _, path := range strings.Fields(varData[name]) {
327 abs, err := filepath.Abs(path)
328 if err != nil {
329 ctx.Fatalln("Failed to get absolute path of", path, err)
330 }
331 res = append(res, abs)
332 }
333 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
334 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700335}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700336
Patrice Arrudab7b22822019-05-21 17:46:23 -0700337func stdio() terminal.StdioInterface {
338 return terminal.StdioImpl{}
339}
340
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700341func customStdio() terminal.StdioInterface {
342 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
343}
344
345// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
346func dumpVarConfig(ctx build.Context, args ...string) build.Config {
347 return build.NewConfig(ctx)
348}
349
Patrice Arrudab7b22822019-05-21 17:46:23 -0700350func buildActionConfig(ctx build.Context, args ...string) build.Config {
351 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
352 flags.Usage = func() {
353 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
354 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
355 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
356 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
357 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
358 fmt.Fprintln(ctx.Writer, "")
359 flags.PrintDefaults()
360 }
361
362 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700363 name string
364 description string
365 action build.BuildAction
366 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700367 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700368 name: "all-modules",
369 description: "Build action: build from the top of the source tree.",
370 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700371 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700372 // This is redirecting to mma build command behaviour. Once it has soaked for a
373 // while, the build command is deleted from here once it has been removed from the
374 // envsetup.sh.
375 name: "modules-in-a-dir-no-deps",
376 description: "Build action: builds all of the modules in the current directory without their dependencies.",
377 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700378 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700379 // This is redirecting to mmma build command behaviour. Once it has soaked for a
380 // while, the build command is deleted from here once it has been removed from the
381 // envsetup.sh.
382 name: "modules-in-dirs-no-deps",
383 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
384 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700385 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700386 name: "modules-in-a-dir",
387 description: "Build action: builds all of the modules in the current directory and their dependencies.",
388 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700389 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700390 name: "modules-in-dirs",
391 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
392 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700393 }}
394 for i, flag := range buildActionFlags {
395 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
396 }
397 dir := flags.String("dir", "", "Directory of the executed build command.")
398
399 // Only interested in the first two args which defines the build action and the directory.
400 // The remaining arguments are passed down to the config.
401 const numBuildActionFlags = 2
402 if len(args) < numBuildActionFlags {
403 flags.Usage()
404 ctx.Fatalln("Improper build action arguments.")
405 }
406 flags.Parse(args[0:numBuildActionFlags])
407
408 // The next block of code is to validate that exactly one build action is set and the dir flag
409 // is specified.
410 buildActionCount := 0
411 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700412 for _, flag := range buildActionFlags {
413 if flag.set {
414 buildActionCount++
415 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700416 }
417 }
418 if buildActionCount != 1 {
419 ctx.Fatalln("Build action not defined.")
420 }
421 if *dir == "" {
422 ctx.Fatalln("-dir not specified.")
423 }
424
425 // Remove the build action flags from the args as they are not recognized by the config.
426 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700427 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700428}
429
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700430func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
431 if config.IsVerbose() {
432 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700433 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
434 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
435 fmt.Fprintln(writer, "!")
436 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
437 fmt.Fprintln(writer, "!")
438 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
439 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700440 select {
441 case <-time.After(5 * time.Second):
442 case <-ctx.Done():
443 return
444 }
445 }
446
447 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
448 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700449 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700450 fmt.Fprintln(writer, "!")
451 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
452 fmt.Fprintln(writer, "!")
453 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
454 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700455 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700456 }
457
458 toBuild := build.BuildAll
459 if config.Checkbuild() {
460 toBuild |= build.RunBuildTests
461 }
462 build.Build(ctx, config, toBuild)
463}
464
465// getCommand finds the appropriate command based on args[1] flag. args[0]
466// is the soong_ui filename.
467func getCommand(args []string) (*command, []string) {
468 if len(args) < 2 {
469 return nil, args
470 }
471
472 for _, c := range commands {
473 if c.flag == args[1] {
474 return &c, args[2:]
475 }
476
477 // special case for --make-mode: if soong_ui was called from
478 // build/make/core/main.mk, the makeparallel with --ninja
479 // option specified puts the -j<num> before --make-mode.
480 // TODO: Remove this hack once it has been fixed.
481 if c.flag == makeModeFlagName {
482 if inList(makeModeFlagName, args) {
483 return &c, args[1:]
484 }
485 }
486 }
487
488 // command not found
489 return nil, args
490}