github.com/gophergala2016/cmd-go-js@v0.0.0-20160421080227-24a7748a7d62/cmd/go/run.go (about)

     1  // Copyright 2011 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 main
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"os/exec"
    11  	"runtime"
    12  	"strings"
    13  )
    14  
    15  var execCmd []string // -exec flag, for run and test
    16  
    17  func findExecCmd() []string {
    18  	if execCmd != nil {
    19  		return execCmd
    20  	}
    21  	execCmd = []string{} // avoid work the second time
    22  	if goos == runtime.GOOS && goarch == runtime.GOARCH {
    23  		return execCmd
    24  	}
    25  	path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch))
    26  	if err == nil {
    27  		execCmd = []string{path}
    28  	}
    29  	return execCmd
    30  }
    31  
    32  var cmdRun = &Command{
    33  	UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]",
    34  	Short:     "compile and run Go program",
    35  	Long: `
    36  Run compiles and runs the main package comprising the named Go source files.
    37  A Go source file is defined to be a file ending in a literal ".go" suffix.
    38  
    39  By default, 'go run' runs the compiled binary directly: 'a.out arguments...'.
    40  If the -exec flag is given, 'go run' invokes the binary using xprog:
    41  	'xprog a.out arguments...'.
    42  If the -exec flag is not given, GOOS or GOARCH is different from the system
    43  default, and a program named go_$GOOS_$GOARCH_exec can be found
    44  on the current search path, 'go run' invokes the binary using that program,
    45  for example 'go_nacl_386_exec a.out arguments...'. This allows execution of
    46  cross-compiled programs when a simulator or other execution method is
    47  available.
    48  
    49  For more about build flags, see 'go help build'.
    50  
    51  See also: go build.
    52  	`,
    53  }
    54  
    55  func init() {
    56  	cmdRun.Run = runRun // break init loop
    57  
    58  	addBuildFlags(cmdRun)
    59  	cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "")
    60  }
    61  
    62  func printStderr(args ...interface{}) (int, error) {
    63  	return fmt.Fprint(os.Stderr, args...)
    64  }
    65  
    66  func runRun(cmd *Command, args []string) {
    67  	raceInit()
    68  	buildModeInit()
    69  	var b builder
    70  	b.init()
    71  	b.print = printStderr
    72  	i := 0
    73  	for i < len(args) && strings.HasSuffix(args[i], ".go") {
    74  		i++
    75  	}
    76  	files, cmdArgs := args[:i], args[i:]
    77  	if len(files) == 0 {
    78  		fatalf("go run: no go files listed")
    79  	}
    80  	for _, file := range files {
    81  		if strings.HasSuffix(file, "_test.go") {
    82  			// goFilesPackage is going to assign this to TestGoFiles.
    83  			// Reject since it won't be part of the build.
    84  			fatalf("go run: cannot run *_test.go files (%s)", file)
    85  		}
    86  	}
    87  	p := goFilesPackage(files)
    88  	if p.Error != nil {
    89  		fatalf("%s", p.Error)
    90  	}
    91  	p.omitDWARF = true
    92  	for _, err := range p.DepsErrors {
    93  		errorf("%s", err)
    94  	}
    95  	exitIfErrors()
    96  	if p.Name != "main" {
    97  		fatalf("go run: cannot run non-main package")
    98  	}
    99  	p.target = "" // must build - not up to date
   100  	var src string
   101  	if len(p.GoFiles) > 0 {
   102  		src = p.GoFiles[0]
   103  	} else if len(p.CgoFiles) > 0 {
   104  		src = p.CgoFiles[0]
   105  	} else {
   106  		// this case could only happen if the provided source uses cgo
   107  		// while cgo is disabled.
   108  		hint := ""
   109  		if !buildContext.CgoEnabled {
   110  			hint = " (cgo is disabled)"
   111  		}
   112  		fatalf("go run: no suitable source files%s", hint)
   113  	}
   114  	p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
   115  	a1 := b.action(modeBuild, modeBuild, p)
   116  	a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
   117  	b.do(a)
   118  }
   119  
   120  // runProgram is the action for running a binary that has already
   121  // been compiled.  We ignore exit status.
   122  func (b *builder) runProgram(a *action) error {
   123  	cmdline := stringList(findExecCmd(), a.deps[0].target, a.args)
   124  	if buildN || buildX {
   125  		b.showcmd("", "%s", strings.Join(cmdline, " "))
   126  		if buildN {
   127  			return nil
   128  		}
   129  	}
   130  
   131  	runStdin(cmdline)
   132  	return nil
   133  }
   134  
   135  // runStdin is like run, but connects Stdin.
   136  func runStdin(cmdline []string) {
   137  	cmd := exec.Command(cmdline[0], cmdline[1:]...)
   138  	cmd.Stdin = os.Stdin
   139  	cmd.Stdout = os.Stdout
   140  	cmd.Stderr = os.Stderr
   141  	cmd.Env = origEnv
   142  	startSigHandlers()
   143  	if err := cmd.Run(); err != nil {
   144  		errorf("%v", err)
   145  	}
   146  }