diff --git a/compiler/cmd/internal/version/version.go b/compiler/cmd/internal/version/version.go index 9caf7cb2..75bba7a1 100644 --- a/compiler/cmd/internal/version/version.go +++ b/compiler/cmd/internal/version/version.go @@ -21,7 +21,7 @@ import ( "runtime" "github.com/goplus/llgo/compiler/cmd/internal/base" - "github.com/goplus/llgo/x/env" + "github.com/goplus/llgo/compiler/internal/env" ) // llgo version diff --git a/x/env/build.go b/compiler/internal/env/build.go similarity index 100% rename from x/env/build.go rename to compiler/internal/env/build.go diff --git a/compiler/internal/env/env.go b/compiler/internal/env/env.go index 6eef99be..1088de59 100644 --- a/compiler/internal/env/env.go +++ b/compiler/internal/env/env.go @@ -2,9 +2,11 @@ package env import ( "bytes" + "fmt" "os" "os/exec" "path/filepath" + "runtime" "strings" ) @@ -12,6 +14,7 @@ const ( LLGoCompilerPkg = "github.com/goplus/llgo" LLGoRuntimePkgName = "runtime" LLGoRuntimePkg = LLGoCompilerPkg + "/" + LLGoRuntimePkgName + envFileName = "/compiler/internal/env/env.go" ) func GOROOT() string { @@ -53,13 +56,22 @@ func LLGoROOT() string { } // Check if parent directory is bin dir := filepath.Dir(exe) - if filepath.Base(dir) != "bin" { - return "" + if filepath.Base(dir) == "bin" { + // Get parent directory of bin + root := filepath.Dir(dir) + if root, ok := isLLGoRoot(root); ok { + return root + } } - // Get parent directory of bin - root := filepath.Dir(dir) - if root, ok := isLLGoRoot(root); ok { - return root + if Devel() { + root, err := getRuntimePkgDirByCaller() + if err != nil { + return "" + } + if root, ok := isLLGoRoot(root); ok { + fmt.Fprintln(os.Stderr, "WARNING: Using LLGO root for devel: "+root) + return root + } } return "" } @@ -83,3 +95,22 @@ func isLLGoRoot(root string) (string, bool) { } return root, true } + +func getRuntimePkgDirByCaller() (string, error) { + _, file, _, ok := runtime.Caller(0) + if !ok { + return "", fmt.Errorf("cannot get caller") + } + if !strings.HasSuffix(file, envFileName) { + return "", fmt.Errorf("wrong caller") + } + // check file exists + if _, err := os.Stat(file); os.IsNotExist(err) { + return "", fmt.Errorf("file %s not exists", file) + } + modPath := strings.TrimSuffix(file, envFileName) + if st, err := os.Stat(modPath); os.IsNotExist(err) || !st.IsDir() { + return "", fmt.Errorf("not llgo compiler root: %s", modPath) + } + return modPath, nil +} diff --git a/compiler/internal/env/env_test.go b/compiler/internal/env/env_test.go index 14a49808..0bb19cdb 100644 --- a/compiler/internal/env/env_test.go +++ b/compiler/internal/env/env_test.go @@ -58,8 +58,10 @@ func TestLLGoRuntimeDir(t *testing.T) { defer os.Setenv("LLGO_ROOT", origLLGoRoot) os.Setenv("LLGO_ROOT", "/nonexistent/path") - if got := LLGoRuntimeDir(); got != "" { - t.Errorf("LLGoRuntimeDir() = %v, want empty string", got) + wd, _ := os.Getwd() + expected, _ := filepath.Abs(filepath.Join(wd, "../../../runtime")) + if got := LLGoRuntimeDir(); got != expected { + t.Errorf("LLGoRuntimeDir() = %v, want %v", got, expected) } }) } diff --git a/x/env/version.go b/compiler/internal/env/version.go similarity index 92% rename from x/env/version.go rename to compiler/internal/env/version.go index 975d4fef..ea80e2bf 100644 --- a/x/env/version.go +++ b/compiler/internal/env/version.go @@ -23,6 +23,8 @@ import "runtime/debug" var buildVersion string // Version returns the version of the running LLGo binary. +// +//export LLGoVersion func Version() string { if buildVersion != "" { return buildVersion @@ -33,3 +35,7 @@ func Version() string { } return "(devel)" } + +func Devel() bool { + return Version() == "(devel)" +}