提交 087431f0 编写于 作者: A aarzilli 提交者: Derek Parker

Makefile: replace makefile with a script

We were using our makefile not for the intended purpose of makefiles
but to multiplex a series of small scripts.
We can easily achieve the same result in a more reasonable programming
language and as a bonus we don't need to install a version of make on
windows anymore.
Additionally our test script had become fairly complicated and will
become even more complicated when testing of PIE buildmode is
introduced.
Allows the tests to run on Windows without having to install Mingw
(although we still want it installed so that we can run cgo tests on
Windows).

Fixes building when GOPATH isn't set.

Fixes #759
上级 5e6b7997
.DEFAULT_GOAL=test
UNAME=$(shell uname)
PREFIX=github.com/derekparker/delve
GOPATH=$(shell go env GOPATH)
GOVERSION=$(shell go version)
BUILD_SHA=$(shell git rev-parse HEAD)
LLDB_SERVER=$(shell which lldb-server)
ifeq "$(UNAME)" "Darwin"
BUILD_FLAGS=-ldflags="-s -X main.Build=$(BUILD_SHA)"
else
BUILD_FLAGS=-ldflags="-X main.Build=$(BUILD_SHA)"
endif
# Workaround for GO15VENDOREXPERIMENT bug (https://github.com/golang/go/issues/11659)
ALL_PACKAGES=$(shell go list ./... | grep -v /vendor/ | grep -v /scripts)
# We must compile with -ldflags="-s" to omit
# DWARF info on OSX when compiling with the
# 1.5 toolchain. Otherwise the resulting binary
# will be malformed once we codesign it and
# unable to execute.
# See https://github.com/golang/go/issues/11887#issuecomment-126117692.
ifeq "$(UNAME)" "Darwin"
TEST_FLAGS=-count 1 -exec=$(shell pwd)/scripts/testsign
export PROCTEST=lldb
DARWIN="true"
else
TEST_FLAGS=-count 1
endif
# If we're on OSX make sure the proper CERT env var is set.
check-cert:
ifneq "$(TRAVIS)" "true"
ifdef DARWIN
ifeq "$(CERT)" ""
scripts/gencert.sh || (echo "An error occurred when generating and installing a new certificate"; exit 1)
CERT = dlv-cert
endif
endif
endif
@go run scripts/make.go check-cert
build: check-cert
go build $(BUILD_FLAGS) github.com/derekparker/delve/cmd/dlv
ifdef DARWIN
ifdef CERT
codesign -s "$(CERT)" ./dlv
endif
endif
build:
@go run scripts/make.go build
install: check-cert
go install $(BUILD_FLAGS) github.com/derekparker/delve/cmd/dlv
ifdef DARWIN
ifneq "$(GOBIN)" ""
codesign -s "$(CERT)" $(GOBIN)/dlv
else
codesign -s "$(CERT)" $(GOPATH)/bin/dlv
endif
endif
install:
@go run scripts/make.go install
test: check-cert
ifeq "$(TRAVIS)" "true"
ifdef DARWIN
sudo -E go test -p 1 -count 1 -v $(ALL_PACKAGES)
else
go test -p 1 $(TEST_FLAGS) $(BUILD_FLAGS) $(ALL_PACKAGES)
endif
else
go test -p 1 $(TEST_FLAGS) $(BUILD_FLAGS) $(ALL_PACKAGES)
endif
ifneq "$(shell which lldb-server 2>/dev/null)" ""
@echo
@echo 'Testing LLDB backend (proc)'
go test $(TEST_FLAGS) $(BUILD_FLAGS) $(PREFIX)/pkg/proc -backend=lldb
@echo
@echo 'Testing LLDB backend (integration)'
go test $(TEST_FLAGS) $(BUILD_FLAGS) $(PREFIX)/service/test -backend=lldb
@echo
@echo 'Testing LLDB backend (terminal)'
go test $(TEST_FLAGS) $(BUILD_FLAGS) $(PREFIX)/pkg/terminal -backend=lldb
endif
ifneq "$(shell which rr 2>/dev/null)" ""
@echo
@echo 'Testing Mozilla RR backend (proc)'
go test $(TEST_FLAGS) $(BUILD_FLAGS) $(PREFIX)/pkg/proc -backend=rr
@echo
@echo 'Testing Mozilla RR backend (integration)'
go test $(TEST_FLAGS) $(BUILD_FLAGS) $(PREFIX)/service/test -backend=rr
@echo
@echo 'Testing Mozilla RR backend (terminal)'
go test $(TEST_FLAGS) $(BUILD_FLAGS) $(PREFIX)/pkg/terminal -backend=rr
endif
test:
@go run scripts/make.go test
test-proc-run:
go test $(TEST_FLAGS) $(BUILD_FLAGS) -test.v -test.run="$(RUN)" -backend=$(BACKEND) $(PREFIX)/pkg/proc
@go run scripts/make.go test -s proc -r $(RUN)
test-integration-run:
go test $(TEST_FLAGS) $(BUILD_FLAGS) -test.run="$(RUN)" -backend=$(BACKEND) $(PREFIX)/service/test
@go run scripts/make.go test -s service/test -r ($RUN)
vendor: glide.yaml
@glide up -v
@glide-vc --use-lock-file --no-tests --only-code
vendor:
@go run scripts/make.go vendor
.PHONY: vendor test-integration-run test-proc-run test check-cert install build
......@@ -59,28 +59,22 @@ func goPath(name string) string {
func TestBuild(t *testing.T) {
const listenAddr = "localhost:40573"
var err error
makedir := filepath.Join(goPath("GOPATH"), "src", "github.com", "derekparker", "delve")
for _, makeProgram := range []string{"make", "mingw32-make"} {
var out []byte
cmd := exec.Command(makeProgram, "build")
cmd.Dir = makedir
out, err = cmd.CombinedOutput()
if err == nil {
break
} else {
t.Logf("makefile error %s (%s): %v", makeProgram, makedir, err)
t.Logf("output %s", string(out))
}
cmd := exec.Command("go", "run", "scripts/make.go", "build")
cmd.Dir = filepath.Join(goPath("GOPATH"), "src", "github.com", "derekparker", "delve")
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("makefile error: %v\noutput %s\n", err, string(out))
}
assertNoError(err, t, "make")
dlvbin := filepath.Join(makedir, "dlv")
dlvbin := filepath.Join(cmd.Dir, "dlv")
defer os.Remove(dlvbin)
fixtures := protest.FindFixturesDir()
buildtestdir := filepath.Join(fixtures, "buildtest")
cmd := exec.Command(dlvbin, "debug", "--headless=true", "--listen="+listenAddr, "--api-version=2", "--backend="+testBackend, "--log", "--log-output=debugger,rpc")
cmd = exec.Command(dlvbin, "debug", "--headless=true", "--listen="+listenAddr, "--api-version=2", "--backend="+testBackend, "--log", "--log-output=debugger,rpc")
cmd.Dir = buildtestdir
stderr, err := cmd.StderrPipe()
assertNoError(err, t, "stderr pipe")
......
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"sort"
"strings"
"github.com/spf13/cobra"
)
const DelveMainPackagePath = "github.com/derekparker/delve/cmd/dlv"
var Verbose bool
var TestSet, TestRegex, TestBackend string
func NewMakeCommands() *cobra.Command {
RootCommand := &cobra.Command{
Use: "make.go",
Short: "make script for delve.",
}
RootCommand.AddCommand(&cobra.Command{
Use: "check-cert",
Short: "Check certificate for macOS.",
Run: checkCertCmd,
})
RootCommand.AddCommand(&cobra.Command{
Use: "build",
Short: "Build delve",
Run: func(cmd *cobra.Command, args []string) {
checkCertCmd(nil, nil)
execute("go", "build", buildFlags(), DelveMainPackagePath)
if runtime.GOOS == "darwin" && os.Getenv("CERT") != "" {
codesign("./dlv")
}
},
})
RootCommand.AddCommand(&cobra.Command{
Use: "install",
Short: "Installs delve",
Run: func(cmd *cobra.Command, args []string) {
checkCertCmd(nil, nil)
execute("go", "install", buildFlags(), DelveMainPackagePath)
if runtime.GOOS == "darwin" {
codesign(installedExecutablePath())
}
},
})
test := &cobra.Command{
Use: "test",
Short: "Tests delve",
Long: `Tests delve.
Use the flags -s, -r and -b to specify which tests to run. Specifying nothing is equivalent to:
go run scripts/make.go test -s all -b default
go run scripts/make.go test -s basic -b lldb
go run scripts/make.go test -s basic -b rr
with lldb and rr tests only run if the relevant programs are installed.`,
Run: testCmd,
}
test.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "Verbose tests")
test.PersistentFlags().StringVarP(&TestSet, "test-set", "s", "", `Select the set of tests to run, one of either:
all tests all packages
basic tests proc, integration and terminal
integration tests github.com/derekparker/delve/service/test
package-name test the specified package only
`)
test.PersistentFlags().StringVarP(&TestRegex, "test-run", "r", "", `Only runs the tests matching the specified regex. This option can only be specified if testset is a single package`)
test.PersistentFlags().StringVarP(&TestBackend, "test-backend", "b", "", `Runs tests for the specified backend only, one of either:
default the default backend
lldb lldb backend
rr rr backend
This option can only be specified if testset is basic or a single package.`)
RootCommand.AddCommand(test)
RootCommand.AddCommand(&cobra.Command{
Use: "vendor",
Short: "vendors dependencies",
Run: func(cmd *cobra.Command, args []string) {
execute("glide", "up", "-v")
execute("glide-vc", "--use-lock-file", "--no-tests", "--only-code")
},
})
return RootCommand
}
func checkCertCmd(cmd *cobra.Command, args []string) {
// If we're on OSX make sure the proper CERT env var is set.
if os.Getenv("TRAVIS") == "true" || runtime.GOOS != "darwin" || os.Getenv("CERT") != "" {
return
}
x := exec.Command("scripts/gencert.sh")
err := x.Run()
if x.ProcessState != nil && !x.ProcessState.Success() {
fmt.Printf("An error occurred when generating and installing a new certificate\n")
os.Exit(1)
}
if err != nil {
log.Fatal(err)
}
os.Setenv("CERT", "dlv-cert")
}
func strflatten(v []interface{}) []string {
r := []string{}
for _, s := range v {
switch s := s.(type) {
case []string:
r = append(r, s...)
case string:
if s != "" {
r = append(r, s)
}
}
}
return r
}
func executeq(cmd string, args ...interface{}) {
x := exec.Command(cmd, strflatten(args)...)
x.Stdout = os.Stdout
x.Stderr = os.Stderr
x.Env = os.Environ()
err := x.Run()
if x.ProcessState != nil && !x.ProcessState.Success() {
os.Exit(1)
}
if err != nil {
log.Fatal(err)
}
}
func execute(cmd string, args ...interface{}) {
fmt.Printf("%s %s\n", cmd, strings.Join(quotemaybe(strflatten(args)), " "))
executeq(cmd, args...)
}
func quotemaybe(args []string) []string {
for i := range args {
if strings.Index(args[i], " ") >= 0 {
args[i] = fmt.Sprintf("%q", args[i])
}
}
return args
}
func getoutput(cmd string, args ...interface{}) string {
x := exec.Command(cmd, strflatten(args)...)
x.Env = os.Environ()
out, err := x.CombinedOutput()
if err != nil {
log.Fatal(err)
}
if !x.ProcessState.Success() {
os.Exit(1)
}
return string(out)
}
func codesign(path string) {
execute("codesign", "-s", os.Getenv("CERT"), path)
}
func installedExecutablePath() string {
if gobin := os.Getenv("GOBIN"); gobin != "" {
return filepath.Join(gobin, "dlv")
}
gopath := strings.Split(getoutput("go", "env", "GOPATH"), ":")
return filepath.Join(gopath[0], "dlv")
}
func buildFlags() []string {
buildSHA, err := exec.Command("git", "rev-parse", "HEAD").CombinedOutput()
if err != nil {
log.Fatal(err)
}
ldFlags := "-X main.Build=" + strings.TrimSpace(string(buildSHA))
if runtime.GOOS == "darwin" {
ldFlags = "-s " + ldFlags
}
return []string{fmt.Sprintf("-ldflags=%s", ldFlags)}
}
func testFlags() []string {
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
testFlags := []string{"-count", "1", "-p", "1"}
if Verbose {
testFlags = append(testFlags, "-v")
}
if runtime.GOOS == "darwin" {
testFlags = append(testFlags, "-exec="+wd+"/scripts/testsign")
}
return testFlags
}
func testCmd(cmd *cobra.Command, args []string) {
checkCertCmd(nil, nil)
if os.Getenv("TRAVIS") == "true" && runtime.GOOS == "darwin" {
os.Setenv("PROCTEST", "lldb")
executeq("sudo", "-E", "go", "test", testFlags(), allPackages())
return
}
if TestSet == "" && TestBackend == "" {
if TestRegex != "" {
fmt.Printf("Can not use --test-run without --test-set\n")
os.Exit(1)
}
fmt.Println("Testing default backend")
testCmdIntl("all", "", "default")
if inpath("lldb-server") {
fmt.Println("\nTesting LLDB backend")
testCmdIntl("basic", "", "lldb")
}
if inpath("rr") {
fmt.Println("\nTesting RR backend")
testCmdIntl("basic", "", "rr")
}
return
}
if TestSet == "" {
TestSet = "all"
}
if TestBackend == "" {
TestBackend = "default"
}
testCmdIntl(TestSet, TestRegex, TestBackend)
}
func testCmdIntl(testSet, testRegex, testBackend string) {
testPackages := testSetToPackages(testSet)
if len(testPackages) == 0 {
fmt.Printf("Unknown test set %q\n", testSet)
os.Exit(1)
}
if testRegex != "" && len(testPackages) != 1 {
fmt.Printf("Can not use test-run with test set %q\n", testSet)
os.Exit(1)
}
backendFlag := ""
if testBackend != "" && testBackend != "default" {
if testSet != "basic" && len(testPackages) != 1 {
fmt.Printf("Can not use test-backend with test set %q\n", testSet)
os.Exit(1)
}
backendFlag = "-backend=" + testBackend
}
if len(testPackages) > 3 {
execute("go", "test", testFlags(), buildFlags(), testPackages, backendFlag)
} else if testRegex != "" {
execute("go", "test", testFlags(), buildFlags(), testPackages, "-run="+testRegex, backendFlag)
} else {
execute("go", "test", testFlags(), buildFlags(), testPackages, backendFlag)
}
}
func testSetToPackages(testSet string) []string {
switch testSet {
case "", "all":
return allPackages()
case "basic":
return []string{"github.com/derekparker/delve/pkg/proc", "github.com/derekparker/delve/service/test", "github.com/derekparker/delve/pkg/terminal"}
case "integration":
return []string{"github.com/derekparker/delve/service/test"}
default:
for _, pkg := range allPackages() {
if pkg == testSet || strings.HasSuffix(pkg, "/"+testSet) {
return []string{pkg}
}
}
return nil
}
}
func inpath(exe string) bool {
path, _ := exec.LookPath(exe)
return path != ""
}
func allPackages() []string {
r := []string{}
for _, dir := range strings.Split(getoutput("go", "list", "./..."), "\n") {
dir = strings.TrimSpace(dir)
if dir == "" || strings.Contains(dir, "/vendor/") || strings.Contains(dir, "/scripts") {
continue
}
r = append(r, dir)
}
sort.Strings(r)
return r
}
func main() {
NewMakeCommands().Execute()
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册