github.com/aca02djr/gb@v0.4.1/cmd/gb/build.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "os" 7 "path/filepath" 8 "runtime" 9 10 "github.com/constabulary/gb" 11 "github.com/constabulary/gb/cmd" 12 ) 13 14 func init() { 15 registerCommand(BuildCmd) 16 } 17 18 var ( 19 // build flags 20 21 // should we build all packages in this project. 22 // defaults to true when build is invoked from the project root. 23 A bool 24 25 // should we perform a release build +release tag ? 26 // defaults to false, +debug. 27 R bool 28 29 // force rebuild of packages 30 F bool 31 32 // skip caching of packages 33 FF bool 34 35 // enable race runtime 36 race bool 37 38 ldflags, gcflags []string 39 40 P int // number of executors to run in parallel 41 42 dotfile string // path to dot output file 43 44 buildtags []string 45 ) 46 47 func addBuildFlags(fs *flag.FlagSet) { 48 // TODO(dfc) this should accept a *gb.Context 49 fs.BoolVar(&A, "a", false, "build all packages in this project") 50 fs.BoolVar(&R, "r", false, "perform a release build") 51 fs.BoolVar(&F, "f", false, "rebuild up-to-date packages") 52 fs.BoolVar(&FF, "F", false, "do not cache built packages") 53 fs.BoolVar(&race, "race", false, "enable race detector") 54 fs.IntVar(&P, "P", runtime.NumCPU(), "number of parallel jobs") 55 fs.Var((*stringsFlag)(&ldflags), "ldflags", "flags passed to the linker") 56 fs.Var((*stringsFlag)(&gcflags), "gcflags", "flags passed to the compiler") 57 fs.StringVar(&dotfile, "dotfile", "", "path to dot output file") 58 fs.Var((*stringsFlag)(&buildtags), "tags", "") 59 } 60 61 var BuildCmd = &cmd.Command{ 62 Name: "build", 63 Short: "build a package", 64 UsageLine: "build [build flags] [packages]", 65 Long: ` 66 Build compiles the packages named by the import paths, along with their 67 dependencies. 68 69 Flags: 70 71 -f 72 ignore cached packages if present, new packages built will overwrite 73 any cached packages. This effectively disables incremental 74 compilation. 75 -F 76 do not cache packages, cached packages will still be used for 77 incremental compilation. -f -F is advised to disable the package 78 caching system. 79 -q 80 decreases verbosity, effectively raising the output level to ERROR. 81 In a successful build, no output will be displayed. 82 -P 83 The number of build jobs to run in parallel, including test execution. 84 By default this is the number of CPUs visible to gb. 85 -R 86 sets the base of the project root search path from the current working 87 directory to the value supplied. Effectively gb changes working 88 directory to this path before searching for the project root. 89 -dotfile 90 if provided, gb will output a dot formatted file of the build steps to 91 be performed. 92 -ldflags 'flag list' 93 arguments to pass on each linker invocation. 94 -gcflags 'arg list' 95 arguments to pass on each compile invocation. 96 -race 97 enable data race detection. 98 Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. 99 -tags 'tag list' 100 additional build tags. 101 102 The list flags accept a space-separated list of strings. To embed spaces in an 103 element in the list, surround it with either single or double quotes. 104 105 For more about where packages and binaries are installed, run 'gb help project'. 106 `, 107 Run: func(ctx *gb.Context, args []string) error { 108 // TODO(dfc) run should take a *gb.Context not a *gb.Project 109 ctx.Force = F 110 ctx.Install = !FF 111 112 pkgs, err := resolveRootPackages(ctx, args...) 113 if err != nil { 114 return err 115 } 116 117 build, err := gb.BuildPackages(pkgs...) 118 if err != nil { 119 return err 120 } 121 122 if dotfile != "" { 123 f, err := os.Create(dotfile) 124 if err != nil { 125 return err 126 } 127 defer f.Close() 128 printActions(f, build) 129 } 130 131 startSigHandlers() 132 return gb.ExecuteConcurrent(build, P, interrupted) 133 }, 134 AddFlags: addBuildFlags, 135 } 136 137 // Resolver resolves packages. 138 type Resolver interface { 139 Projectdir() string 140 // ResolvePackage resolves the import path to a *Package 141 ResolvePackage(path string) (*gb.Package, error) 142 } 143 144 // resolveRootPackages resolves import paths into packages. 145 // Only packages which exist inside $PROJECT/src are elegable to be 146 // roots to build or test. Other import paths are discarded. 147 func resolveRootPackages(r Resolver, paths ...string) ([]*gb.Package, error) { 148 var pkgs []*gb.Package 149 for _, path := range paths { 150 pkg, err := r.ResolvePackage(path) 151 if err != nil { 152 return pkgs, fmt.Errorf("failed to resolve import path %q: %v", path, err) 153 } 154 if pkg.SrcRoot == filepath.Join(runtime.GOROOT(), "src") { 155 // skip package roots that are not part of this project. 156 // TODO(dfc) should gb return an error here? 157 continue 158 } 159 pkgs = append(pkgs, pkg) 160 } 161 return pkgs, nil 162 }