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

Further improve GOPATH detection in Makefile #24387

Closed
wants to merge 3 commits into from

Conversation

mqudsi
Copy link
Contributor

@mqudsi mqudsi commented Mar 31, 2018

In recent versions of go, GOPATH need not be explicitly set (and go env GOPATH will return nothing) if using the default $HOME/go as $GOPATH.

Additionally, it is necessary to use readlink -f to get the real paths
of both $GOPATH and $CWD, as symlinks may be in play. For instance, on
FreeBSD /home is symlinked to /usr/home/, but the former is often
used. If readlink isn't used, the string-based prefix matching will
incorrectly claim that CWD is not a child of GOPATH.

This patch sets GOPATH to $HOME/go if GOPATH is not exported and
$HOME/go exists (since readlink -f $HOME/go will return an empty
string if its target is not found). No change in the existing behavior
is expected if the environment variable GOPATH is not blank or if it is
both blank and $HOME/go is not the GOPATH.

Release note: None

@mqudsi mqudsi requested a review from a team March 31, 2018 18:34
@cockroach-teamcity
Copy link
Member

This change is Reviewable

@mqudsi
Copy link
Contributor Author

mqudsi commented Mar 31, 2018

ref #24358 #23245
cc @benesch

In recent versions of go, GOPATH need not be explicitly set (and `go env
GOPATH` will return nothing) if using the default $HOME/go as $GOPATH.

Additionally, it is necessary to use `readlink -f` to get the real paths
of both $GOPATH and $CWD, as symlinks may be in play. For instance, on
FreeBSD `/home` is symlinked to `/usr/home/`, but the former is often
used. If `readlink` isn't used, the string-based prefix matching will
incorrectly claim that CWD is not a child of GOPATH.

This patch sets GOPATH to `$HOME/go` if GOPATH is not exported and
`$HOME/go` exists (since `readlink -f $HOME/go` will return an empty
string if its target is not found). No change in the existing behavior
is expected if the environment variable GOPATH is not blank or if it is
both blank and $HOME/go is not the GOPATH.

Release note: None
Copy link
Contributor

@benesch benesch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, thanks for the additional improvements, @mqudsi. Added some comments. One last point: your commit message mentions following symlinks in CURDIR, but the code doesn't seem to do that.

Makefile Outdated
# GOPATH need not be explicitly set if it is the default $HOME/go
ifeq ($(strip $(GOPATH)),)
GOPATH := $(shell readlink -f $$HOME/go)
endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I can't reproduce the need for this. go env GOPATH does the right thing for me when GOPATH is not set in the environment—and in fact that's why we don't use GOPATH directly. Does the following return a different result for you?

$ unset GOPATH && go env GOPATH
/home/benesch/go

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mqudsi@mysql ~/g/s/g/c/cockroach> go version
go version go1.10.1 freebsd/amd64
mqudsi@mysql ~/g/s/g/c/cockroach> set -e GOPATH; go env GOPATH

mqudsi@mysql ~/g/s/g/c/cockroach> env GOPATH="" go env GOPATH

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, on another machine:

mqudsi@freebsd ~/g/s/g/c/cockroach> go version
go version go1.10.1 freebsd/amd64
mqudsi@freebsd ~/g/s/g/c/cockroach> env GOPATH="" go env GOPATH
/home/mqudsi/go

Not sure what to make of this. A golang bug, perhaps?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check this out:

$ HOME= GOPATH= go env GOPATH

$

Seems like maybe $HOME is unset? Or os/user.Current is otherwise bricked on that machine?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, $HOME is correct. This was a new deployment of both go and cockroach, just installed. cockroach is the first go installation on this machine. Perhaps the clue lies therein somewhere?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've come up with another way of causing this situation:

$ GOROOT=$HOME/go GOPATH= go env GOPATH

$

Does that perhaps describe your situation? If not, could you post the full output of go env?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You nailed it. GOPATH and GOROOT can't both be the same, so that breaks the auto-generation of GOPATH.

I guess the best thing here is to error out if go env GOPATH returns an empty result.

