github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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  	"fmt"
    10  	"os"
    11  	"runtime"
    12  	"strings"
    13  
    14  	"cmd/go/internal/base"
    15  	"cmd/go/internal/cfg"
    16  	"cmd/go/internal/load"
    17  	"cmd/go/internal/work"
    18  )
    19  
    20  var CmdEnv = &base.Command{
    21  	Run:       runEnv,
    22  	UsageLine: "env [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  }
    33  
    34  func MkEnv() []cfg.EnvVar {
    35  	var b work.Builder
    36  	b.Init()
    37  
    38  	env := []cfg.EnvVar{
    39  		{Name: "GOARCH", Value: cfg.Goarch},
    40  		{Name: "GOBIN", Value: cfg.GOBIN},
    41  		{Name: "GOEXE", Value: cfg.ExeSuffix},
    42  		{Name: "GOHOSTARCH", Value: runtime.GOARCH},
    43  		{Name: "GOHOSTOS", Value: runtime.GOOS},
    44  		{Name: "GOOS", Value: cfg.Goos},
    45  		{Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
    46  		{Name: "GORACE", Value: os.Getenv("GORACE")},
    47  		{Name: "GOROOT", Value: cfg.GOROOT},
    48  		{Name: "GOTOOLDIR", Value: base.ToolDir},
    49  
    50  		// disable escape codes in clang errors
    51  		{Name: "TERM", Value: "dumb"},
    52  	}
    53  
    54  	if work.GccgoBin != "" {
    55  		env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin})
    56  	} else {
    57  		env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName})
    58  	}
    59  
    60  	switch cfg.Goarch {
    61  	case "arm":
    62  		env = append(env, cfg.EnvVar{Name: "GOARM", Value: os.Getenv("GOARM")})
    63  	case "386":
    64  		env = append(env, cfg.EnvVar{Name: "GO386", Value: os.Getenv("GO386")})
    65  	}
    66  
    67  	cmd := b.GccCmd(".")
    68  	env = append(env, cfg.EnvVar{Name: "CC", Value: cmd[0]})
    69  	env = append(env, cfg.EnvVar{Name: "GOGCCFLAGS", Value: strings.Join(cmd[3:], " ")})
    70  	cmd = b.GxxCmd(".")
    71  	env = append(env, cfg.EnvVar{Name: "CXX", Value: cmd[0]})
    72  
    73  	if cfg.BuildContext.CgoEnabled {
    74  		env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"})
    75  	} else {
    76  		env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"})
    77  	}
    78  
    79  	return env
    80  }
    81  
    82  func findEnv(env []cfg.EnvVar, name string) string {
    83  	for _, e := range env {
    84  		if e.Name == name {
    85  			return e.Value
    86  		}
    87  	}
    88  	return ""
    89  }
    90  
    91  // ExtraEnvVars returns environment variables that should not leak into child processes.
    92  func ExtraEnvVars() []cfg.EnvVar {
    93  	var b work.Builder
    94  	b.Init()
    95  	cppflags, cflags, cxxflags, fflags, ldflags := b.CFlags(&load.Package{})
    96  	return []cfg.EnvVar{
    97  		{Name: "PKG_CONFIG", Value: b.PkgconfigCmd()},
    98  		{Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")},
    99  		{Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")},
   100  		{Name: "CGO_CXXFLAGS", Value: strings.Join(cxxflags, " ")},
   101  		{Name: "CGO_FFLAGS", Value: strings.Join(fflags, " ")},
   102  		{Name: "CGO_LDFLAGS", Value: strings.Join(ldflags, " ")},
   103  	}
   104  }
   105  
   106  func runEnv(cmd *base.Command, args []string) {
   107  	env := cfg.CmdEnv
   108  	env = append(env, ExtraEnvVars()...)
   109  	if len(args) > 0 {
   110  		for _, name := range args {
   111  			fmt.Printf("%s\n", findEnv(env, name))
   112  		}
   113  		return
   114  	}
   115  
   116  	for _, e := range env {
   117  		if e.Name != "TERM" {
   118  			switch runtime.GOOS {
   119  			default:
   120  				fmt.Printf("%s=\"%s\"\n", e.Name, e.Value)
   121  			case "plan9":
   122  				if strings.IndexByte(e.Value, '\x00') < 0 {
   123  					fmt.Printf("%s='%s'\n", e.Name, strings.Replace(e.Value, "'", "''", -1))
   124  				} else {
   125  					v := strings.Split(e.Value, "\x00")
   126  					fmt.Printf("%s=(", e.Name)
   127  					for x, s := range v {
   128  						if x > 0 {
   129  							fmt.Printf(" ")
   130  						}
   131  						fmt.Printf("%s", s)
   132  					}
   133  					fmt.Printf(")\n")
   134  				}
   135  			case "windows":
   136  				fmt.Printf("set %s=%s\n", e.Name, e.Value)
   137  			}
   138  		}
   139  	}
   140  }