Skip to content

Commit c3a0246

Browse files
committed
Internal implementation of "go run"
Stop using "go run" to compile and execute the user's code as well as our capsules (sub/). Instead, call "go build" and then launch the binary. This allows: - proper exit status code - no "exit status #" display - no conflict with 'go' command arguments parsing - no artificial import of "os" in the program Closes #9.
1 parent c150541 commit c3a0246

File tree

2 files changed

+35
-24
lines changed

2 files changed

+35
-24
lines changed

main.go

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"os"
2727
"os/exec"
2828
"path/filepath"
29+
"runtime"
2930
"strings"
3031
"time"
3132

@@ -135,19 +136,38 @@ func runTime(cmd *exec.Cmd) error {
135136
return cmd.Run()
136137
}
137138

138-
func gorun(srcFilename string, env []string, dir string, args ...string) error {
139-
runArgs := make([]string, 0, 3+len(args))
140-
runArgs = append(runArgs, "run", srcFilename, "--")
141-
runArgs = append(runArgs, args...)
142-
// log.Println(goCmd, runArgs)
139+
func gorun(srcFilename string, env []string, buildDir string, runDir string, args ...string) error {
140+
exeDir, err := os.MkdirTemp("", "goeval*")
141+
if err != nil {
142+
return err
143+
}
144+
defer func() {
145+
if err := os.RemoveAll(exeDir); err != nil {
146+
log.Printf("RemoveAll(%q): %v", exeDir, err)
147+
}
148+
}()
143149

144-
cmd := exec.Command(goCmd, runArgs...)
145-
cmd.Env = env
146-
cmd.Dir = dir // In Go module mode we run from the temp module dir
147-
cmd.Stdin = os.Stdin
148-
cmd.Stdout = os.Stdout
149-
cmd.Stderr = os.Stderr
150-
return run(cmd)
150+
exePath := filepath.Join(exeDir, "goeval-run")
151+
if runtime.GOOS == "windows" {
152+
exePath += ".exe"
153+
}
154+
155+
cmdBuild := exec.Command(goCmd, "build", "-o", exePath, srcFilename)
156+
cmdBuild.Env = env
157+
cmdBuild.Dir = buildDir
158+
cmdBuild.Stdout = os.Stdout
159+
cmdBuild.Stderr = os.Stderr
160+
if err := run(cmdBuild); err != nil {
161+
return fmt.Errorf("failed to build: %w", err)
162+
}
163+
164+
cmdRun := exec.Command(exePath, args...)
165+
cmdRun.Env = env
166+
cmdRun.Dir = runDir // In Go module mode we run from the temp module dir
167+
cmdRun.Stdin = os.Stdin
168+
cmdRun.Stdout = os.Stdout
169+
cmdRun.Stderr = os.Stderr
170+
return run(cmdRun)
151171
}
152172

153173
var goCmd = "go"
@@ -202,7 +222,7 @@ func flagAction(name string, a actionBits, usage string) {
202222

203223
func _main() error {
204224
imports := imports{
205-
packages: map[string]string{" ": "os"},
225+
packages: map[string]string{},
206226
onlySemVer: true,
207227
}
208228
flag.Var(&imports, "i", "* import package: [alias=]import-path\n* switch to Go module mode and import package: [alias=]import-path@version")
@@ -381,10 +401,6 @@ func _main() error {
381401
}
382402
src.WriteString("func main() {\n")
383403
if action <= actionDump {
384-
src.WriteString("os.Args[1] = os.Args[0]\nos.Args = os.Args[1:]\n")
385-
if moduleMode {
386-
fmt.Fprintf(&src, "_ = os.Chdir(%q)\n", origDir)
387-
}
388404
src.WriteString("//line :1\n")
389405
}
390406
src.WriteString(code)
@@ -410,7 +426,7 @@ func _main() error {
410426
if err = f.Close(); err != nil {
411427
return err
412428
}
413-
return gorun(srcFilename, env, dir, args...)
429+
return gorun(srcFilename, env, dir, origDir, args...)
414430
}
415431
case actionPlay:
416432
var cleanup func()

main_test.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,9 @@ func Example_dump() {
4242
// Output:
4343
// package main
4444
//
45-
// import (
46-
// "fmt"
47-
// "os"
48-
// )
45+
// import "fmt"
4946
//
5047
// func main() {
51-
// os.Args[1] = os.Args[0]
52-
// os.Args = os.Args[1:]
5348
// //line :1
5449
// fmt.Println("OK")
5550
// }

0 commit comments

Comments
 (0)