github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/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  	"strings"
    12  )
    13  
    14  var cmdRun = &Command{
    15  	UsageLine: "run [build flags] gofiles... [arguments...]",
    16  	Short:     "compile and run Go program",
    17  	Long: `
    18  Run compiles and runs the main package comprising the named Go source files.
    19  A Go source file is defined to be a file ending in a literal ".go" suffix.
    20  
    21  For more about build flags, see 'go help build'.
    22  
    23  See also: go build.
    24  	`,
    25  }
    26  
    27  func init() {
    28  	cmdRun.Run = runRun // break init loop
    29  
    30  	addBuildFlags(cmdRun)
    31  }
    32  
    33  func printStderr(args ...interface{}) (int, error) {
    34  	return fmt.Fprint(os.Stderr, args...)
    35  }
    36  
    37  func runRun(cmd *Command, args []string) {
    38  	raceInit()
    39  	var b builder
    40  	b.init()
    41  	b.print = printStderr
    42  	i := 0
    43  	for i < len(args) && strings.HasSuffix(args[i], ".go") {
    44  		i++
    45  	}
    46  	files, cmdArgs := args[:i], args[i:]
    47  	if len(files) == 0 {
    48  		fatalf("go run: no go files listed")
    49  	}
    50  	for _, file := range files {
    51  		if strings.HasSuffix(file, "_test.go") {
    52  			// goFilesPackage is going to assign this to TestGoFiles.
    53  			// Reject since it won't be part of the build.
    54  			fatalf("go run: cannot run *_test.go files (%s)", file)
    55  		}
    56  	}
    57  	p := goFilesPackage(files)
    58  	if p.Error != nil {
    59  		fatalf("%s", p.Error)
    60  	}
    61  	for _, err := range p.DepsErrors {
    62  		errorf("%s", err)
    63  	}
    64  	exitIfErrors()
    65  	if p.Name != "main" {
    66  		fatalf("go run: cannot run non-main package")
    67  	}
    68  	p.target = "" // must build - not up to date
    69  	var src string
    70  	if len(p.GoFiles) > 0 {
    71  		src = p.GoFiles[0]
    72  	} else if len(p.CgoFiles) > 0 {
    73  		src = p.CgoFiles[0]
    74  	} else {
    75  		// this case could only happen if the provided source uses cgo
    76  		// while cgo is disabled.
    77  		hint := ""
    78  		if !buildContext.CgoEnabled {
    79  			hint = " (cgo is disabled)"
    80  		}
    81  		fatalf("go run: no suitable source files%s", hint)
    82  	}
    83  	p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file
    84  	a1 := b.action(modeBuild, modeBuild, p)
    85  	a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}}
    86  	b.do(a)
    87  }
    88  
    89  // runProgram is the action for running a binary that has already
    90  // been compiled.  We ignore exit status.
    91  func (b *builder) runProgram(a *action) error {
    92  	if buildN || buildX {
    93  		b.showcmd("", "%s %s", a.deps[0].target, strings.Join(a.args, " "))
    94  		if buildN {
    95  			return nil
    96  		}
    97  	}
    98  
    99  	runStdin(a.deps[0].target, a.args)
   100  	return nil
   101  }
   102  
   103  // runStdin is like run, but connects Stdin.
   104  func runStdin(cmdargs ...interface{}) {
   105  	cmdline := stringList(cmdargs...)
   106  	cmd := exec.Command(cmdline[0], cmdline[1:]...)
   107  	cmd.Stdin = os.Stdin
   108  	cmd.Stdout = os.Stdout
   109  	cmd.Stderr = os.Stderr
   110  	startSigHandlers()
   111  	if err := cmd.Run(); err != nil {
   112  		errorf("%v", err)
   113  	}
   114  }