github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/blueprint/bootstrap/command.go (about) 1 // Copyright 2014 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 bootstrap 16 17 import ( 18 "bytes" 19 "flag" 20 "fmt" 21 "io/ioutil" 22 "os" 23 "path/filepath" 24 "runtime" 25 "runtime/debug" 26 "runtime/pprof" 27 "runtime/trace" 28 29 "github.com/google/blueprint" 30 "github.com/google/blueprint/deptools" 31 ) 32 33 var ( 34 outFile string 35 depFile string 36 docFile string 37 cpuprofile string 38 memprofile string 39 traceFile string 40 runGoTests bool 41 noGC bool 42 moduleListFile string 43 44 BuildDir string 45 NinjaBuildDir string 46 SrcDir string 47 ) 48 49 func init() { 50 flag.StringVar(&outFile, "o", "build.ninja", "the Ninja file to output") 51 flag.StringVar(&BuildDir, "b", ".", "the build output directory") 52 flag.StringVar(&NinjaBuildDir, "n", "", "the ninja builddir directory") 53 flag.StringVar(&depFile, "d", "", "the dependency file to output") 54 flag.StringVar(&docFile, "docs", "", "build documentation file to output") 55 flag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file") 56 flag.StringVar(&traceFile, "trace", "", "write trace to file") 57 flag.StringVar(&memprofile, "memprofile", "", "write memory profile to file") 58 flag.BoolVar(&noGC, "nogc", false, "turn off GC for debugging") 59 flag.BoolVar(&runGoTests, "t", false, "build and run go tests during bootstrap") 60 flag.StringVar(&moduleListFile, "l", "", "file that lists filepaths to parse") 61 } 62 63 func Main(ctx *blueprint.Context, config interface{}, extraNinjaFileDeps ...string) { 64 if !flag.Parsed() { 65 flag.Parse() 66 } 67 68 runtime.GOMAXPROCS(runtime.NumCPU()) 69 70 if noGC { 71 debug.SetGCPercent(-1) 72 } 73 74 if cpuprofile != "" { 75 f, err := os.Create(cpuprofile) 76 if err != nil { 77 fatalf("error opening cpuprofile: %s", err) 78 } 79 pprof.StartCPUProfile(f) 80 defer f.Close() 81 defer pprof.StopCPUProfile() 82 } 83 84 if traceFile != "" { 85 f, err := os.Create(traceFile) 86 if err != nil { 87 fatalf("error opening trace: %s", err) 88 } 89 trace.Start(f) 90 defer f.Close() 91 defer trace.Stop() 92 } 93 94 if flag.NArg() != 1 { 95 fatalf("no Blueprints file specified") 96 } 97 98 SrcDir = filepath.Dir(flag.Arg(0)) 99 if moduleListFile != "" { 100 ctx.SetModuleListFile(moduleListFile) 101 extraNinjaFileDeps = append(extraNinjaFileDeps, moduleListFile) 102 } else { 103 fatalf("-l <moduleListFile> is required and must be nonempty") 104 } 105 filesToParse, err := ctx.ListModulePaths(SrcDir) 106 if err != nil { 107 fatalf("could not enumerate files: %v\n", err.Error()) 108 } 109 110 if NinjaBuildDir == "" { 111 NinjaBuildDir = BuildDir 112 } 113 114 stage := StageMain 115 if c, ok := config.(ConfigInterface); ok { 116 if c.GeneratingPrimaryBuilder() { 117 stage = StagePrimary 118 } 119 } 120 121 bootstrapConfig := &Config{ 122 stage: stage, 123 topLevelBlueprintsFile: flag.Arg(0), 124 runGoTests: runGoTests, 125 moduleListFile: moduleListFile, 126 } 127 128 ctx.RegisterBottomUpMutator("bootstrap_plugin_deps", pluginDeps) 129 ctx.RegisterModuleType("bootstrap_go_package", newGoPackageModuleFactory(bootstrapConfig)) 130 ctx.RegisterModuleType("bootstrap_go_binary", newGoBinaryModuleFactory(bootstrapConfig, false)) 131 ctx.RegisterModuleType("blueprint_go_binary", newGoBinaryModuleFactory(bootstrapConfig, true)) 132 ctx.RegisterSingletonType("bootstrap", newSingletonFactory(bootstrapConfig)) 133 134 ctx.RegisterSingletonType("glob", globSingletonFactory(ctx)) 135 136 deps, errs := ctx.ParseFileList(filepath.Dir(bootstrapConfig.topLevelBlueprintsFile), filesToParse) 137 if len(errs) > 0 { 138 fatalErrors(errs) 139 } 140 141 // Add extra ninja file dependencies 142 deps = append(deps, extraNinjaFileDeps...) 143 144 extraDeps, errs := ctx.ResolveDependencies(config) 145 if len(errs) > 0 { 146 fatalErrors(errs) 147 } 148 deps = append(deps, extraDeps...) 149 150 if docFile != "" { 151 err := writeDocs(ctx, docFile) 152 if err != nil { 153 fatalErrors([]error{err}) 154 } 155 return 156 } 157 158 if c, ok := config.(ConfigStopBefore); ok { 159 if c.StopBefore() == StopBeforePrepareBuildActions { 160 return 161 } 162 } 163 164 extraDeps, errs = ctx.PrepareBuildActions(config) 165 if len(errs) > 0 { 166 fatalErrors(errs) 167 } 168 deps = append(deps, extraDeps...) 169 170 buf := bytes.NewBuffer(nil) 171 err = ctx.WriteBuildFile(buf) 172 if err != nil { 173 fatalf("error generating Ninja file contents: %s", err) 174 } 175 176 const outFilePermissions = 0666 177 err = ioutil.WriteFile(outFile, buf.Bytes(), outFilePermissions) 178 if err != nil { 179 fatalf("error writing %s: %s", outFile, err) 180 } 181 182 if depFile != "" { 183 err := deptools.WriteDepFile(depFile, outFile, deps) 184 if err != nil { 185 fatalf("error writing depfile: %s", err) 186 } 187 } 188 189 if c, ok := config.(ConfigRemoveAbandonedFilesUnder); ok { 190 under := c.RemoveAbandonedFilesUnder() 191 err := removeAbandonedFilesUnder(ctx, bootstrapConfig, SrcDir, under) 192 if err != nil { 193 fatalf("error removing abandoned files: %s", err) 194 } 195 } 196 197 if memprofile != "" { 198 f, err := os.Create(memprofile) 199 if err != nil { 200 fatalf("error opening memprofile: %s", err) 201 } 202 defer f.Close() 203 pprof.WriteHeapProfile(f) 204 } 205 } 206 207 func fatalf(format string, args ...interface{}) { 208 fmt.Printf(format, args...) 209 fmt.Print("\n") 210 os.Exit(1) 211 } 212 213 func fatalErrors(errs []error) { 214 red := "\x1b[31m" 215 unred := "\x1b[0m" 216 217 for _, err := range errs { 218 switch err := err.(type) { 219 case *blueprint.BlueprintError, 220 *blueprint.ModuleError, 221 *blueprint.PropertyError: 222 fmt.Printf("%serror:%s %s\n", red, unred, err.Error()) 223 default: 224 fmt.Printf("%sinternal error:%s %s\n", red, unred, err) 225 } 226 } 227 os.Exit(1) 228 }