blob: 29030d69e36a2e2d2251fdbd63184528d525d307 [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
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800128 // Create a terminal output that mimics Ninja's.
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000129 output := terminal.NewStatusOutput(c.stdio().Stdout(), os.Getenv("NINJA_STATUS"), c.simpleOutput,
Colin Crosse0df1a32019-06-09 19:40:08 -0700130 build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700131
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800132 // Attach a new logger instance to the terminal output.
Colin Crosse0df1a32019-06-09 19:40:08 -0700133 log := logger.New(output)
Dan Willemsen1e704462016-08-21 15:17:17 -0700134 defer log.Cleanup()
135
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800136 // Create a context to simplify the program termination process.
Dan Willemsen1e704462016-08-21 15:17:17 -0700137 ctx, cancel := context.WithCancel(context.Background())
138 defer cancel()
139
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800140 // Create a new trace file writer, making it log events to the log instance.
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700141 trace := tracer.New(log)
142 defer trace.Close()
Dan Willemsen1e704462016-08-21 15:17:17 -0700143
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800144 // Create and start a new metric record.
Nan Zhang17f27672018-12-12 16:01:49 -0800145 met := metrics.New()
Patrice Arruda73c790f2020-07-13 23:01:18 +0000146 met.SetBuildDateTime(buildStarted)
Patrice Arrudae92c30d2020-10-29 11:01:32 -0700147 met.SetBuildCommand(os.Args)
Nan Zhang17f27672018-12-12 16:01:49 -0800148
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800149 // Create a new Status instance, which manages action counts and event output channels.
Dan Willemsenb82471a2018-05-17 16:37:09 -0700150 stat := &status.Status{}
151 defer stat.Finish()
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800152 // Hook up the terminal output and tracer to Status.
Colin Crosse0df1a32019-06-09 19:40:08 -0700153 stat.AddOutput(output)
Dan Willemsenb82471a2018-05-17 16:37:09 -0700154 stat.AddOutput(trace.StatusTracer())
155
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800156 // Set up a cleanup procedure in case the normal termination process doesn't work.
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700157 build.SetupSignals(log, cancel, func() {
158 trace.Close()
159 log.Cleanup()
Dan Willemsenb82471a2018-05-17 16:37:09 -0700160 stat.Finish()
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700161 })
162
Dan Willemsen59339a22018-07-22 21:18:45 -0700163 buildCtx := build.Context{ContextImpl: &build.ContextImpl{
Dan Willemsenb82471a2018-05-17 16:37:09 -0700164 Context: ctx,
165 Logger: log,
Nan Zhang17f27672018-12-12 16:01:49 -0800166 Metrics: met,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700167 Tracer: trace,
Colin Crosse0df1a32019-06-09 19:40:08 -0700168 Writer: output,
Dan Willemsenb82471a2018-05-17 16:37:09 -0700169 Status: stat,
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700170 }}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700171
172 config := c.config(buildCtx, args...)
Dan Willemsen1e704462016-08-21 15:17:17 -0700173
Dan Willemsend9f6fa22016-08-21 15:17:17 -0700174 build.SetupOutDir(buildCtx, config)
Dan Willemsen8a073a82017-02-04 17:30:44 -0800175
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800176 // Set up files to be outputted in the log directory.
Dan Willemsenb82471a2018-05-17 16:37:09 -0700177 logsDir := config.OutDir()
Dan Willemsen8a073a82017-02-04 17:30:44 -0800178 if config.Dist() {
Dan Willemsenb82471a2018-05-17 16:37:09 -0700179 logsDir = filepath.Join(config.DistDir(), "logs")
Dan Willemsen8a073a82017-02-04 17:30:44 -0800180 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700181
Patrice Arruda219eef32020-06-01 17:29:30 +0000182 buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
183 rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
184 soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
Patrice Arrudaf445ba12020-07-28 17:49:01 +0000185 defer build.UploadMetrics(buildCtx, config, c.simpleOutput, buildStarted, buildErrorFile, rbeMetricsFile, soongMetricsFile)
Kousik Kumara0a44a82020-10-08 02:33:29 -0400186 build.PrintOutDirWarning(buildCtx, config)
Patrice Arruda219eef32020-06-01 17:29:30 +0000187
Dan Willemsenb82471a2018-05-17 16:37:09 -0700188 os.MkdirAll(logsDir, 0777)
Colin Crossc0b9f6b2019-09-23 12:44:54 -0700189 log.SetOutput(filepath.Join(logsDir, c.logsPrefix+"soong.log"))
190 trace.SetOutput(filepath.Join(logsDir, c.logsPrefix+"build.trace"))
191 stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, c.logsPrefix+"verbose.log")))
192 stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, c.logsPrefix+"error.log")))
Patrice Arruda219eef32020-06-01 17:29:30 +0000193 stat.AddOutput(status.NewProtoErrorLog(log, buildErrorFile))
Colin Cross7b624532019-06-21 15:08:30 -0700194 stat.AddOutput(status.NewCriticalPath(log))
Patrice Arruda74b43992020-03-11 08:21:05 -0700195 stat.AddOutput(status.NewBuildProgressLog(log, filepath.Join(logsDir, c.logsPrefix+"build_progress.pb")))
Dan Willemsenb82471a2018-05-17 16:37:09 -0700196
Colin Cross8b8bec32019-11-15 13:18:43 -0800197 buildCtx.Verbosef("Detected %.3v GB total RAM", float32(config.TotalRAM())/(1024*1024*1024))
198 buildCtx.Verbosef("Parallelism (local/remote/highmem): %v/%v/%v",
199 config.Parallel(), config.RemoteParallel(), config.HighmemParallel())
200
Patrice Arruda219eef32020-06-01 17:29:30 +0000201 defer met.Dump(soongMetricsFile)
Patrice Arruda62f1bf22020-07-07 12:48:26 +0000202 defer build.DumpRBEMetrics(buildCtx, config, rbeMetricsFile)
Nan Zhangd50f53b2019-01-07 20:26:51 -0800203
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800204 // Read the time at the starting point.
Dan Willemsen1e704462016-08-21 15:17:17 -0700205 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800206 // soong_ui.bash uses the date command's %N (nanosec) flag when getting the start time,
207 // which Darwin doesn't support. Check if it was executed properly before parsing the value.
Dan Willemsen1e704462016-08-21 15:17:17 -0700208 if !strings.HasSuffix(start, "N") {
209 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
210 log.Verbosef("Took %dms to start up.",
211 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
Nan Zhang17f27672018-12-12 16:01:49 -0800212 buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
Dan Willemsen1e704462016-08-21 15:17:17 -0700213 }
214 }
Dan Willemsencae59bc2017-07-13 14:27:31 -0700215
216 if executable, err := os.Executable(); err == nil {
217 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
218 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700219 }
220
Dan Willemsen6b783c82019-03-08 11:42:28 -0800221 // Fix up the source tree due to a repo bug where it doesn't remove
222 // linkfiles that have been removed
223 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
224 fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
225
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800226 // Create a source finder.
Jeff Gastonb64fc1c2017-08-04 12:30:12 -0700227 f := build.NewSourceFinder(buildCtx, config)
228 defer f.Shutdown()
229 build.FindSources(buildCtx, config, f)
230
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700231 c.run(buildCtx, config, args, logsDir)
Dan Willemsen051133b2017-07-14 11:29:29 -0700232}
233
Dan Willemsen6b783c82019-03-08 11:42:28 -0800234func fixBadDanglingLink(ctx build.Context, name string) {
235 _, err := os.Lstat(name)
236 if err != nil {
237 return
238 }
239 _, err = os.Stat(name)
240 if os.IsNotExist(err) {
241 err = os.Remove(name)
242 if err != nil {
243 ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
244 }
245 }
246}
247
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700248func dumpVar(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700249 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
250 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700251 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0])
252 fmt.Fprintln(ctx.Writer, "In dumpvar mode, print the value of the legacy make variable VAR to stdout")
253 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700254
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700255 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that prints the human-readable config banner")
256 fmt.Fprintln(ctx.Writer, "from the beginning of the build.")
257 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700258 flags.PrintDefaults()
259 }
260 abs := flags.Bool("abs", false, "Print the absolute path of the value")
261 flags.Parse(args)
262
263 if flags.NArg() != 1 {
264 flags.Usage()
265 os.Exit(1)
266 }
267
268 varName := flags.Arg(0)
269 if varName == "report_config" {
270 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars)
271 if err != nil {
272 ctx.Fatal(err)
273 }
274
275 fmt.Println(build.Banner(varData))
276 } else {
277 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName})
278 if err != nil {
279 ctx.Fatal(err)
280 }
281
282 if *abs {
283 var res []string
284 for _, path := range strings.Fields(varData[varName]) {
285 if abs, err := filepath.Abs(path); err == nil {
286 res = append(res, abs)
287 } else {
288 ctx.Fatalln("Failed to get absolute path of", path, err)
289 }
290 }
291 fmt.Println(strings.Join(res, " "))
292 } else {
293 fmt.Println(varData[varName])
294 }
295 }
296}
297
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700298func dumpVars(ctx build.Context, config build.Config, args []string, _ string) {
Dan Willemsen051133b2017-07-14 11:29:29 -0700299 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
300 flags.Usage = func() {
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700301 fmt.Fprintf(ctx.Writer, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0])
302 fmt.Fprintln(ctx.Writer, "In dumpvars mode, dump the values of one or more legacy make variables, in")
303 fmt.Fprintln(ctx.Writer, "shell syntax. The resulting output may be sourced directly into a shell to")
304 fmt.Fprintln(ctx.Writer, "set corresponding shell variables.")
305 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700306
Patrice Arrudadb4c2f12019-06-17 17:27:09 -0700307 fmt.Fprintln(ctx.Writer, "'report_config' is a special case that dumps a variable containing the")
308 fmt.Fprintln(ctx.Writer, "human-readable config banner from the beginning of the build.")
309 fmt.Fprintln(ctx.Writer, "")
Dan Willemsen051133b2017-07-14 11:29:29 -0700310 flags.PrintDefaults()
311 }
312
313 varsStr := flags.String("vars", "", "Space-separated list of variables to dump")
314 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)")
315
316 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping")
317 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping")
318
319 flags.Parse(args)
320
321 if flags.NArg() != 0 {
322 flags.Usage()
323 os.Exit(1)
324 }
325
326 vars := strings.Fields(*varsStr)
327 absVars := strings.Fields(*absVarsStr)
328
329 allVars := append([]string{}, vars...)
330 allVars = append(allVars, absVars...)
331
332 if i := indexList("report_config", allVars); i != -1 {
333 allVars = append(allVars[:i], allVars[i+1:]...)
334 allVars = append(allVars, build.BannerVars...)
335 }
336
337 if len(allVars) == 0 {
338 return
339 }
340
341 varData, err := build.DumpMakeVars(ctx, config, nil, allVars)
342 if err != nil {
343 ctx.Fatal(err)
344 }
345
346 for _, name := range vars {
347 if name == "report_config" {
348 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData))
349 } else {
350 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name])
351 }
352 }
353 for _, name := range absVars {
354 var res []string
355 for _, path := range strings.Fields(varData[name]) {
356 abs, err := filepath.Abs(path)
357 if err != nil {
358 ctx.Fatalln("Failed to get absolute path of", path, err)
359 }
360 res = append(res, abs)
361 }
362 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " "))
363 }
Dan Willemsen1e704462016-08-21 15:17:17 -0700364}
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700365
Patrice Arrudab7b22822019-05-21 17:46:23 -0700366func stdio() terminal.StdioInterface {
367 return terminal.StdioImpl{}
368}
369
Jaewoong Jung9f98d3f2020-11-17 18:20:14 -0800370// dumpvar and dumpvars use stdout to output variable values, so use stderr instead of stdout when
371// reporting events to keep stdout clean from noise.
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700372func customStdio() terminal.StdioInterface {
373 return terminal.NewCustomStdio(os.Stdin, os.Stderr, os.Stderr)
374}
375
376// dumpVarConfig does not require any arguments to be parsed by the NewConfig.
377func dumpVarConfig(ctx build.Context, args ...string) build.Config {
378 return build.NewConfig(ctx)
379}
380
Patrice Arrudab7b22822019-05-21 17:46:23 -0700381func buildActionConfig(ctx build.Context, args ...string) build.Config {
382 flags := flag.NewFlagSet("build-mode", flag.ContinueOnError)
383 flags.Usage = func() {
384 fmt.Fprintf(ctx.Writer, "usage: %s --build-mode --dir=<path> <build action> [<build arg 1> <build arg 2> ...]\n\n", os.Args[0])
385 fmt.Fprintln(ctx.Writer, "In build mode, build the set of modules based on the specified build")
386 fmt.Fprintln(ctx.Writer, "action. The --dir flag is required to determine what is needed to")
387 fmt.Fprintln(ctx.Writer, "build in the source tree based on the build action. See below for")
388 fmt.Fprintln(ctx.Writer, "the list of acceptable build action flags.")
389 fmt.Fprintln(ctx.Writer, "")
390 flags.PrintDefaults()
391 }
392
393 buildActionFlags := []struct {
Dan Willemsence41e942019-07-29 23:39:30 -0700394 name string
395 description string
396 action build.BuildAction
397 set bool
Patrice Arrudab7b22822019-05-21 17:46:23 -0700398 }{{
Dan Willemsence41e942019-07-29 23:39:30 -0700399 name: "all-modules",
400 description: "Build action: build from the top of the source tree.",
401 action: build.BUILD_MODULES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700402 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700403 // This is redirecting to mma build command behaviour. Once it has soaked for a
404 // while, the build command is deleted from here once it has been removed from the
405 // envsetup.sh.
406 name: "modules-in-a-dir-no-deps",
407 description: "Build action: builds all of the modules in the current directory without their dependencies.",
408 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700409 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700410 // This is redirecting to mmma build command behaviour. Once it has soaked for a
411 // while, the build command is deleted from here once it has been removed from the
412 // envsetup.sh.
413 name: "modules-in-dirs-no-deps",
414 description: "Build action: builds all of the modules in the supplied directories without their dependencies.",
415 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700416 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700417 name: "modules-in-a-dir",
418 description: "Build action: builds all of the modules in the current directory and their dependencies.",
419 action: build.BUILD_MODULES_IN_A_DIRECTORY,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700420 }, {
Dan Willemsence41e942019-07-29 23:39:30 -0700421 name: "modules-in-dirs",
422 description: "Build action: builds all of the modules in the supplied directories and their dependencies.",
423 action: build.BUILD_MODULES_IN_DIRECTORIES,
Patrice Arrudab7b22822019-05-21 17:46:23 -0700424 }}
425 for i, flag := range buildActionFlags {
426 flags.BoolVar(&buildActionFlags[i].set, flag.name, false, flag.description)
427 }
428 dir := flags.String("dir", "", "Directory of the executed build command.")
429
430 // Only interested in the first two args which defines the build action and the directory.
431 // The remaining arguments are passed down to the config.
432 const numBuildActionFlags = 2
433 if len(args) < numBuildActionFlags {
434 flags.Usage()
435 ctx.Fatalln("Improper build action arguments.")
436 }
437 flags.Parse(args[0:numBuildActionFlags])
438
439 // The next block of code is to validate that exactly one build action is set and the dir flag
440 // is specified.
441 buildActionCount := 0
442 var buildAction build.BuildAction
Patrice Arrudab7b22822019-05-21 17:46:23 -0700443 for _, flag := range buildActionFlags {
444 if flag.set {
445 buildActionCount++
446 buildAction = flag.action
Patrice Arrudab7b22822019-05-21 17:46:23 -0700447 }
448 }
449 if buildActionCount != 1 {
450 ctx.Fatalln("Build action not defined.")
451 }
452 if *dir == "" {
453 ctx.Fatalln("-dir not specified.")
454 }
455
456 // Remove the build action flags from the args as they are not recognized by the config.
457 args = args[numBuildActionFlags:]
Dan Willemsence41e942019-07-29 23:39:30 -0700458 return build.NewBuildActionConfig(buildAction, *dir, ctx, args...)
Patrice Arrudab7b22822019-05-21 17:46:23 -0700459}
460
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700461func make(ctx build.Context, config build.Config, _ []string, logsDir string) {
462 if config.IsVerbose() {
463 writer := ctx.Writer
Colin Cross097ed2a2019-06-08 21:48:58 -0700464 fmt.Fprintln(writer, "! The argument `showcommands` is no longer supported.")
465 fmt.Fprintln(writer, "! Instead, the verbose log is always written to a compressed file in the output dir:")
466 fmt.Fprintln(writer, "!")
467 fmt.Fprintf(writer, "! gzip -cd %s/verbose.log.gz | less -R\n", logsDir)
468 fmt.Fprintln(writer, "!")
469 fmt.Fprintln(writer, "! Older versions are saved in verbose.log.#.gz files")
470 fmt.Fprintln(writer, "")
Dan Willemsenc6360832019-07-25 14:07:36 -0700471 select {
472 case <-time.After(5 * time.Second):
473 case <-ctx.Done():
474 return
475 }
476 }
477
478 if _, ok := config.Environment().Get("ONE_SHOT_MAKEFILE"); ok {
479 writer := ctx.Writer
Dan Willemsence41e942019-07-29 23:39:30 -0700480 fmt.Fprintln(writer, "! The variable `ONE_SHOT_MAKEFILE` is obsolete.")
Dan Willemsenc6360832019-07-25 14:07:36 -0700481 fmt.Fprintln(writer, "!")
482 fmt.Fprintln(writer, "! If you're using `mm`, you'll need to run `source build/envsetup.sh` to update.")
483 fmt.Fprintln(writer, "!")
484 fmt.Fprintln(writer, "! Otherwise, either specify a module name with m, or use mma / MODULES-IN-...")
485 fmt.Fprintln(writer, "")
Dan Willemsence41e942019-07-29 23:39:30 -0700486 ctx.Fatal("done")
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700487 }
488
Patrice Arruda0c1c4562020-11-11 13:01:25 -0800489 toBuild := build.BuildAll
490 if config.UseBazel() {
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000491 toBuild = build.BuildAllWithBazel
Rupert Shuttleworth680387b2020-10-25 12:31:27 +0000492 }
493
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700494 if config.Checkbuild() {
495 toBuild |= build.RunBuildTests
496 }
497 build.Build(ctx, config, toBuild)
498}
499
500// getCommand finds the appropriate command based on args[1] flag. args[0]
501// is the soong_ui filename.
Liz Kammer0e7993e2020-10-15 11:07:13 -0700502func getCommand(args []string) (*command, []string, error) {
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700503 if len(args) < 2 {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700504 return nil, nil, fmt.Errorf("Too few arguments: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700505 }
506
507 for _, c := range commands {
508 if c.flag == args[1] {
Liz Kammer0e7993e2020-10-15 11:07:13 -0700509 return &c, args[2:], nil
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700510 }
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700511 }
512
513 // command not found
Liz Kammer0e7993e2020-10-15 11:07:13 -0700514 return nil, nil, fmt.Errorf("Command not found: %q", args)
Patrice Arrudaa5c25422019-04-09 18:49:49 -0700515}