Source file src/pkg/cmd/go/internal/cfg/cfg.go
1
2
3
4
5
6
7 package cfg
8
9 import (
10 "bytes"
11 "fmt"
12 "go/build"
13 "internal/cfg"
14 "io/ioutil"
15 "os"
16 "path/filepath"
17 "runtime"
18 "strings"
19 "sync"
20
21 "cmd/internal/objabi"
22 )
23
24
25 var (
26 BuildA bool
27 BuildBuildmode string
28 BuildContext = defaultContext()
29 BuildMod string
30 BuildI bool
31 BuildLinkshared bool
32 BuildMSan bool
33 BuildN bool
34 BuildO string
35 BuildP = runtime.NumCPU()
36 BuildPkgdir string
37 BuildRace bool
38 BuildToolexec []string
39 BuildToolchainName string
40 BuildToolchainCompiler func() string
41 BuildToolchainLinker func() string
42 BuildTrimpath bool
43 BuildV bool
44 BuildWork bool
45 BuildX bool
46
47 CmdName string
48
49 DebugActiongraph string
50 )
51
52 func defaultContext() build.Context {
53 ctxt := build.Default
54 ctxt.JoinPath = filepath.Join
55
56 ctxt.GOROOT = findGOROOT()
57 if runtime.Compiler != "gccgo" {
58
59
60
61
62
63 build.ToolDir = filepath.Join(ctxt.GOROOT, "pkg/tool/"+runtime.GOOS+"_"+runtime.GOARCH)
64 }
65
66 ctxt.GOPATH = envOr("GOPATH", ctxt.GOPATH)
67
68
69
70 ctxt.GOOS = envOr("GOOS", ctxt.GOOS)
71 ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH)
72
73
74
75
76
77
78 if v := Getenv("CGO_ENABLED"); v == "0" || v == "1" {
79 ctxt.CgoEnabled = v[0] == '1'
80 } else if ctxt.GOOS != runtime.GOOS || ctxt.GOARCH != runtime.GOARCH {
81 ctxt.CgoEnabled = false
82 } else {
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 }
98
99 return ctxt
100 }
101
102 func init() {
103 BuildToolchainCompiler = func() string { return "missing-compiler" }
104 BuildToolchainLinker = func() string { return "missing-linker" }
105 }
106
107
108 type EnvVar struct {
109 Name string
110 Value string
111 }
112
113
114 var OrigEnv []string
115
116
117
118
119 var CmdEnv []EnvVar
120
121
122 var (
123 Goarch = BuildContext.GOARCH
124 Goos = BuildContext.GOOS
125
126 ExeSuffix = exeSuffix()
127
128
129
130
131 ModulesEnabled bool
132 )
133
134 func exeSuffix() string {
135 if Goos == "windows" {
136 return ".exe"
137 }
138 return ""
139 }
140
141 var envCache struct {
142 once sync.Once
143 m map[string]string
144 }
145
146
147 func EnvFile() (string, error) {
148 if file := os.Getenv("GOENV"); file != "" {
149 if file == "off" {
150 return "", fmt.Errorf("GOENV=off")
151 }
152 return file, nil
153 }
154 dir, err := os.UserConfigDir()
155 if err != nil {
156 return "", err
157 }
158 if dir == "" {
159 return "", fmt.Errorf("missing user-config dir")
160 }
161 return filepath.Join(dir, "go/env"), nil
162 }
163
164 func initEnvCache() {
165 envCache.m = make(map[string]string)
166 file, _ := EnvFile()
167 if file == "" {
168 return
169 }
170 data, err := ioutil.ReadFile(file)
171 if err != nil {
172 return
173 }
174
175 for len(data) > 0 {
176
177 line := data
178 i := bytes.IndexByte(data, '\n')
179 if i >= 0 {
180 line, data = line[:i], data[i+1:]
181 } else {
182 data = nil
183 }
184
185 i = bytes.IndexByte(line, '=')
186 if i < 0 || line[0] < 'A' || 'Z' < line[0] {
187
188
189
190
191
192 continue
193 }
194 key, val := line[:i], line[i+1:]
195 envCache.m[string(key)] = string(val)
196 }
197 }
198
199
200
201
202
203
204
205
206 func Getenv(key string) string {
207 if !CanGetenv(key) {
208 switch key {
209 case "CGO_TEST_ALLOW", "CGO_TEST_DISALLOW", "CGO_test_ALLOW", "CGO_test_DISALLOW":
210
211 default:
212 panic("internal error: invalid Getenv " + key)
213 }
214 }
215 val := os.Getenv(key)
216 if val != "" {
217 return val
218 }
219 envCache.once.Do(initEnvCache)
220 return envCache.m[key]
221 }
222
223
224 func CanGetenv(key string) bool {
225 return strings.Contains(cfg.KnownEnv, "\t"+key+"\n")
226 }
227
228 var (
229 GOROOT = BuildContext.GOROOT
230 GOBIN = Getenv("GOBIN")
231 GOROOTbin = filepath.Join(GOROOT, "bin")
232 GOROOTpkg = filepath.Join(GOROOT, "pkg")
233 GOROOTsrc = filepath.Join(GOROOT, "src")
234 GOROOT_FINAL = findGOROOT_FINAL()
235
236
237 GOARM = envOr("GOARM", fmt.Sprint(objabi.GOARM))
238 GO386 = envOr("GO386", objabi.GO386)
239 GOMIPS = envOr("GOMIPS", objabi.GOMIPS)
240 GOMIPS64 = envOr("GOMIPS64", objabi.GOMIPS64)
241 GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", objabi.GOPPC64))
242 GOWASM = envOr("GOWASM", fmt.Sprint(objabi.GOWASM))
243
244 GOPROXY = envOr("GOPROXY", "direct")
245 GOSUMDB = envOr("GOSUMDB", "off")
246 GOPRIVATE = Getenv("GOPRIVATE")
247 GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
248 GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
249 )
250
251
252
253
254
255 func GetArchEnv() (key, val string) {
256 switch Goarch {
257 case "arm":
258 return "GOARM", GOARM
259 case "386":
260 return "GO386", GO386
261 case "mips", "mipsle":
262 return "GOMIPS", GOMIPS
263 case "mips64", "mips64le":
264 return "GOMIPS64", GOMIPS64
265 case "ppc64", "ppc64le":
266 return "GOPPC64", GOPPC64
267 case "wasm":
268 return "GOWASM", GOWASM
269 }
270 return "", ""
271 }
272
273
274 func envOr(key, def string) string {
275 val := Getenv(key)
276 if val == "" {
277 val = def
278 }
279 return val
280 }
281
282
283
284
285
286
287
288
289
290
291
292 func findGOROOT() string {
293 if env := Getenv("GOROOT"); env != "" {
294 return filepath.Clean(env)
295 }
296 def := filepath.Clean(runtime.GOROOT())
297 if runtime.Compiler == "gccgo" {
298
299
300 return def
301 }
302 exe, err := os.Executable()
303 if err == nil {
304 exe, err = filepath.Abs(exe)
305 if err == nil {
306 if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
307
308
309 if isSameDir(def, dir) {
310 return def
311 }
312 return dir
313 }
314 exe, err = filepath.EvalSymlinks(exe)
315 if err == nil {
316 if dir := filepath.Join(exe, "../.."); isGOROOT(dir) {
317 if isSameDir(def, dir) {
318 return def
319 }
320 return dir
321 }
322 }
323 }
324 }
325 return def
326 }
327
328 func findGOROOT_FINAL() string {
329
330
331 def := GOROOT
332 if env := os.Getenv("GOROOT_FINAL"); env != "" {
333 def = filepath.Clean(env)
334 }
335 return def
336 }
337
338
339 func isSameDir(dir1, dir2 string) bool {
340 if dir1 == dir2 {
341 return true
342 }
343 info1, err1 := os.Stat(dir1)
344 info2, err2 := os.Stat(dir2)
345 return err1 == nil && err2 == nil && os.SameFile(info1, info2)
346 }
347
348
349
350
351
352
353
354
355 func isGOROOT(path string) bool {
356 stat, err := os.Stat(filepath.Join(path, "pkg", "tool"))
357 if err != nil {
358 return false
359 }
360 return stat.IsDir()
361 }
362
View as plain text