Cross compiled binary caches goroot?

189 views
Skip to first unread message

Nate Finch

unread,
Oct 15, 2017, 8:22:56 AM10/15/17
to golang-nuts
https://github.com/magefile/mage/issues/69

Mage calls go build via os/exec, explicitly passing through os.Environ to the subprocess.

Somehow the cross compiled binary from my osx laptop is referencing the goroot from my laptop when it tries to run go build on a Linux machine.

1. How is this possible?
2. How can I fix it?

Nate Finch

unread,
Oct 15, 2017, 8:24:34 AM10/15/17
to golang-nuts
I cross compiled using go 1.9 if it matters.

Ian Lance Taylor

unread,
Oct 15, 2017, 3:33:02 PM10/15/17
to Nate Finch, golang-nuts
Cross-compiling your Go toolchain is the rare case where it may make
sense to set GOROOT in the environment when running the cross-compiled
Go toolchain.

Ian

Nate Finch

unread,
Oct 15, 2017, 5:00:18 PM10/15/17
to golang-nuts
I'm not cross compiling the tool chain. I'm cross compiling a binary(Mage) that just calls os/exec with "go", "build" and passes through os.Environ

I'll see if I can repro with a minimal example tonight.

Dave Cheney

unread,
Oct 15, 2017, 5:36:43 PM10/15/17
to golang-nuts
My guess is that GOROOT is not set in the target environment so the value eventually collapses back on the GOROOT compiled into mage from the value compiled into the toolchain that built mage.

gb has the same problem, I didn’t want to encourage people to set GOROOT, but if they don’t, there is no way to find the right tool chain.

I gave up and stoped distributing binary images, which 1/2 solved the problem.

Nate Finch

unread,
Oct 15, 2017, 7:30:45 PM10/15/17
to golang-nuts
hmm... I really don't want people to have to build Mage, since mage is a build tool.  Would it be horrible to just run go env GOROOT and use that to set GOROOT in the environs for the command that runs go build?

Dave Cheney

unread,
Oct 15, 2017, 7:43:47 PM10/15/17
to golang-nuts
Thank should work.

Nate Finch

unread,
Oct 16, 2017, 12:07:06 AM10/16/17
to golang-nuts
Reporting back: this worked perfectly.

Nate Finch

unread,
Oct 16, 2017, 10:55:02 AM10/16/17
to golang-nuts
Nope, I'm wrong.  It was an invalid test. It's still failing.

I'm going to raise this as an issue on the go tool.

IMO, this should work, and does not:

 c := exec.Command("go", "build", "main.go")
 c
.Env = append(os.Environ(), "GOROOT="+goroot)
 err
:= c.Run()

It should probably even work without setting GOROOT explicitly, but it definitely should if I do (presuming GOROOT is correct, of course)

Nate Finch

unread,
Oct 16, 2017, 11:27:06 AM10/16/17
to golang-nuts
well now, that's weird.  I just tried this in a minimal use case, compiled a linux command on my mac and ran it on my ubuntu box that just did the below... and it worked.  Now I'm wondering what the difference is.

Daniel Skinner

unread,
Oct 16, 2017, 12:22:00 PM10/16/17
to Nate Finch, golang-nuts
As mentioned in last paragraph here: https://golang.org/pkg/runtime/

GOARCH, GOOS, and GOROOT are recorded at compile time and made available by constants or functions in this package, but they do not influence the execution of the run-time system.

I'd first be inclined to think Mage source has done something to cause the GOROOT constant to influence run-time execution.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nate Finch

unread,
Oct 16, 2017, 1:33:03 PM10/16/17
to golang-nuts
There's no explicit use or inspection of GOROOT at all (aside from what I just added to add GOROOT to the execution, which since it didn't help, I may strip out).  The code has no external dependencies aside from the stdlib and stuff in its own repo.  Obviously there's something which is influencing the behavior, but it's very weird to me that any difference in how mage is compiled should affect how a command it runs in a subprocess executes (aside from environment variables).

I'll continue trying to pare down what mage does to see if I can isolate what code is making the difference between the failing program and the succeeding one

Daniel Skinner

unread,
Oct 16, 2017, 1:50:33 PM10/16/17
to Nate Finch, golang-nuts
You may want to try passing ldflag `-w` for darwin (`-s` for other platforms) to strip that information from the compiled executable during your testing in identifying the exact issue.

Nate Finch

unread,
Oct 16, 2017, 11:59:30 PM10/16/17
to golang-nuts
So I figured out I was looking for the error in the wrong place.  The place it was failing was in go/types when it tries to parse the files, using the go/build.Default context.  Which is created here: https://github.com/golang/go/blob/master/src/go/build/build.go#L285

It uses either the GOROOT of the environment (which is invariably not set), or the GOROOT of the machine that built this binary.

Thanks to Dave, no one ever sets GOROOT, and so it defaults to the one from my OSX machine where I built the binary.  aaarrggg

So the fix is to call go env GOROOT and use that to set the GOROOT on build.Default and then it'll actually do the right thing.  Just in case anyone else ever hits this. (Hello me from the future!  You're welcome!)

Nate Finch

unread,
Oct 17, 2017, 12:01:36 AM10/17/17
to golang-nuts
Oh and also, FYI, os.Setenv("GOROOT") will *not* work, because runtime.GOROOT() does *not* look at the current environment, it caches the GOROOT from when the binary first started up... which makes sense, but its docs confusingly say it looks at the environment, which is does, but not the *current* environment.   

Dave Cheney

unread,
Oct 17, 2017, 6:30:50 PM10/17/17
to golang-nuts


On Tuesday, 17 October 2017 14:59:30 UTC+11, Nate Finch wrote:
So I figured out I was looking for the error in the wrong place.  The place it was failing was in go/types when it tries to parse the files, using the go/build.Default context.  Which is created here: https://github.com/golang/go/blob/master/src/go/build/build.go#L285

It uses either the GOROOT of the environment (which is invariably not set), or the GOROOT of the machine that built this binary.

Thanks to Dave, no one ever sets GOROOT, and so it defaults to the one from my OSX machine where I built the binary.  aaarrggg

I don't know if this was intended as a compliment, but I'll take it :)

Nate Finch

unread,
Oct 18, 2017, 11:03:07 AM10/18/17
to golang-nuts
On Tuesday, October 17, 2017 at 6:30:50 PM UTC-4, Dave Cheney wrote:

On Tuesday, 17 October 2017 14:59:30 UTC+11, Nate Finch wrote:
Thanks to Dave, no one ever sets GOROOT, and so it defaults to the one from my OSX machine where I built the binary.  aaarrggg

I don't know if this was intended as a compliment, but I'll take it :)

I don't know either ;) 
Reply all
Reply to author
Forward
0 new messages