blob: a1b0c8e90662e15e38a38aab651d0f0c04dda0c5 [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
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000128 output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
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()
Patrice Arruda73c790f2020-07-13 23:01:18 +0000141 met.SetBuildDateTime(buildStarted)
Nan Zhang17f27672018-12-12 16:01:49 -0800142
Dan Willemsenb82471a2018-05-17 16:37:09 -0700143 stat := &status.Status{}
144 defer stat.Finish()
Colin Crosse0df1a32019-06-09 19:40:08 -0700145 stat.AddOutput(output)
Dan Willemsenb82471a2018-05-17 16:37:09 -0700146 stat.AddOutput(trace.StatusTracer())
147
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700148 build.SetupSignals(log, cancel, func() {
149 trace.Close()
150 log.Cleanup()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700151 stat.Finish()
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700152 })
153
Dan Willemsen59339a22018-07-22 21:18:45 -0700154 buildCtx := build.Context{ContextImpl: &build.ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -0700155 Context: ctx,
156 Logger: log,
Nan Zhang17f27672018-12-12 16:01:49 -0800157 Metrics: met,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700158 Tracer: trace,
Colin Crosse0df1a32019-06-09 19:40:08 -0700159 Writer: output,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700160 Status: stat,
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700161 }}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700162
163 config := c.config(buildCtx, args...)
Dan Willemsen1e704462016-08-21 15:17:17 -0700164
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700165 build.SetupOutDir(buildCtx, config)
Dan Willemsen8a073a82017-02-04 17:30:44 -0800166
Dan Willemsenb82471a2018-05-17 16:37:09 -0700167 logsDir := config.OutDir()
Dan Willemsen8a073a82017-02-04 17:30:44 -0800168 if config.Dist() {
Dan Willemsenb82471a2018-05-17 16:37:09 -0700169 logsDir = filepath.Join(config.DistDir(), "logs")
Dan Willemsen8a073a82017-02-04 17:30:44 -0800170 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700171
Patrice Arruda219eef32020-06-01 17:29:30 +0000172 buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
173 rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
174 soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000175 defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
Kousik Kumara0a44a82020-10-08 02:33:29 -0400176 build.PrintOutDirWarning(buildCtx, config)
Patrice Arruda219eef32020-06-01 17:29:30 +0000177
Dan Willemsenb82471a2018-05-17 16:37:09 -0700178 os.MkdirAll(logsDir, 0777)
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700179 log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
180 trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
181 stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
182 stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
Patrice Arruda219eef32020-06-01 17:29:30 +0000183 stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
Colin Cross7b624532019-06-21 15:08:30 -0700184 stat.AddOutput(status.NewCriticalPath(log))
Patrice Arruda74b43992020-03-11 08:21:05 -0700185 stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700186
Colin Cross8b8bec32019-11-15 13:18:43 -0800187 buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
188 buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
189 config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
190
Patrice Arruda219eef32020-06-01 17:29:30 +0000191 defer met.Dump(soongMetricsFile)
Patrice Arruda62f1bf22020-07-07 12:48:26 +0000192 defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
Nan Zhangd50f53b2019-01-07 20:26:51 -0800193
Dan Willemsen1e704462016-08-21 15:17:17 -0700194 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
195 if !strings.HasSuffix(start, "N") {
196 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
197 log.Verbosef("Took %dms to start up.",
198 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800199 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700200 }
201 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700202
203 if executable, err := os.Executable(); err == nil {
204 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
205 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700206 }
207
Dan Willemsen6b783c82019-03-08 11:42:28 -0800208 // Fix up the source tree due to a repo bug where it doesn't remove
209 // linkfiles that have been removed
210 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
211 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
212
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700213 f := build.NewSourceFinder(buildCtx, config)
214 defer f.Shutdown()
215 build.FindSources(buildCtx, config, f)
216
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700217 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700218}
219
Dan Willemsen6b783c82019-03-08 11:42:28 -0800220func fixBadDanglingLink(ctx build.Context, name string) {
221 _, err := os.Lstat(name)
222 if err != nil {
223 return
224 }
225 _, err = os.Stat(name)
226 if os.IsNotExist(err) {
227 err = os.Remove(name)
228 if err != nil {
229 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
230 }
231 }
232}
233
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700234func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700235 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
236 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700237 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
238 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
239 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700240
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700241 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
242 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
243 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700244 flags.PrintDefaults()
245 }
246 abs := flags.Bool("abs", false, "Print the absolute path of the value")
247 flags.Parse(args)
248
249 if flags.NArg() != 1 {
250 flags.Usage()
251 os.Exit(1)
252 }
253
254 varName := flags.Arg(0)
255 if varName == "report_config" {
256 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
257 if err != nil {
258 ctx.Fatal(err)
259 }
260
261 fmt.Println(build.Banner(varData))
262 } else {
263 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
264 if err != nil {
265 ctx.Fatal(err)
266 }
267
268 if *abs {
269 var res []string
270 for _, path := range strings.Fields(varData[varName]) {
271 if abs, err := filepath.Abs(path); err == nil {
272 res = append(res, abs)
273 } else {
274 ctx.Fatalln("Failed to get absolute path of", path, err)
275 }
276 }
277 fmt.Println(strings.Join(res, " "))
278 } else {
279 fmt.Println(varData[varName])
280 }
281 }
282}
283
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700284func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700285 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
286 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700287 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
288 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
289 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
290 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
291 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700292
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700293 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
294 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
295 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700296 flags.PrintDefaults()
297 }
298
299 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
300 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
301
302 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
303 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
304
305 flags.Parse(args)
306
307 if flags.NArg() != 0 {
308 flags.Usage()
309 os.Exit(1)
310 }
311
312 vars := strings.Fields(*varsStr)
313 absVars := strings.Fields(*absVarsStr)
314
315 allVars := append([]string{}, vars...)
316 allVars = append(allVars, absVars...)
317
318 if i := indexList("report_config", allVars); i != -1 {
319 allVars = append(allVars[:i], allVars[i+1:]...)
320 allVars = append(allVars, build.BannerVars...)
321 }
322
323 if len(allVars) == 0 {
324 return
325 }
326
327 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
328 if err != nil {
329 ctx.Fatal(err)
330 }
331
332 for _, name := range vars {
333 if name == "report_config" {
334 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
335 } else {
336 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
337 }
338 }
339 for _, name := range absVars {
340 var res []string
341 for _, path := range strings.Fields(varData[name]) {
342 abs, err := filepath.Abs(path)
343 if err != nil {
344 ctx.Fatalln("Failed to get absolute path of", path, err)
345 }
346 res = append(res, abs)
347 }
348 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
349 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700350}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700351
Patrice Arrudab7b22822019-05-21 17:46:23 -0700352func stdio() terminal.StdioInterface {
353 return terminal.StdioImpl{}
354}
355
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700356func customStdio() terminal.StdioInterface {
357 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
358}
359
360// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
361func dumpVarConfig(ctx build.Context, args ...string) build.Config {
362 return build.NewConfig(ctx)
363}
364
Patrice Arrudab7b22822019-05-21 17:46:23 -0700365func buildActionConfig(ctx build.Context, args ...string) build.Config {
366 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
367 flags.Usage = func() {
368 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
369 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
370 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
371 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
372 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
373 fmt.Fprintln(ctx.Writer, "")
374 flags.PrintDefaults()
375 }
376
377 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700378 name string
379 description string
380 action build.BuildAction
381 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700382 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700383 name: "all-modules",
384 description: "Build action: build from the top of the source tree.",
385 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700386 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700387 // This is redirecting to mma build command behaviour. Once it has soaked for a
388 // while, the build command is deleted from here once it has been removed from the
389 // envsetup.sh.
390 name: "modules-in-a-dir-no-deps",
391 description: "Build action: builds all of the modules in the current directory without their dependencies.",
392 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700393 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700394 // This is redirecting to mmma build command behaviour. Once it has soaked for a
395 // while, the build command is deleted from here once it has been removed from the
396 // envsetup.sh.
397 name: "modules-in-dirs-no-deps",
398 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
399 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700400 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700401 name: "modules-in-a-dir",
402 description: "Build action: builds all of the modules in the current directory and their dependencies.",
403 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700404 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700405 name: "modules-in-dirs",
406 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
407 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700408 }}
409 for i, flag := range buildActionFlags {
410 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
411 }
412 dir := flags.String("dir", "", "Directory of the executed build command.")
413
414 // Only interested in the first two args which defines the build action and the directory.
415 // The remaining arguments are passed down to the config.
416 const numBuildActionFlags = 2
417 if len(args) < numBuildActionFlags {
418 flags.Usage()
419 ctx.Fatalln("Improper build action arguments.")
420 }
421 flags.Parse(args[0:numBuildActionFlags])
422
423 // The next block of code is to validate that exactly one build action is set and the dir flag
424 // is specified.
425 buildActionCount := 0
426 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700427 for _, flag := range buildActionFlags {
428 if flag.set {
429 buildActionCount++
430 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700431 }
432 }
433 if buildActionCount != 1 {
434 ctx.Fatalln("Build action not defined.")
435 }
436 if *dir == "" {
437 ctx.Fatalln("-dir not specified.")
438 }
439
440 // Remove the build action flags from the args as they are not recognized by the config.
441 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700442 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700443}
444
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700445func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
446 if config.IsVerbose() {
447 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700448 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
449 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
450 fmt.Fprintln(writer, "!")
451 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
452 fmt.Fprintln(writer, "!")
453 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
454 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700455 select {
456 case <-time.After(5 * time.Second):
457 case <-ctx.Done():
458 return
459 }
460 }
461
462 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
463 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700464 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700465 fmt.Fprintln(writer, "!")
466 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
467 fmt.Fprintln(writer, "!")
468 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
469 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700470 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700471 }
472
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000473 var toBuild int
474 if _, ok := config.Environment().Get("USE_BAZEL"); ok {
475 toBuild = build.BuildAllWithBazel
476 } else {
477 toBuild = build.BuildAll
478 }
479
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700480 if config.Checkbuild() {
481 toBuild |= build.RunBuildTests
482 }
483 build.Build(ctx, config, toBuild)
484}
485
486// getCommand finds the appropriate command based on args[1] flag. args[0]
487// is the soong_ui filename.
Liz Kammer0e7993e2020-10-15 11:07:13 -0700488func getCommand(args []string) (*command, []string, error) {
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700489 if len(args) < 2 {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700490 return nil, nil, fmt.Errorf("Too few arguments: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700491 }
492
493 for _, c := range commands {
494 if c.flag == args[1] {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700495 return &c, args[2:], nil
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700496 }
497
498 // special case for --make-mode: if soong_ui was called from
499 // build/make/core/main.mk, the makeparallel with --ninja
500 // option specified puts the -j<num> before --make-mode.
501 // TODO: Remove this hack once it has been fixed.
502 if c.flag == makeModeFlagName {
503 if inList(makeModeFlagName, args) {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700504 return &c, args[1:], nil
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700505 }
506 }
507 }
508
509 // command not found
Liz Kammer0e7993e2020-10-15 11:07:13 -0700510 return nil, nil, fmt.Errorf("Command not found: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700511}