Skip to content

Commit

Permalink
add options --options-from-file and cmd/debug-compile
Browse files Browse the repository at this point in the history
  • Loading branch information
xhd2015 committed Jun 1, 2024
1 parent f8e03d3 commit dd7da82
Show file tree
Hide file tree
Showing 25 changed files with 1,280 additions and 288 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@
/covers
cover*.out

/tmp
/tmp

debug-compile.json
166 changes: 166 additions & 0 deletions cmd/debug-compile/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package main

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"time"

"github.com/xhd2015/xgo/cmd/xgo/exec_tool"
"github.com/xhd2015/xgo/support/cmd"
"github.com/xhd2015/xgo/support/debug"
"github.com/xhd2015/xgo/support/netutil"
)

// usage:
// go run -tags dev ./cmd/xgo --debug-compile ./src --> will generate a file called debug-compile.json
// go run -tags dev ./cmd/xgo build --build-compile --> will build the compiler with -gcflags and print it's path
// go run ./cmd/debug-compile --debug-with-dlv --> will read debug-compile.json, and start a debug server listen on localhost:2345

func main() {
args := os.Args[1:]
err := run(args)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
}

func run(args []string) error {
var compilerBinary string
n := len(args)
var projectDir string

data, readErr := ioutil.ReadFile("debug-compile.json")
if readErr != nil {
if !errors.Is(readErr, os.ErrNotExist) {
return readErr
}
}
var debugCompiler *exec_tool.DebugCompile
if len(data) > 0 {
err := json.Unmarshal(data, &debugCompiler)
if err != nil {
return fmt.Errorf("parse debug-compile.json: %w", err)
}
}

var extraFlags []string
var extraEnvs []string
var debugWithDlv bool
for i := 0; i < n; i++ {
arg := args[i]
if arg == "--project-dir" {
projectDir = args[i+1]
i++
continue
}
if arg == "--env" {
extraEnvs = append(extraEnvs, args[i+1])
i++
continue
}
if arg == "--compiler" {
compilerBinary = args[i+1]
i++
continue
}
if arg == "-cpuprofile" {
extraFlags = append(extraFlags, arg, args[i+1])
i++
continue
}
if arg == "-blockprofile" {
extraFlags = append(extraFlags, arg, args[i+1])
i++
continue
}
if arg == "-memprofile" || arg == "-memprofilerate" {
extraFlags = append(extraFlags, arg, args[i+1])
i++
continue
}
if arg == "-N" || arg == "-l" {
extraFlags = append(extraFlags, arg)
continue
}
if arg == "-c" {
extraFlags = append(extraFlags, arg, args[i+1])
continue
}
if arg == "--debug-with-dlv" {
debugWithDlv = true
continue
}
}
if compilerBinary == "" {
compilerBinary = debugCompiler.Compiler
}

runArgs := append(debugCompiler.Flags, extraFlags...)
runArgs = append(runArgs, debugCompiler.Files...)

runEnvs := append(debugCompiler.Env, extraEnvs...)

if debugWithDlv {
return dlvExecListen(projectDir, runEnvs, compilerBinary, runArgs)
}

start := time.Now()
defer func() {
fmt.Printf("cost: %v\n", time.Since(start))
}()
return cmd.Dir(projectDir).Env(runEnvs).Run(compilerBinary, runArgs...)
}

// /Users/xhd2015/.xgo/go-instrument-dev/go1.21.7_Us_xh_in_go_096be049/compile

func dlvExecListen(dir string, env []string, compilerBinary string, args []string) error {
var vscodeExtra []string
n := len(env)
for i := n - 1; i >= 0; i-- {
e := env[i]
if !strings.HasPrefix(e, "GOROOT=") {
continue
}
goroot := strings.TrimPrefix(e, "GOROOT=")
if goroot != "" {
vscodeExtra = append(vscodeExtra,
fmt.Sprintf(" NOTE: VSCode will map source files to workspace's goroot,"),
fmt.Sprintf(" To fix this, update .vscode/settings.json, set go.goroot to:"),
fmt.Sprintf(" %s", goroot),
fmt.Sprintf(" And set a breakpoint at:"),
fmt.Sprintf(" %s/src/cmd/compile/main.go", goroot),
)
}
break
}
return netutil.ServePort(2345, true, 500*time.Millisecond, func(port int) {
prompt := debug.FormatDlvPromptOptions(port, &debug.FormatDlvOptions{
VscodeExtra: vscodeExtra,
})
fmt.Println(prompt)
}, func(port int) error {
// dlv exec --api-version=2 --listen=localhost:2345 --accept-multiclient --headless ./debug.bin
dlvArgs := []string{
"--api-version=2",
fmt.Sprintf("--listen=localhost:%d", port),
"--check-go-version=false",
"--log=true",
// "--accept-multiclient", // exits when client exits
"--headless", "exec",
compilerBinary,
"--",
}
// dlvArgs = append(dlvArgs, compilerBin)
dlvArgs = append(dlvArgs, args...)
err := cmd.Dir(dir).Env(env).Run("dlv", dlvArgs...)
if err != nil {
return fmt.Errorf("dlv: %w", err)
}
return nil
})
}
67 changes: 49 additions & 18 deletions cmd/xgo/exec_tool/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,54 @@ import (
"path/filepath"
)

