github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cmd/soong_ui/main.go (about) 1 // 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 15 package main 16 17 import ( 18 "context" 19 "flag" 20 "fmt" 21 "os" 22 "path/filepath" 23 "strconv" 24 "strings" 25 "time" 26 27 "android/soong/ui/build" 28 "android/soong/ui/logger" 29 "android/soong/ui/tracer" 30 ) 31 32 func indexList(s string, list []string) int { 33 for i, l := range list { 34 if l == s { 35 return i 36 } 37 } 38 39 return -1 40 } 41 42 func inList(s string, list []string) bool { 43 return indexList(s, list) != -1 44 } 45 46 func main() { 47 log := logger.New(os.Stderr) 48 defer log.Cleanup() 49 50 if len(os.Args) < 2 || !(inList("--make-mode", os.Args) || 51 os.Args[1] == "--dumpvars-mode" || 52 os.Args[1] == "--dumpvar-mode") { 53 54 log.Fatalln("The `soong` native UI is not yet available.") 55 } 56 57 ctx, cancel := context.WithCancel(context.Background()) 58 defer cancel() 59 60 trace := tracer.New(log) 61 defer trace.Close() 62 63 build.SetupSignals(log, cancel, func() { 64 trace.Close() 65 log.Cleanup() 66 }) 67 68 buildCtx := build.Context{&build.ContextImpl{ 69 Context: ctx, 70 Logger: log, 71 Tracer: trace, 72 StdioInterface: build.StdioImpl{}, 73 }} 74 var config build.Config 75 if os.Args[1] == "--dumpvars-mode" || os.Args[1] == "--dumpvar-mode" { 76 config = build.NewConfig(buildCtx) 77 } else { 78 config = build.NewConfig(buildCtx, os.Args[1:]...) 79 } 80 81 log.SetVerbose(config.IsVerbose()) 82 build.SetupOutDir(buildCtx, config) 83 84 if config.Dist() { 85 logsDir := filepath.Join(config.DistDir(), "logs") 86 os.MkdirAll(logsDir, 0777) 87 log.SetOutput(filepath.Join(logsDir, "soong.log")) 88 trace.SetOutput(filepath.Join(logsDir, "build.trace")) 89 } else { 90 log.SetOutput(filepath.Join(config.OutDir(), "soong.log")) 91 trace.SetOutput(filepath.Join(config.OutDir(), "build.trace")) 92 } 93 94 if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok { 95 if !strings.HasSuffix(start, "N") { 96 if start_time, err := strconv.ParseUint(start, 10, 64); err == nil { 97 log.Verbosef("Took %dms to start up.", 98 time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds()) 99 buildCtx.CompleteTrace("startup", start_time, uint64(time.Now().UnixNano())) 100 } 101 } 102 103 if executable, err := os.Executable(); err == nil { 104 trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace")) 105 } 106 } 107 108 f := build.NewSourceFinder(buildCtx, config) 109 defer f.Shutdown() 110 build.FindSources(buildCtx, config, f) 111 112 if os.Args[1] == "--dumpvar-mode" { 113 dumpVar(buildCtx, config, os.Args[2:]) 114 } else if os.Args[1] == "--dumpvars-mode" { 115 dumpVars(buildCtx, config, os.Args[2:]) 116 } else { 117 toBuild := build.BuildAll 118 if config.Checkbuild() { 119 toBuild |= build.RunBuildTests 120 } 121 build.Build(buildCtx, config, toBuild) 122 } 123 } 124 125 func dumpVar(ctx build.Context, config build.Config, args []string) { 126 flags := flag.NewFlagSet("dumpvar", flag.ExitOnError) 127 flags.Usage = func() { 128 fmt.Fprintf(os.Stderr, "usage: %s --dumpvar-mode [--abs] <VAR>\n\n", os.Args[0]) 129 fmt.Fprintln(os.Stderr, "In dumpvar mode, print the value of the legacy make variable VAR to stdout") 130 fmt.Fprintln(os.Stderr, "") 131 132 fmt.Fprintln(os.Stderr, "'report_config' is a special case that prints the human-readable config banner") 133 fmt.Fprintln(os.Stderr, "from the beginning of the build.") 134 fmt.Fprintln(os.Stderr, "") 135 flags.PrintDefaults() 136 } 137 abs := flags.Bool("abs", false, "Print the absolute path of the value") 138 flags.Parse(args) 139 140 if flags.NArg() != 1 { 141 flags.Usage() 142 os.Exit(1) 143 } 144 145 varName := flags.Arg(0) 146 if varName == "report_config" { 147 varData, err := build.DumpMakeVars(ctx, config, nil, build.BannerVars) 148 if err != nil { 149 ctx.Fatal(err) 150 } 151 152 fmt.Println(build.Banner(varData)) 153 } else { 154 varData, err := build.DumpMakeVars(ctx, config, nil, []string{varName}) 155 if err != nil { 156 ctx.Fatal(err) 157 } 158 159 if *abs { 160 var res []string 161 for _, path := range strings.Fields(varData[varName]) { 162 if abs, err := filepath.Abs(path); err == nil { 163 res = append(res, abs) 164 } else { 165 ctx.Fatalln("Failed to get absolute path of", path, err) 166 } 167 } 168 fmt.Println(strings.Join(res, " ")) 169 } else { 170 fmt.Println(varData[varName]) 171 } 172 } 173 } 174 175 func dumpVars(ctx build.Context, config build.Config, args []string) { 176 flags := flag.NewFlagSet("dumpvars", flag.ExitOnError) 177 flags.Usage = func() { 178 fmt.Fprintf(os.Stderr, "usage: %s --dumpvars-mode [--vars=\"VAR VAR ...\"]\n\n", os.Args[0]) 179 fmt.Fprintln(os.Stderr, "In dumpvars mode, dump the values of one or more legacy make variables, in") 180 fmt.Fprintln(os.Stderr, "shell syntax. The resulting output may be sourced directly into a shell to") 181 fmt.Fprintln(os.Stderr, "set corresponding shell variables.") 182 fmt.Fprintln(os.Stderr, "") 183 184 fmt.Fprintln(os.Stderr, "'report_config' is a special case that dumps a variable containing the") 185 fmt.Fprintln(os.Stderr, "human-readable config banner from the beginning of the build.") 186 fmt.Fprintln(os.Stderr, "") 187 flags.PrintDefaults() 188 } 189 190 varsStr := flags.String("vars", "", "Space-separated list of variables to dump") 191 absVarsStr := flags.String("abs-vars", "", "Space-separated list of variables to dump (using absolute paths)") 192 193 varPrefix := flags.String("var-prefix", "", "String to prepend to all variable names when dumping") 194 absVarPrefix := flags.String("abs-var-prefix", "", "String to prepent to all absolute path variable names when dumping") 195 196 flags.Parse(args) 197 198 if flags.NArg() != 0 { 199 flags.Usage() 200 os.Exit(1) 201 } 202 203 vars := strings.Fields(*varsStr) 204 absVars := strings.Fields(*absVarsStr) 205 206 allVars := append([]string{}, vars...) 207 allVars = append(allVars, absVars...) 208 209 if i := indexList("report_config", allVars); i != -1 { 210 allVars = append(allVars[:i], allVars[i+1:]...) 211 allVars = append(allVars, build.BannerVars...) 212 } 213 214 if len(allVars) == 0 { 215 return 216 } 217 218 varData, err := build.DumpMakeVars(ctx, config, nil, allVars) 219 if err != nil { 220 ctx.Fatal(err) 221 } 222 223 for _, name := range vars { 224 if name == "report_config" { 225 fmt.Printf("%sreport_config='%s'\n", *varPrefix, build.Banner(varData)) 226 } else { 227 fmt.Printf("%s%s='%s'\n", *varPrefix, name, varData[name]) 228 } 229 } 230 for _, name := range absVars { 231 var res []string 232 for _, path := range strings.Fields(varData[name]) { 233 abs, err := filepath.Abs(path) 234 if err != nil { 235 ctx.Fatalln("Failed to get absolute path of", path, err) 236 } 237 res = append(res, abs) 238 } 239 fmt.Printf("%s%s='%s'\n", *absVarPrefix, name, strings.Join(res, " ")) 240 } 241 }