github.com/MangoDowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/cmd/go/internal/envcmd/env.go (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package envcmd implements the ``go env'' command. 6 package envcmd 7 8 import ( 9 "encoding/json" 10 "fmt" 11 "os" 12 "runtime" 13 "strings" 14 15 "cmd/go/internal/base" 16 "cmd/go/internal/cfg" 17 "cmd/go/internal/load" 18 "cmd/go/internal/work" 19 ) 20 21 var CmdEnv = &base.Command{ 22 UsageLine: "env [-json] [var ...]", 23 Short: "print Go environment information", 24 Long: ` 25 Env prints Go environment information. 26 27 By default env prints information as a shell script 28 (on Windows, a batch file). If one or more variable 29 names is given as arguments, env prints the value of 30 each named variable on its own line. 31 32 The -json flag prints the environment in JSON format 33 instead of as a shell script. 34 `, 35 } 36 37 func init() { 38 CmdEnv.Run = runEnv // break init cycle 39 } 40 41 var envJson = CmdEnv.Flag.Bool("json", false, "") 42 43 func MkEnv() []cfg.EnvVar { 44 var b work.Builder 45 b.Init() 46 47 env := []cfg.EnvVar{ 48 {Name: "GOARCH", Value: cfg.Goarch}, 49 {Name: "GOBIN", Value: cfg.GOBIN}, 50 {Name: "GOEXE", Value: cfg.ExeSuffix}, 51 {Name: "GOHOSTARCH", Value: runtime.GOARCH}, 52 {Name: "GOHOSTOS", Value: runtime.GOOS}, 53 {Name: "GOOS", Value: cfg.Goos}, 54 {Name: "GOPATH", Value: cfg.BuildContext.GOPATH}, 55 {Name: "GORACE", Value: os.Getenv("GORACE")}, 56 {Name: "GOROOT", Value: cfg.GOROOT}, 57 {Name: "GOTOOLDIR", Value: base.ToolDir}, 58 59 // disable escape codes in clang errors 60 {Name: "TERM", Value: "dumb"}, 61 } 62 63 if work.GccgoBin != "" { 64 env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin}) 65 } else { 66 env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName}) 67 } 68 69 switch cfg.Goarch { 70 case "arm": 71 env = append(env, cfg.EnvVar{Name: "GOARM", Value: cfg.GOARM}) 72 case "386": 73 env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386}) 74 } 75 76 cmd := b.GccCmd(".") 77 env = append(env, cfg.EnvVar{Name: "CC", Value: cmd[0]}) 78 env = append(env, cfg.EnvVar{Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")}) 79 cmd = b.GxxCmd(".") 80 env = append(env, cfg.EnvVar{Name: "CXX", Value: cmd[0]}) 81 82 if cfg.BuildContext.CgoEnabled { 83 env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"}) 84 } else { 85 env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"}) 86 } 87 88 return env 89 } 90 91 func findEnv(env []cfg.EnvVar, name string) string { 92 for _, e := range env { 93 if e.Name == name { 94 return e.Value 95 } 96 } 97 return "" 98 } 99 100 // ExtraEnvVars returns environment variables that should not leak into child processes. 101 func ExtraEnvVars() []cfg.EnvVar { 102 var b work.Builder 103 b.Init() 104 cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{}) 105 if err != nil { 106 // Should not happen - b.CFlags was given an empty package. 107 fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err) 108 return nil 109 } 110 return []cfg.EnvVar{ 111 {Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")}, 112 {Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")}, 113 {Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")}, 114 {Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")}, 115 {Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")}, 116 {Name: "PKG_CONFIG", Value: b.PkgconfigCmd()}, 117 } 118 } 119 120 func runEnv(cmd *base.Command, args []string) { 121 env := cfg.CmdEnv 122 env = append(env, ExtraEnvVars()...) 123 if len(args) > 0 { 124 if *envJson { 125 var es []cfg.EnvVar 126 for _, name := range args { 127 e := cfg.EnvVar{Name: name, Value: findEnv(env, name)} 128 es = append(es, e) 129 } 130 printEnvAsJSON(es) 131 } else { 132 for _, name := range args { 133 fmt.Printf("%s\n", findEnv(env, name)) 134 } 135 } 136 return 137 } 138 139 if *envJson { 140 printEnvAsJSON(env) 141 return 142 } 143 144 for _, e := range env { 145 if e.Name != "TERM" { 146 switch runtime.GOOS { 147 default: 148 fmt.Printf("%s=\"%s\"\n", e.Name, e.Value) 149 case "plan9": 150 if strings.IndexByte(e.Value, '\x00') < 0 { 151 fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1)) 152 } else { 153 v := strings.Split(e.Value, "\x00") 154 fmt.Printf("%s=(", e.Name) 155 for x, s := range v { 156 if x > 0 { 157 fmt.Printf(" ") 158 } 159 fmt.Printf("%s", s) 160 } 161 fmt.Printf(")\n") 162 } 163 case "windows": 164 fmt.Printf("set %s=%s\n", e.Name, e.Value) 165 } 166 } 167 } 168 } 169 170 func printEnvAsJSON(env []cfg.EnvVar) { 171 m := make(map[string]string) 172 for _, e := range env { 173 if e.Name == "TERM" { 174 continue 175 } 176 m[e.Name] = e.Value 177 } 178 enc := json.NewEncoder(os.Stdout) 179 enc.SetIndent("", "\t") 180 if err := enc.Encode(m); err != nil { 181 base.Fatalf("%s", err) 182 } 183 }