func getDebugEnv(xgoCompilerEnableEnv string) map[string]string {
return map[string]string{
"COMPILER_ALLOW_IR_REWRITE": "true",
"COMPILER_ALLOW_SYNTAX_REWRITE": "true",
"COMPILER_DEBUG_IR_REWRITE_FUNC": os.Getenv("COMPILER_DEBUG_IR_REWRITE_FUNC"),
"COMPILER_DEBUG_IR_DUMP_FUNCS": os.Getenv("COMPILER_DEBUG_IR_DUMP_FUNCS"),
XGO_DEBUG_DUMP_IR: os.Getenv(XGO_DEBUG_DUMP_IR),
XGO_DEBUG_DUMP_IR_FILE: os.Getenv(XGO_DEBUG_DUMP_IR_FILE),
XGO_DEBUG_DUMP_AST: os.Getenv(XGO_DEBUG_DUMP_AST),
XGO_DEBUG_DUMP_AST_FILE: os.Getenv(XGO_DEBUG_DUMP_AST_FILE),
"GOCACHE": os.Getenv("GOCACHE"),
XGO_MAIN_MODULE: os.Getenv(XGO_MAIN_MODULE),
XGO_COMPILE_PKG_DATA_DIR: os.Getenv(XGO_COMPILE_PKG_DATA_DIR),
XGO_STD_LIB_TRAP_DEFAULT_ALLOW: os.Getenv(XGO_STD_LIB_TRAP_DEFAULT_ALLOW),
"GOROOT": "../..",
"PATH": "../../bin:${env:PATH}",
"XGO_COMPILER_ENABLE": xgoCompilerEnableEnv,
type DebugCompile struct {
Package string `json:"package"`
Env []string `json:"env"`
Compiler string `json:"compiler"`
Flags []string `json:"flags"`
Files []string `json:"files"`
}

func getDebugEnvMapping(xgoCompilerEnableEnv string) map[string]string {
envs := getDebugEnvList(xgoCompilerEnableEnv)
mapping := make(map[string]string, len(envs))
for _, env := range envs {
mapping[env[0]] = env[1]
}
return mapping
}

func getDebugEnv(xgoCompilerEnableEnv string) []string {
envs := getDebugEnvList(xgoCompilerEnableEnv)
joints := make([]string, 0, len(envs))
for _, env := range envs {
joints = append(joints, env[0]+"="+env[1])
}
return joints
}

func getDebugEnvList(xgoCompilerEnableEnv string) [][2]string {
return [][2]string{
{"XGO_COMPILER_ENABLE", xgoCompilerEnableEnv},
{"COMPILER_ALLOW_IR_REWRITE", "true"},
{"COMPILER_ALLOW_SYNTAX_REWRITE", "true"},
{"COMPILER_DEBUG_IR_REWRITE_FUNC", os.Getenv("COMPILER_DEBUG_IR_REWRITE_FUNC")},
{"COMPILER_DEBUG_IR_DUMP_FUNCS", os.Getenv("COMPILER_DEBUG_IR_DUMP_FUNCS")},
{XGO_DEBUG_DUMP_IR, os.Getenv(XGO_DEBUG_DUMP_IR)},
{XGO_DEBUG_DUMP_IR_FILE, os.Getenv(XGO_DEBUG_DUMP_IR_FILE)},
{XGO_DEBUG_DUMP_AST, os.Getenv(XGO_DEBUG_DUMP_AST)},
{XGO_DEBUG_DUMP_AST_FILE, os.Getenv(XGO_DEBUG_DUMP_AST_FILE)},
{XGO_MAIN_MODULE, os.Getenv(XGO_MAIN_MODULE)},
{XGO_COMPILE_PKG_DATA_DIR, os.Getenv(XGO_COMPILE_PKG_DATA_DIR)},
{XGO_STD_LIB_TRAP_DEFAULT_ALLOW, os.Getenv(XGO_STD_LIB_TRAP_DEFAULT_ALLOW)},
{XGO_DEBUG_COMPILE_PKG, os.Getenv(XGO_DEBUG_COMPILE_PKG)},
{XGO_DEBUG_COMPILE_LOG_FILE, os.Getenv(XGO_DEBUG_COMPILE_LOG_FILE)},
{XGO_COMPILER_OPTIONS_FILE, os.Getenv(XGO_COMPILER_OPTIONS_FILE)},
{XGO_SRC_WD, os.Getenv(XGO_SRC_WD)},
{"GOROOT", os.Getenv("GOROOT")},
{"GOPATH", os.Getenv("GOPATH")},
{"PATH", os.Getenv("PATH")},
{"GOCACHE", os.Getenv("GOCACHE")},
}
}

Expand All @@ -35,7 +66,7 @@ func getVscodeDebugCmd(cmd string, xgoCompilerEnableEnv string, args []string) *
Mode: "exec",
Program: cmd,
Args: args,
Env: getDebugEnv(xgoCompilerEnableEnv),
Env: getDebugEnvMapping(xgoCompilerEnableEnv),
}
}

