2020-03-04 17:22:51 +00:00
|
|
|
// Package gobuild provides utilities for building programs and tests
|
|
|
|
// for the debugging session.
|
|
|
|
package gobuild
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
2021-02-21 19:17:14 +00:00
|
|
|
"runtime"
|
2021-05-17 16:13:25 +00:00
|
|
|
"strings"
|
2021-02-21 19:17:14 +00:00
|
|
|
"time"
|
2020-03-04 17:22:51 +00:00
|
|
|
|
|
|
|
"github.com/go-delve/delve/pkg/config"
|
|
|
|
"github.com/go-delve/delve/pkg/goversion"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Remove the file at path and issue a warning to stderr if this fails.
|
|
|
|
// This can be used to remove the temporary binary generated for the session.
|
|
|
|
func Remove(path string) {
|
2021-03-08 18:16:41 +00:00
|
|
|
var err error
|
|
|
|
for i := 0; i < 20; i++ {
|
2021-02-21 19:17:14 +00:00
|
|
|
err = os.Remove(path)
|
2021-03-08 18:16:41 +00:00
|
|
|
// Open files can be removed on Unix, but not on Windows, where there also appears
|
2021-03-15 16:34:26 +00:00
|
|
|
// to be a delay in releasing the binary when the process exits.
|
|
|
|
// Leaving temporary files behind can be annoying to users, so we try again.
|
2021-03-08 18:16:41 +00:00
|
|
|
if err == nil || runtime.GOOS != "windows" {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
time.Sleep(1 * time.Millisecond)
|
2021-02-21 19:17:14 +00:00
|
|
|
}
|
2020-03-04 17:22:51 +00:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "could not remove %v: %v\n", path, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// optflags generates default build flags to turn off optimization and inlining.
|
|
|
|
func optflags(args []string) []string {
|
|
|
|
// after go1.9 building with -gcflags='-N -l' and -a simultaneously works.
|
|
|
|
// after go1.10 specifying -a is unnecessary because of the new caching strategy,
|
|
|
|
// but we should pass -gcflags=all=-N -l to have it applied to all packages
|
|
|
|
// see https://github.com/golang/go/commit/5993251c015dfa1e905bdf44bdb41572387edf90
|
|
|
|
|
|
|
|
ver, _ := goversion.Installed()
|
|
|
|
switch {
|
2020-03-18 16:25:32 +00:00
|
|
|
case ver.Major < 0 || ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 10, Rev: -1}):
|
2020-03-04 17:22:51 +00:00
|
|
|
args = append(args, "-gcflags", "all=-N -l")
|
2020-03-18 16:25:32 +00:00
|
|
|
case ver.AfterOrEqual(goversion.GoVersion{Major: 1, Minor: 9, Rev: -1}):
|
2020-03-04 17:22:51 +00:00
|
|
|
args = append(args, "-gcflags", "-N -l", "-a")
|
|
|
|
default:
|
|
|
|
args = append(args, "-gcflags", "-N -l")
|
|
|
|
}
|
|
|
|
return args
|
|
|
|
}
|
|
|
|
|
|
|
|
// GoBuild builds non-test files in 'pkgs' with the specified 'buildflags'
|
|
|
|
// and writes the output at 'debugname'.
|
|
|
|
func GoBuild(debugname string, pkgs []string, buildflags string) error {
|
2021-04-26 17:31:59 +00:00
|
|
|
args := goBuildArgs(debugname, pkgs, buildflags, false)
|
|
|
|
return gocommandRun("build", args...)
|
2020-03-04 17:22:51 +00:00
|
|
|
}
|
|
|
|
|
2021-04-26 17:31:59 +00:00
|
|
|
// GoBuildCombinedOutput builds non-test files in 'pkgs' with the specified 'buildflags'
|
|
|
|
// and writes the output at 'debugname'.
|
2021-05-17 16:13:25 +00:00
|
|
|
func GoBuildCombinedOutput(debugname string, pkgs []string, buildflags string) (string, []byte, error) {
|
2021-04-26 17:31:59 +00:00
|
|
|
args := goBuildArgs(debugname, pkgs, buildflags, false)
|
|
|
|
return gocommandCombinedOutput("build", args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GoTestBuild builds test files 'pkgs' with the specified 'buildflags'
|
2020-03-04 17:22:51 +00:00
|
|
|
// and writes the output at 'debugname'.
|
|
|
|
func GoTestBuild(debugname string, pkgs []string, buildflags string) error {
|
2021-04-26 17:31:59 +00:00
|
|
|
args := goBuildArgs(debugname, pkgs, buildflags, true)
|
|
|
|
return gocommandRun("test", args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GoTestBuildCombinedOutput builds test files 'pkgs' with the specified 'buildflags'
|
|
|
|
// and writes the output at 'debugname'.
|
2021-05-17 16:13:25 +00:00
|
|
|
func GoTestBuildCombinedOutput(debugname string, pkgs []string, buildflags string) (string, []byte, error) {
|
2021-04-26 17:31:59 +00:00
|
|
|
args := goBuildArgs(debugname, pkgs, buildflags, true)
|
|
|
|
return gocommandCombinedOutput("test", args...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func goBuildArgs(debugname string, pkgs []string, buildflags string, isTest bool) []string {
|
|
|
|
args := []string{"-o", debugname}
|
|
|
|
if isTest {
|
|
|
|
args = append([]string{"-c"}, args...)
|
|
|
|
}
|
2020-03-04 17:22:51 +00:00
|
|
|
args = optflags(args)
|
|
|
|
if buildflags != "" {
|
|
|
|
args = append(args, config.SplitQuotedFields(buildflags, '\'')...)
|
|
|
|
}
|
|
|
|
args = append(args, pkgs...)
|
2021-04-26 17:31:59 +00:00
|
|
|
return args
|
2020-03-04 17:22:51 +00:00
|
|
|
}
|
|
|
|
|
2021-04-26 17:31:59 +00:00
|
|
|
func gocommandRun(command string, args ...string) error {
|
2021-05-17 16:13:25 +00:00
|
|
|
_, goBuild := gocommandExecCmd(command, args...)
|
2021-04-26 17:31:59 +00:00
|
|
|
goBuild.Stderr = os.Stdout
|
|
|
|
goBuild.Stdout = os.Stderr
|
|
|
|
return goBuild.Run()
|
|
|
|
}
|
|
|
|
|
2021-05-17 16:13:25 +00:00
|
|
|
func gocommandCombinedOutput(command string, args ...string) (string, []byte, error) {
|
|
|
|
buildCmd, goBuild := gocommandExecCmd(command, args...)
|
|
|
|
out, err := goBuild.CombinedOutput()
|
|
|
|
return buildCmd, out, err
|
2021-04-26 17:31:59 +00:00
|
|
|
}
|
|
|
|
|
2021-05-17 16:13:25 +00:00
|
|
|
func gocommandExecCmd(command string, args ...string) (string, *exec.Cmd) {
|
2020-03-04 17:22:51 +00:00
|
|
|
allargs := []string{command}
|
|
|
|
allargs = append(allargs, args...)
|
|
|
|
goBuild := exec.Command("go", allargs...)
|
2021-05-17 16:13:25 +00:00
|
|
|
return strings.Join(append([]string{"go"}, allargs...), " "), goBuild
|
2020-03-04 17:22:51 +00:00
|
|
|
}
|