blob: aee8e5a496095e00bee0f779829bf5e83b64f526 [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)
Patrice Arrudae92c30d2020-10-29 11:01:32 -0700142 met.SetBuildCommand(os.Args)
Nan Zhang17f27672018-12-12 16:01:49 -0800143
Dan Willemsenb82471a2018-05-17 16:37:09 -0700144 stat := &status.Status{}
145 defer stat.Finish()
Colin Crosse0df1a32019-06-09 19:40:08 -0700146 stat.AddOutput(output)
Dan Willemsenb82471a2018-05-17 16:37:09 -0700147 stat.AddOutput(trace.StatusTracer())
148
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700149 build.SetupSignals(log, cancel, func() {
150 trace.Close()
151 log.Cleanup()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700152 stat.Finish()
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700153 })
154
Dan Willemsen59339a22018-07-22 21:18:45 -0700155 buildCtx := build.Context{ContextImpl: &build.ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -0700156 Context: ctx,
157 Logger: log,
Nan Zhang17f27672018-12-12 16:01:49 -0800158 Metrics: met,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700159 Tracer: trace,
Colin Crosse0df1a32019-06-09 19:40:08 -0700160 Writer: output,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700161 Status: stat,
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700162 }}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700163
164 config := c.config(buildCtx, args...)
Dan Willemsen1e704462016-08-21 15:17:17 -0700165
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700166 build.SetupOutDir(buildCtx, config)
Dan Willemsen8a073a82017-02-04 17:30:44 -0800167
Dan Willemsenb82471a2018-05-17 16:37:09 -0700168 logsDir := config.OutDir()
Dan Willemsen8a073a82017-02-04 17:30:44 -0800169 if config.Dist() {
Dan Willemsenb82471a2018-05-17 16:37:09 -0700170 logsDir = filepath.Join(config.DistDir(), "logs")
Dan Willemsen8a073a82017-02-04 17:30:44 -0800171 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700172
Patrice Arruda219eef32020-06-01 17:29:30 +0000173 buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
174 rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
175 soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000176 defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
Kousik Kumara0a44a82020-10-08 02:33:29 -0400177 build.PrintOutDirWarning(buildCtx, config)
Patrice Arruda219eef32020-06-01 17:29:30 +0000178
Dan Willemsenb82471a2018-05-17 16:37:09 -0700179 os.MkdirAll(logsDir, 0777)
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700180 log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
181 trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
182 stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
183 stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
Patrice Arruda219eef32020-06-01 17:29:30 +0000184 stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
Colin Cross7b624532019-06-21 15:08:30 -0700185 stat.AddOutput(status.NewCriticalPath(log))
Patrice Arruda74b43992020-03-11 08:21:05 -0700186 stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700187
Colin Cross8b8bec32019-11-15 13:18:43 -0800188 buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
189 buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
190 config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
191
Patrice Arruda219eef32020-06-01 17:29:30 +0000192 defer met.Dump(soongMetricsFile)
Patrice Arruda62f1bf22020-07-07 12:48:26 +0000193 defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
Nan Zhangd50f53b2019-01-07 20:26:51 -0800194
Dan Willemsen1e704462016-08-21 15:17:17 -0700195 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
196 if !strings.HasSuffix(start, "N") {
197 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
198 log.Verbosef("Took %dms to start up.",
199 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800200 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700201 }
202 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700203
204 if executable, err := os.Executable(); err == nil {
205 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
206 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700207 }
208
Dan Willemsen6b783c82019-03-08 11:42:28 -0800209 // Fix up the source tree due to a repo bug where it doesn't remove
210 // linkfiles that have been removed
211 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
212 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
213
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700214 f := build.NewSourceFinder(buildCtx, config)
215 defer f.Shutdown()
216 build.FindSources(buildCtx, config, f)
217
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700218 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700219}
220
Dan Willemsen6b783c82019-03-08 11:42:28 -0800221func fixBadDanglingLink(ctx build.Context, name string) {
222 _, err := os.Lstat(name)
223 if err != nil {
224 return
225 }
226 _, err = os.Stat(name)
227 if os.IsNotExist(err) {
228 err = os.Remove(name)
229 if err != nil {
230 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
231 }
232 }
233}
234
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700235func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700236 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
237 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700238 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
239 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
240 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700241
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700242 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
243 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
244 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700245 flags.PrintDefaults()
246 }
247 abs := flags.Bool("abs", false, "Print the absolute path of the value")
248 flags.Parse(args)
249
250 if flags.NArg() != 1 {
251 flags.Usage()
252 os.Exit(1)
253 }
254
255 varName := flags.Arg(0)
256 if varName == "report_config" {
257 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
258 if err != nil {
259 ctx.Fatal(err)
260 }
261
262 fmt.Println(build.Banner(varData))
263 } else {
264 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
265 if err != nil {
266 ctx.Fatal(err)
267 }
268
269 if *abs {
270 var res []string
271 for _, path := range strings.Fields(varData[varName]) {
272 if abs, err := filepath.Abs(path); err == nil {
273 res = append(res, abs)
274 } else {
275 ctx.Fatalln("Failed to get absolute path of", path, err)
276 }
277 }
278 fmt.Println(strings.Join(res, " "))
279 } else {
280 fmt.Println(varData[varName])
281 }
282 }
283}
284
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700285func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700286 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
287 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700288 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
289 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
290 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
291 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
292 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700293
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700294 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
295 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
296 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700297 flags.PrintDefaults()
298 }
299
300 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
301 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
302
303 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
304 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
305
306 flags.Parse(args)
307
308 if flags.NArg() != 0 {
309 flags.Usage()
310 os.Exit(1)
311 }
312
313 vars := strings.Fields(*varsStr)
314 absVars := strings.Fields(*absVarsStr)
315
316 allVars := append([]string{}, vars...)
317 allVars = append(allVars, absVars...)
318
319 if i := indexList("report_config", allVars); i != -1 {
320 allVars = append(allVars[:i], allVars[i+1:]...)
321 allVars = append(allVars, build.BannerVars...)
322 }
323
324 if len(allVars) == 0 {
325 return
326 }
327
328 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
329 if err != nil {
330 ctx.Fatal(err)
331 }
332
333 for _, name := range vars {
334 if name == "report_config" {
335 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
336 } else {
337 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
338 }
339 }
340 for _, name := range absVars {
341 var res []string
342 for _, path := range strings.Fields(varData[name]) {
343 abs, err := filepath.Abs(path)
344 if err != nil {
345 ctx.Fatalln("Failed to get absolute path of", path, err)
346 }
347 res = append(res, abs)
348 }
349 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
350 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700351}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700352
Patrice Arrudab7b22822019-05-21 17:46:23 -0700353func stdio() terminal.StdioInterface {
354 return terminal.StdioImpl{}
355}
356
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700357func customStdio() terminal.StdioInterface {
358 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
359}
360
361// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
362func dumpVarConfig(ctx build.Context, args ...string) build.Config {
363 return build.NewConfig(ctx)
364}
365
Patrice Arrudab7b22822019-05-21 17:46:23 -0700366func buildActionConfig(ctx build.Context, args ...string) build.Config {
367 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
368 flags.Usage = func() {
369 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
370 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
371 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
372 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
373 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
374 fmt.Fprintln(ctx.Writer, "")
375 flags.PrintDefaults()
376 }
377
378 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700379 name string
380 description string
381 action build.BuildAction
382 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700383 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700384 name: "all-modules",
385 description: "Build action: build from the top of the source tree.",
386 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700387 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700388 // This is redirecting to mma build command behaviour. Once it has soaked for a
389 // while, the build command is deleted from here once it has been removed from the
390 // envsetup.sh.
391 name: "modules-in-a-dir-no-deps",
392 description: "Build action: builds all of the modules in the current directory without 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 // This is redirecting to mmma build command behaviour. Once it has soaked for a
396 // while, the build command is deleted from here once it has been removed from the
397 // envsetup.sh.
398 name: "modules-in-dirs-no-deps",
399 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
400 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700401 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700402 name: "modules-in-a-dir",
403 description: "Build action: builds all of the modules in the current directory and their dependencies.",
404 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700405 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700406 name: "modules-in-dirs",
407 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
408 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700409 }}
410 for i, flag := range buildActionFlags {
411 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
412 }
413 dir := flags.String("dir", "", "Directory of the executed build command.")
414
415 // Only interested in the first two args which defines the build action and the directory.
416 // The remaining arguments are passed down to the config.
417 const numBuildActionFlags = 2
418 if len(args) < numBuildActionFlags {
419 flags.Usage()
420 ctx.Fatalln("Improper build action arguments.")
421 }
422 flags.Parse(args[0:numBuildActionFlags])
423
424 // The next block of code is to validate that exactly one build action is set and the dir flag
425 // is specified.
426 buildActionCount := 0
427 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700428 for _, flag := range buildActionFlags {
429 if flag.set {
430 buildActionCount++
431 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700432 }
433 }
434 if buildActionCount != 1 {
435 ctx.Fatalln("Build action not defined.")
436 }
437 if *dir == "" {
438 ctx.Fatalln("-dir not specified.")
439 }
440
441 // Remove the build action flags from the args as they are not recognized by the config.
442 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700443 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700444}
445
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700446func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
447 if config.IsVerbose() {
448 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700449 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
450 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
451 fmt.Fprintln(writer, "!")
452 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
453 fmt.Fprintln(writer, "!")
454 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
455 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700456 select {
457 case <-time.After(5 * time.Second):
458 case <-ctx.Done():
459 return
460 }
461 }
462
463 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
464 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700465 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700466 fmt.Fprintln(writer, "!")
467 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
468 fmt.Fprintln(writer, "!")
469 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
470 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700471 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700472 }
473
Patrice Arruda0c1c4562020-11-11 13:01:25 -0800474 toBuild := build.BuildAll
475 if config.UseBazel() {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000476 toBuild = build.BuildAllWithBazel
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000477 }
478
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700479 if config.Checkbuild() {
480 toBuild |= build.RunBuildTests
481 }
482 build.Build(ctx, config, toBuild)
483}
484
485// getCommand finds the appropriate command based on args[1] flag. args[0]
486// is the soong_ui filename.
Liz Kammer0e7993e2020-10-15 11:07:13 -0700487func getCommand(args []string) (*command, []string, error) {
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700488 if len(args) < 2 {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700489 return nil, nil, fmt.Errorf("Too few arguments: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700490 }
491
492 for _, c := range commands {
493 if c.flag == args[1] {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700494 return &c, args[2:], nil
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700495 }
496
497 // special case for --make-mode: if soong_ui was called from
498 // build/make/core/main.mk, the makeparallel with --ninja
499 // option specified puts the -j<num> before --make-mode.
500 // TODO: Remove this hack once it has been fixed.
501 if c.flag == makeModeFlagName {
502 if inList(makeModeFlagName, args) {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700503 return &c, args[1:], nil
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700504 }
505 }
506 }
507
508 // command not found
Liz Kammer0e7993e2020-10-15 11:07:13 -0700509 return nil, nil, fmt.Errorf("Command not found: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700510}