Expand Down
8 changes: 8 additions & 0 deletions cmd/xgo/exec_tool/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,11 @@ const XGO_MAIN_MODULE = "XGO_MAIN_MODULE"
const XGO_COMPILE_PKG_DATA_DIR = "XGO_COMPILE_PKG_DATA_DIR"

const XGO_STD_LIB_TRAP_DEFAULT_ALLOW = "XGO_STD_LIB_TRAP_DEFAULT_ALLOW"

const XGO_DEBUG_COMPILE_PKG = "XGO_DEBUG_COMPILE_PKG"
const XGO_DEBUG_COMPILE_LOG_FILE = "XGO_DEBUG_COMPILE_LOG_FILE"

const XGO_COMPILER_OPTIONS_FILE = "XGO_COMPILER_OPTIONS_FILE"

// xgo's origial working dir

Check warning on line 26 in cmd/xgo/exec_tool/env.go

View workflow job for this annotation

GitHub Actions / check-build

"origial" should be "original".
const XGO_SRC_WD = "XGO_SRC_WD"
72 changes: 71 additions & 1 deletion cmd/xgo/exec_tool/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -92,6 +94,9 @@ func handleCompile(cmd string, opts *options, args []string) error {
}
}

debugCompilePkg := os.Getenv(XGO_DEBUG_COMPILE_PKG)
debugCompileLogFile := os.Getenv(XGO_DEBUG_COMPILE_LOG_FILE)

xgoCompilerEnableEnv, ok := os.LookupEnv(XGO_COMPILER_ENABLE)
if !ok {
if opts.enable {
Expand Down Expand Up @@ -125,7 +130,7 @@ func handleCompile(cmd string, opts *options, args []string) error {
compilerBin,
"--",
}
envs := getDebugEnv(xgoCompilerEnableEnv)
envs := getDebugEnvMapping(xgoCompilerEnableEnv)
// dlvArgs = append(dlvArgs, compilerBin)
dlvArgs = append(dlvArgs, args...)
var strPrint []string
Expand Down Expand Up @@ -195,6 +200,31 @@ func handleCompile(cmd string, opts *options, args []string) error {
}
}
}
if debugCompilePkg != "" && debugCompilePkg == pkgPath {
envs := getDebugEnv(xgoCompilerEnableEnv)
flags, files := splitArgs(args)
str := formatDebugCompile(envs, compilerBin, flags, files)

debugOptions := &DebugCompile{
Package: pkgPath,
Env: envs,
Compiler: compilerBin,
Flags: flags,
Files: files,
}
err := ioutil.WriteFile(debugCompileLogFile, []byte(str), 0755)
if err != nil {
return err
}
srcWD := os.Getenv(XGO_SRC_WD)
err = marshalNoEscape(filepath.Join(srcWD, "debug-compile.json"), debugOptions)
if err != nil {
return err
}
for {
time.Sleep(1024 * time.Minute)
}
}
// COMPILER_ALLOW_SYNTAX_REWRITE=${COMPILER_ALLOW_SYNTAX_REWRITE:-true} COMPILER_ALLOW_IR_REWRITE=${COMPILER_ALLOW_IR_REWRITE:-true} "$shdir/compile" ${@:2}
runCommandExitFilter(compilerBin, args, func(cmd *exec.Cmd) {
cmd.Env = append(cmd.Env,
Expand All @@ -207,6 +237,46 @@ func handleCompile(cmd string, opts *options, args []string) error {
return nil
}

func marshalNoEscape(file string, data interface{}) error {
f, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetEscapeHTML(false)
enc.SetIndent("", " ")
return enc.Encode(data)
}

func splitArgs(args []string) (flags []string, files []string) {
n := len(args)
i := n - 1
for ; i >= 0; i-- {
if !strings.HasSuffix(args[i], ".go") {
break
}
}
return args[:i+1], args[i+1:]
}
func formatDebugCompile(env []string, bin string, flags []string, files []string) string {
var b strings.Builder

b.WriteString(fmt.Sprintf("var env = []string{%s}\n", formatGoList(env)))
b.WriteString(fmt.Sprintf("var flags = []string{%s}\n", formatGoList(flags)))
b.WriteString(fmt.Sprintf("var files = []string{%s}\n", formatGoList(files)))
b.WriteString(fmt.Sprintf("var compiler = %q\n", bin))

return b.String()
}

func formatGoList(list []string) string {
qlist := make([]string, 0, len(list))
for _, e := range list {
qlist = append(qlist, strconv.Quote(e))
}
return strings.Join(qlist, ", ")
}
func hasFlag(args []string, flag string) bool {
flagEq := flag + "="
for _, arg := range args {
Expand Down
Loading

0 comments on commit dd7da82

Please sign in to comment.