Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add xgo shadow #230

Merged
merged 1 commit into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion cmd/xgo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ func main() {
consumeErrAndExit(err)
return
}
if cmd == "shadow" {
err := handleShadow()
consumeErrAndExit(err)
return
}
if cmd != "build" && cmd != "run" && cmd != "test" && cmd != "exec" {
fmt.Fprintf(os.Stderr, "xgo %s: unknown command\nRun 'xgo help' for usage.\n", cmd)
os.Exit(1)
Expand Down Expand Up @@ -742,8 +747,14 @@ func getXgoHome(xgoHome string) (string, error) {
return absHome, nil
}

func getNakedGo() string {
if nakedGoReplacement != "" {
return nakedGoReplacement
}
return "go"
}
func getGoEnvRoot(dir string) (string, error) {
goroot, err := cmd.Dir(dir).Output("go", "env", "GOROOT")
goroot, err := cmd.Dir(dir).Output(getNakedGo(), "env", "GOROOT")
if err != nil {
return "", err
}
Expand All @@ -753,6 +764,8 @@ func getGoEnvRoot(dir string) (string, error) {
return goroot, nil
}

var nakedGoReplacement = os.Getenv("XGO_REAL_GO_BINARY")

func checkGoroot(dir string, goroot string) (string, error) {
if goroot == "" {
// use env first because dir will affect the actual
Expand Down
4 changes: 2 additions & 2 deletions cmd/xgo/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ func buildInstrumentTool(goroot string, xgoSrc string, compilerBin string, compi
actualExecToolBin := execToolBin
if isDevelopment {
// build exec tool
buildExecToolCmd := exec.Command("go", "build", "-o", execToolBin, "./exec_tool")
buildExecToolCmd := exec.Command(getNakedGo(), "build", "-o", execToolBin, "./exec_tool")
buildExecToolCmd.Dir = filepath.Join(xgoSrc, "cmd")
buildExecToolCmd.Stdout = os.Stdout
buildExecToolCmd.Stderr = os.Stderr
Expand Down Expand Up @@ -337,7 +337,7 @@ func compareAndUpdateCompilerID(compilerFile string, compilerIDFile string) (cha
}

func getBuildID(file string) (string, error) {
data, err := exec.Command("go", "tool", "buildid", file).Output()
data, err := exec.Command(getNakedGo(), "tool", "buildid", file).Output()
if err != nil {
return "", err
}
Expand Down
55 changes: 55 additions & 0 deletions cmd/xgo/shadow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package main

import (
"embed"
"fmt"
"io/ioutil"
"os"
"path/filepath"

"github.com/xhd2015/xgo/support/cmd"
"github.com/xhd2015/xgo/support/osinfo"
)

//go:embed shadow
var shadowFS embed.FS

func handleShadow() error {
xgoHome, err := getXgoHome("")
if err != nil {
return err
}

shadowDir := filepath.Join(xgoHome, "shadow")
err = os.MkdirAll(shadowDir, 0755)
if err != nil {
return err
}

tmpDir, err := os.MkdirTemp("", "shadow-build")
if err != nil {
return err
}
defer os.RemoveAll(tmpDir)

err = copyEmbedDir(shadowFS, "shadow", tmpDir)
if err != nil {
return err
}

err = ioutil.WriteFile(filepath.Join(tmpDir, "go.mod"), []byte(`module github.com/xhd2015/xgo/cmd/xgo/shadow

go 1.14
`), 0755)
if err != nil {
return err
}

err = cmd.Dir(tmpDir).Run(getNakedGo(), "build", "-o", filepath.Join(shadowDir, "go"+osinfo.EXE_SUFFIX), "./")
if err != nil {
return err
}
fmt.Println(shadowDir)

return nil
}
34 changes: 34 additions & 0 deletions cmd/xgo/shadow/prepare_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//go:build unix
// +build unix

package main

import (
"fmt"
"os"
"path/filepath"
"strings"
)

func exclude(dir string) (func(), error) {
path := os.Getenv("PATH")

list := filepath.SplitList(path)
n := len(list)
j := 0
for i := 0; i < n; i++ {
d := list[i]
if d == dir {
continue
}
list[j] = d
j++
}
if j == n {
return nil, fmt.Errorf("xgo shadow not found in PATH: %s", dir)
}
os.Setenv("PATH", strings.Join(list[:j], string(filepath.ListSeparator)))
return func() {
os.Setenv("PATH", path)
}, nil
}
14 changes: 14 additions & 0 deletions cmd/xgo/shadow/prepare_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build windows
// +build windows

package main

import (
"fmt"
)

var xgo_shadow int = "not support windows yet"

func exclude(dir string) (func(), error) {
return nil, fmt.Errorf("windows not supported")
}
85 changes: 85 additions & 0 deletions cmd/xgo/shadow/shadow.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
)

var exeSuffix = getExeSuffix()

func getExeSuffix() string {
if runtime.GOOS == "windows" {
return ".exe"
}
return ""
}

func main() {
// if invoked with go, os.Args[0] = "go"
realGo, err := GetRealGoPath(os.Args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
args := os.Args[1:]
var subCmd string
if len(args) > 0 {
subCmd = args[0]
}
var cmdErr error
if subCmd == "build" || subCmd == "run" || subCmd == "test" {
cmdErr = runCmd("xgo", args, []string{"XGO_REAL_GO_BINARY=" + realGo})
} else {
cmdErr = runCmd(realGo, args, nil)
}

if cmdErr != nil {
var exitErr *exec.ExitError
if errors.As(cmdErr, &exitErr) {
os.Exit(exitErr.ExitCode())
}
fmt.Fprintf(os.Stderr, "%v\n", cmdErr)
os.Exit(1)
}
}

func runCmd(cmd string, args []string, env []string) error {
exeCmd := exec.Command(cmd, args...)
exeCmd.Stdout = os.Stdout
exeCmd.Stderr = os.Stderr
exeCmd.Env = os.Environ()
exeCmd.Env = append(exeCmd.Env, env...)
return exeCmd.Run()
}

func GetRealGoPath(curGo string) (string, error) {
var absGo string
var err error
// if curGo == "go"
if curGo == "go" || curGo == "go"+exeSuffix {
absGo, err = exec.LookPath(curGo)
if err != nil {
return "", err
}
} else {
if !filepath.IsAbs(curGo) {
return "", fmt.Errorf("xgo shadow not called with go or absolute path: %s", curGo)
}
absGo = curGo
}
return GetRealGoPathExcludeDir(filepath.Dir(absGo))
}

func GetRealGoPathExcludeDir(dir string) (string, error) {
callback, err := exclude(dir)
if err != nil {
return "", err
}
defer callback()

return exec.LookPath("go")
}
4 changes: 2 additions & 2 deletions cmd/xgo/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import "fmt"

// auto updated
const VERSION = "1.0.43"
const REVISION = "f1cf6698521d5b43da06f012ac3ba5afb1308d27+1"
const NUMBER = 280
const REVISION = "7afca256d82933d2cfef3b13ec306cf0907ff378+1"
const NUMBER = 281

// manually updated
const CORE_VERSION = "1.0.43"
Expand Down
Loading