libgo: update to Go1.10rc2
[official-gcc.git] / libgo / go / cmd / go / internal / envcmd / env.go
blob603f7b5060c98522a930c380effa9e7eaa8b0581
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.
5 // Package envcmd implements the ``go env'' command.
6 package envcmd
8 import (
9 "encoding/json"
10 "fmt"
11 "os"
12 "runtime"
13 "strings"
15 "cmd/go/internal/base"
16 "cmd/go/internal/cache"
17 "cmd/go/internal/cfg"
18 "cmd/go/internal/load"
19 "cmd/go/internal/work"
22 var CmdEnv = &base.Command{
23 UsageLine: "env [-json] [var ...]",
24 Short: "print Go environment information",
25 Long: `
26 Env prints Go environment information.
28 By default env prints information as a shell script
29 (on Windows, a batch file). If one or more variable
30 names is given as arguments, env prints the value of
31 each named variable on its own line.
33 The -json flag prints the environment in JSON format
34 instead of as a shell script.
36 For more about environment variables, see 'go help environment'.
40 func init() {
41 CmdEnv.Run = runEnv // break init cycle
44 var envJson = CmdEnv.Flag.Bool("json", false, "")
46 func MkEnv() []cfg.EnvVar {
47 var b work.Builder
48 b.Init()
50 env := []cfg.EnvVar{
51 {Name: "GOARCH", Value: cfg.Goarch},
52 {Name: "GOBIN", Value: cfg.GOBIN},
53 {Name: "GOCACHE", Value: cache.DefaultDir()},
54 {Name: "GOEXE", Value: cfg.ExeSuffix},
55 {Name: "GOHOSTARCH", Value: runtime.GOARCH},
56 {Name: "GOHOSTOS", Value: runtime.GOOS},
57 {Name: "GOOS", Value: cfg.Goos},
58 {Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
59 {Name: "GORACE", Value: os.Getenv("GORACE")},
60 {Name: "GOROOT", Value: cfg.GOROOT},
61 {Name: "GOTMPDIR", Value: os.Getenv("GOTMPDIR")},
62 {Name: "GOTOOLDIR", Value: base.ToolDir},
64 // disable escape codes in clang errors
65 {Name: "TERM", Value: "dumb"},
68 if work.GccgoBin != "" {
69 env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin})
70 } else {
71 env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName})
74 switch cfg.Goarch {
75 case "arm":
76 env = append(env, cfg.EnvVar{Name: "GOARM", Value: cfg.GOARM})
77 case "386":
78 env = append(env, cfg.EnvVar{Name: "GO386", Value: cfg.GO386})
79 case "mips", "mipsle":
80 env = append(env, cfg.EnvVar{Name: "GOMIPS", Value: cfg.GOMIPS})
83 cc := cfg.DefaultCC(cfg.Goos, cfg.Goarch)
84 if env := strings.Fields(os.Getenv("CC")); len(env) > 0 {
85 cc = env[0]
87 cxx := cfg.DefaultCXX(cfg.Goos, cfg.Goarch)
88 if env := strings.Fields(os.Getenv("CXX")); len(env) > 0 {
89 cxx = env[0]
91 env = append(env, cfg.EnvVar{Name: "CC", Value: cc})
92 env = append(env, cfg.EnvVar{Name: "CXX", Value: cxx})
94 if cfg.BuildContext.CgoEnabled {
95 env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"})
96 } else {
97 env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"})
100 return env
103 func findEnv(env []cfg.EnvVar, name string) string {
104 for _, e := range env {
105 if e.Name == name {
106 return e.Value
109 return ""
112 // ExtraEnvVars returns environment variables that should not leak into child processes.
113 func ExtraEnvVars() []cfg.EnvVar {
114 var b work.Builder
115 b.Init()
116 cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{})
117 if err != nil {
118 // Should not happen - b.CFlags was given an empty package.
119 fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err)
120 return nil
122 cmd := b.GccCmd(".", "")
123 return []cfg.EnvVar{
124 // Note: Update the switch in runEnv below when adding to this list.
125 {Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")},
126 {Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")},
127 {Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")},
128 {Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")},
129 {Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")},
130 {Name: "PKG_CONFIG", Value: b.PkgconfigCmd()},
131 {Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")},
135 func runEnv(cmd *base.Command, args []string) {
136 env := cfg.CmdEnv
138 // Do we need to call ExtraEnvVars, which is a bit expensive?
139 // Only if we're listing all environment variables ("go env")
140 // or the variables being requested are in the extra list.
141 needExtra := true
142 if len(args) > 0 {
143 needExtra = false
144 for _, arg := range args {
145 switch arg {
146 case "CGO_CFLAGS",
147 "CGO_CPPFLAGS",
148 "CGO_CXXFLAGS",
149 "CGO_FFLAGS",
150 "CGO_LDFLAGS",
151 "PKG_CONFIG",
152 "GOGCCFLAGS":
153 needExtra = true
157 if needExtra {
158 env = append(env, ExtraEnvVars()...)
161 if len(args) > 0 {
162 if *envJson {
163 var es []cfg.EnvVar
164 for _, name := range args {
165 e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
166 es = append(es, e)
168 printEnvAsJSON(es)
169 } else {
170 for _, name := range args {
171 fmt.Printf("%s\n", findEnv(env, name))
174 return
177 if *envJson {
178 printEnvAsJSON(env)
179 return
182 for _, e := range env {
183 if e.Name != "TERM" {
184 switch runtime.GOOS {
185 default:
186 fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
187 case "plan9":
188 if strings.IndexByte(e.Value, '\x00') < 0 {
189 fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1))
190 } else {
191 v := strings.Split(e.Value, "\x00")
192 fmt.Printf("%s=(", e.Name)
193 for x, s := range v {
194 if x > 0 {
195 fmt.Printf(" ")
197 fmt.Printf("%s", s)
199 fmt.Printf(")\n")
201 case "windows":
202 fmt.Printf("set %s=%s\n", e.Name, e.Value)
208 func printEnvAsJSON(env []cfg.EnvVar) {
209 m := make(map[string]string)
210 for _, e := range env {
211 if e.Name == "TERM" {
212 continue
214 m[e.Name] = e.Value
216 enc := json.NewEncoder(os.Stdout)
217 enc.SetIndent("", "\t")
218 if err := enc.Encode(m); err != nil {
219 base.Fatalf("%s", err)