blob: 1d94f0218d1af3963ef0982a2b88523eb7ee370d [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))
Patrice Arruda74b43992020-03-11 08:21:05 -0700176 stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700177
Colin Cross8b8bec32019-11-15 13:18:43 -0800178 buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
179 buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
180 config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
181
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700182 defer met.Dump(filepath.Join(logsDir, c.logsPrefix+"soong_metrics"))
Nan Zhangd50f53b2019-01-07 20:26:51 -0800183
Dan Willemsen1e704462016-08-21 15:17:17 -0700184 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
185 if !strings.HasSuffix(start, "N") {
186 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
187 log.Verbosef("Took %dms to start up.",
188 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800189 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700190 }
191 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700192
193 if executable, err := os.Executable(); err == nil {
194 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
195 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700196 }
197
Dan Willemsen6b783c82019-03-08 11:42:28 -0800198 // Fix up the source tree due to a repo bug where it doesn't remove
199 // linkfiles that have been removed
200 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
201 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
202
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700203 f := build.NewSourceFinder(buildCtx, config)
204 defer f.Shutdown()
205 build.FindSources(buildCtx, config, f)
206
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700207 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700208}
209
Dan Willemsen6b783c82019-03-08 11:42:28 -0800210func fixBadDanglingLink(ctx build.Context, name string) {
211 _, err := os.Lstat(name)
212 if err != nil {
213 return
214 }
215 _, err = os.Stat(name)
216 if os.IsNotExist(err) {
217 err = os.Remove(name)
218 if err != nil {
219 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
220 }
221 }
222}
223
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700224func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700225 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
226 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700227 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
228 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
229 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700230
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700231 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
232 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
233 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700234 flags.PrintDefaults()
235 }
236 abs := flags.Bool("abs", false, "Print the absolute path of the value")
237 flags.Parse(args)
238
239 if flags.NArg() != 1 {
240 flags.Usage()
241 os.Exit(1)
242 }
243
244 varName := flags.Arg(0)
245 if varName == "report_config" {
246 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
247 if err != nil {
248 ctx.Fatal(err)
249 }
250
251 fmt.Println(build.Banner(varData))
252 } else {
253 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
254 if err != nil {
255 ctx.Fatal(err)
256 }
257
258 if *abs {
259 var res []string
260 for _, path := range strings.Fields(varData[varName]) {
261 if abs, err := filepath.Abs(path); err == nil {
262 res = append(res, abs)
263 } else {
264 ctx.Fatalln("Failed to get absolute path of", path, err)
265 }
266 }
267 fmt.Println(strings.Join(res, " "))
268 } else {
269 fmt.Println(varData[varName])
270 }
271 }
272}
273
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700274func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700275 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
276 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700277 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
278 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
279 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
280 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
281 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700282
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700283 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
284 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
285 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700286 flags.PrintDefaults()
287 }
288
289 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
290 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
291
292 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
293 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
294
295 flags.Parse(args)
296
297 if flags.NArg() != 0 {
298 flags.Usage()
299 os.Exit(1)
300 }
301
302 vars := strings.Fields(*varsStr)
303 absVars := strings.Fields(*absVarsStr)
304
305 allVars := append([]string{}, vars...)
306 allVars = append(allVars, absVars...)
307
308 if i := indexList("report_config", allVars); i != -1 {
309 allVars = append(allVars[:i], allVars[i+1:]...)
310 allVars = append(allVars, build.BannerVars...)
311 }
312
313 if len(allVars) == 0 {
314 return
315 }
316
317 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
318 if err != nil {
319 ctx.Fatal(err)
320 }
321
322 for _, name := range vars {
323 if name == "report_config" {
324 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
325 } else {
326 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
327 }
328 }
329 for _, name := range absVars {
330 var res []string
331 for _, path := range strings.Fields(varData[name]) {
332 abs, err := filepath.Abs(path)
333 if err != nil {
334 ctx.Fatalln("Failed to get absolute path of", path, err)
335 }
336 res = append(res, abs)
337 }
338 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
339 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700340}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700341
Patrice Arrudab7b22822019-05-21 17:46:23 -0700342func stdio() terminal.StdioInterface {
343 return terminal.StdioImpl{}
344}
345
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700346func customStdio() terminal.StdioInterface {
347 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
348}
349
350// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
351func dumpVarConfig(ctx build.Context, args ...string) build.Config {
352 return build.NewConfig(ctx)
353}
354
Patrice Arrudab7b22822019-05-21 17:46:23 -0700355func buildActionConfig(ctx build.Context, args ...string) build.Config {
356 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
357 flags.Usage = func() {
358 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
359 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
360 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
361 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
362 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
363 fmt.Fprintln(ctx.Writer, "")
364 flags.PrintDefaults()
365 }
366
367 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700368 name string
369 description string
370 action build.BuildAction
371 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700372 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700373 name: "all-modules",
374 description: "Build action: build from the top of the source tree.",
375 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700376 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700377 // This is redirecting to mma build command behaviour. Once it has soaked for a
378 // while, the build command is deleted from here once it has been removed from the
379 // envsetup.sh.
380 name: "modules-in-a-dir-no-deps",
381 description: "Build action: builds all of the modules in the current directory without their dependencies.",
382 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700383 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700384 // This is redirecting to mmma 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-dirs-no-deps",
388 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
389 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700390 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700391 name: "modules-in-a-dir",
392 description: "Build action: builds all of the modules in the current directory and their dependencies.",
393 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700394 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700395 name: "modules-in-dirs",
396 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
397 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700398 }}
399 for i, flag := range buildActionFlags {
400 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
401 }
402 dir := flags.String("dir", "", "Directory of the executed build command.")
403
404 // Only interested in the first two args which defines the build action and the directory.
405 // The remaining arguments are passed down to the config.
406 const numBuildActionFlags = 2
407 if len(args) < numBuildActionFlags {
408 flags.Usage()
409 ctx.Fatalln("Improper build action arguments.")
410 }
411 flags.Parse(args[0:numBuildActionFlags])
412
413 // The next block of code is to validate that exactly one build action is set and the dir flag
414 // is specified.
415 buildActionCount := 0
416 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700417 for _, flag := range buildActionFlags {
418 if flag.set {
419 buildActionCount++
420 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700421 }
422 }
423 if buildActionCount != 1 {
424 ctx.Fatalln("Build action not defined.")
425 }
426 if *dir == "" {
427 ctx.Fatalln("-dir not specified.")
428 }
429
430 // Remove the build action flags from the args as they are not recognized by the config.
431 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700432 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700433}
434
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700435func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
436 if config.IsVerbose() {
437 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700438 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
439 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
440 fmt.Fprintln(writer, "!")
441 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
442 fmt.Fprintln(writer, "!")
443 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
444 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700445 select {
446 case <-time.After(5 * time.Second):
447 case <-ctx.Done():
448 return
449 }
450 }
451
452 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
453 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700454 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700455 fmt.Fprintln(writer, "!")
456 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
457 fmt.Fprintln(writer, "!")
458 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
459 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700460 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700461 }
462
463 toBuild := build.BuildAll
464 if config.Checkbuild() {
465 toBuild |= build.RunBuildTests
466 }
467 build.Build(ctx, config, toBuild)
468}
469
470// getCommand finds the appropriate command based on args[1] flag. args[0]
471// is the soong_ui filename.
472func getCommand(args []string) (*command, []string) {
473 if len(args) < 2 {
474 return nil, args
475 }
476
477 for _, c := range commands {
478 if c.flag == args[1] {
479 return &c, args[2:]
480 }
481
482 // special case for --make-mode: if soong_ui was called from
483 // build/make/core/main.mk, the makeparallel with --ninja
484 // option specified puts the -j<num> before --make-mode.
485 // TODO: Remove this hack once it has been fixed.
486 if c.flag == makeModeFlagName {
487 if inList(makeModeFlagName, args) {
488 return &c, args[1:]
489 }
490 }
491 }
492
493 // command not found
494 return nil, args
495}