I've a simple go code, that uses the runtime package as follows:
package main
import (
"runtime"
"fmt"
)
func bar() {
pc := make([]uintptr, 1000)
n := runtime.Callers(0, pc)
frames := runtime.CallersFrames(pc[:n])
for {
frame, more := frames.Next()
if ! more {
break
}
fmt.Printf("FILE = %s and FUNC = %s
", frame.File, frame.Function)
}
}
func foo() {
bar()
}
func main() {
foo()
}
I've Go binary installed in a custom location (/home/userA/bin/go) on a Ubuntu machine (say machine A)
I've compiled it on machine A and ran the executable on the same machine to get the output:
FILE = /home/userA/bin/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = /home/userA/src/main.go and FUNC = main.bar
FILE = /home/userA/src/main.go and FUNC = main.foo
FILE = /home/userA/src/main.go and FUNC = main.main
FILE = /home/userA/bin/go/src/runtime/proc.go and FUNC = runtime.main
Now I copied the compiled executable to another Ubuntu machine (say machine B) where Go binary was installed in another different custom location (/home/userB/bin/go). I ran the executable from /home/userB. But this time also, I got the same output as before:
FILE = /home/userA/bin/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = /home/userA/src/main.go and FUNC = main.bar
FILE = /home/userA/src/main.go and FUNC = main.foo
FILE = /home/userA/src/main.go and FUNC = main.main
FILE = /home/userA/bin/go/src/runtime/proc.go and FUNC = runtime.main
It seems that the runtime package sets the stack-frames during compilation time.
I need to do some processing on the file paths based on GOPATH environment variable, which I've set as /home/userA on machine A and as /home/userB on machine B.
I need to strip the GOPATH part from each of those file paths. I'm doing it with this simple function call: strings.Replace(frame.File, GOPATH, "", 1)
But, because of this behaviour of the runtime package, the strings.Replace
function fails to replace the initial portion of the file paths on machine B.
Any idea on how to accomplish this on machine B ?
UPDATE
Following the suggestion from @JimB, I've built the project with
CGO_ENABLED=0 go build -a -ldflags="-w -s" -gcflags=-trimpath=/home/userA -asmflags=-trimpath=/home/userA
Now, running the executable on the same machine gives output as:
FILE = /home/userA/bin/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = /home/userA/src/vendor/github.com/kataras/golog/golog.go and FUNC = vendor/github.com/kataras/golog.Error
FILE = /home/userA/src/test/test_logger.go and FUNC = test/test_logger.TestLogger
FILE = src/main.go and FUNC = main.bar
FILE = src/main.go and FUNC = main.foo
FILE = src/main.go and FUNC = main.main
FILE = /home/userA/bin/go/src/runtime/proc.go and FUNC = runtime.main
The path prefix is trimmed only for the main file. It's still there for any vendor imported package or any locally imported package.