Makefile Outdated
@@ -201,7 +201,11 @@ UI_ROOT := $(PKG_ROOT)/ui
SQLPARSER_ROOT := $(PKG_ROOT)/sql/parser

# Ensure we have an unambiguous GOPATH.
GOPATH := $(shell $(GO) env GOPATH)
GOPATH := $(shell readlink -f $(shell $(GO) env GOPATH))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm afraid this won't work on macOS.

$ readlink -f 
readlink: illegal option -- f
usage: readlink [-n] [file ...]

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make's built-in realpath function might do what you need, though: https://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bmake guy, so thanks for pointing me in the right direction.

Copy link
Contributor Author

@mqudsi mqudsi Mar 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benesch regarding CURDIR, I meant that the value of the two variables compared here:

ifeq "$(filter $(GOPATH)%,$(CURDIR))" ""

may differ in "symlinkage" while pointing to the same (with possibly either one using the symlink'd $HOME value).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It appears that $(CURDIR) has internally been set to the equivalent of $(realpath $(shell pwd)).

For compatibility with macOS. Thanks to @benesch.

Release note: None
@@ -201,7 +201,11 @@ UI_ROOT := $(PKG_ROOT)/ui
SQLPARSER_ROOT := $(PKG_ROOT)/sql/parser

# Ensure we have an unambiguous GOPATH.
GOPATH := $(shell $(GO) env GOPATH)
GOPATH := $(realpath $(shell $(GO) env GOPATH))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fix looks good. Thanks!

Makefile Outdated
# GOPATH need not be explicitly set if it is the default $HOME/go
ifeq ($(strip $(GOPATH)),)
GOPATH := $(realpath $(shell echo $$HOME/go))
endif
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not to commit this workaround yet. I think it's papering over something more serious.

Makefile Outdated
@@ -201,7 +201,11 @@ UI_ROOT := $(PKG_ROOT)/ui
SQLPARSER_ROOT := $(PKG_ROOT)/sql/parser

# Ensure we have an unambiguous GOPATH.
GOPATH := $(shell $(GO) env GOPATH)
GOPATH := $(shell readlink -f $(shell $(GO) env GOPATH))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. It appears that $(CURDIR) has internally been set to the equivalent of $(realpath $(shell pwd)).

@benesch
Copy link
Contributor

benesch commented Mar 31, 2018 via email

If `go env GOPATH` does not return a workable value, that means there is
something wrong with the golang deployment and it is unsafe to assume
the value of GOPATH and attempt to proceed.

Error out with a message about GOPATH resolution if `go env GOPATH` does
not come back with a good value.

Release note: None
@mqudsi
Copy link
Contributor Author

mqudsi commented Mar 31, 2018

Updated per the review above. Net patch: realpath + error on blank GOPATH.

@benesch
Copy link
Contributor

benesch commented Mar 31, 2018

Great, thanks! I filed golang/go#24623 upstream for the issue we observed with GOROOT=$HOME/go.

Merging on green.

@benesch
Copy link
Contributor

benesch commented Apr 1, 2018

Squashed these down into one commit to save you an additional review roundtrip: #24391. Thanks again for your help, @mqudsi!

craig bot added a commit that referenced this pull request Apr 1, 2018
24391: Makefile: further improve GOPATH detection r=RaduBerinde a=benesch

Squash of #24387.

Closes #24387.

---

It is necessary to use `realpath` to get the real GOPATH, as symlinks
may be in play. For instance, on FreeBSD `/home` is symlinked to
`/usr/home/`, but the former is often used. If `realpath` isn't used,
the string-based prefix matching will incorrectly claim that CWD is not
a child of GOPATH.

Additionally, if `go env GOPATH` does not return a workable value, that
means there is something wrong with the golang deployment and it is
unsafe to assume the value of GOPATH and attempt to proceed. Error out
with a message about GOPATH resolution if `go env GOPATH` does not come
back with a good value.

Release note (build change): None
@craig craig bot closed this in #24391 Apr 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants