diff options
Diffstat (limited to 'libgo/go/cmd/go/run.go')
-rw-r--r-- | libgo/go/cmd/go/run.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/libgo/go/cmd/go/run.go b/libgo/go/cmd/go/run.go new file mode 100644 index 0000000000..ef8aa95a35 --- /dev/null +++ b/libgo/go/cmd/go/run.go @@ -0,0 +1,143 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" + "os" + "os/exec" + "runtime" + "strings" +) + +var execCmd []string // -exec flag, for run and test + +func findExecCmd() []string { + if execCmd != nil { + return execCmd + } + execCmd = []string{} // avoid work the second time + if goos == runtime.GOOS && goarch == runtime.GOARCH { + return execCmd + } + path, err := exec.LookPath(fmt.Sprintf("go_%s_%s_exec", goos, goarch)) + if err == nil { + execCmd = []string{path} + } + return execCmd +} + +var cmdRun = &Command{ + UsageLine: "run [build flags] [-exec xprog] gofiles... [arguments...]", + Short: "compile and run Go program", + Long: ` +Run compiles and runs the main package comprising the named Go source files. +A Go source file is defined to be a file ending in a literal ".go" suffix. + +By default, 'go run' runs the compiled binary directly: 'a.out arguments...'. +If the -exec flag is given, 'go run' invokes the binary using xprog: 'xprog a.out arguments...'. +If the -exec flag is not given, GOOS or GOARCH is different from the system +default, and a program named go_$GOOS_$GOARCH_exec can be found +on the current search path, 'go run' invokes the binary using that program, +for example 'go_nacl_386_exec a.out arguments...'. This allows execution of +cross-compiled programs when a simulator or other execution method is +available. + +For more about build flags, see 'go help build'. + +See also: go build. + `, +} + +func init() { + cmdRun.Run = runRun // break init loop + + addBuildFlags(cmdRun) + cmdRun.Flag.Var((*stringsFlag)(&execCmd), "exec", "") +} + +func printStderr(args ...interface{}) (int, error) { + return fmt.Fprint(os.Stderr, args...) +} + +func runRun(cmd *Command, args []string) { + raceInit() + var b builder + b.init() + b.print = printStderr + i := 0 + for i < len(args) && strings.HasSuffix(args[i], ".go") { + i++ + } + files, cmdArgs := args[:i], args[i:] + if len(files) == 0 { + fatalf("go run: no go files listed") + } + for _, file := range files { + if strings.HasSuffix(file, "_test.go") { + // goFilesPackage is going to assign this to TestGoFiles. + // Reject since it won't be part of the build. + fatalf("go run: cannot run *_test.go files (%s)", file) + } + } + p := goFilesPackage(files) + if p.Error != nil { + fatalf("%s", p.Error) + } + p.omitDWARF = true + for _, err := range p.DepsErrors { + errorf("%s", err) + } + exitIfErrors() + if p.Name != "main" { + fatalf("go run: cannot run non-main package") + } + p.target = "" // must build - not up to date + var src string + if len(p.GoFiles) > 0 { + src = p.GoFiles[0] + } else if len(p.CgoFiles) > 0 { + src = p.CgoFiles[0] + } else { + // this case could only happen if the provided source uses cgo + // while cgo is disabled. + hint := "" + if !buildContext.CgoEnabled { + hint = " (cgo is disabled)" + } + fatalf("go run: no suitable source files%s", hint) + } + p.exeName = src[:len(src)-len(".go")] // name temporary executable for first go file + a1 := b.action(modeBuild, modeBuild, p) + a := &action{f: (*builder).runProgram, args: cmdArgs, deps: []*action{a1}} + b.do(a) +} + +// runProgram is the action for running a binary that has already +// been compiled. We ignore exit status. +func (b *builder) runProgram(a *action) error { + cmdline := stringList(findExecCmd(), a.deps[0].target, a.args) + if buildN || buildX { + b.showcmd("", "%s", strings.Join(cmdline, " ")) + if buildN { + return nil + } + } + + runStdin(cmdline) + return nil +} + +// runStdin is like run, but connects Stdin. +func runStdin(cmdline []string) { + cmd := exec.Command(cmdline[0], cmdline[1:]...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + startSigHandlers() + if err := cmd.Run(); err != nil { + errorf("%v", err) + } +} |