goenv
goenv copied to clipboard
go get binaries: command not found
Okay so, I'm new to Go, and found goenv since I'm familiar with rbenv, pyenv, etc.
I'm having trouble getting stuff installed with go get
commands that have binaries to actually ever say anything other than "command not found".
Forgive me if this has already been discussed, I did browse the closed issues and the open issues but couldn't find exactly this.
I'm assuming this works a lot like rbenv, etc.
I use goenv
as I would any other.
goenv install 1.8.3
goenv global 1.8.3
I install dependencies such as revel
and dep
with:
go get -u github.com/golang/dep/cmd/dep
go get github.com/revel/revel
goenv rehash
and I still am getting:
-bash: dep: command not found
-bash: revel: command not found
In my ~/.bash_profile on MacOS Sierra:
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
export GOPATH="$HOME/go"
As seen above, I even tried something from another closed issue for setting GOPATH=
to ~/go as default. But no dice.
Any tips on this?
Once I added these lines, it seems to have helped.
export GOPATH="$HOME/go"
export PATH="$PATH:$GOPATH/bin"
But I'm not sure that should be required if goenv
works and manages these things but I'll roll with it for now.
@joshuairl Hey, sorry for the late reply.
This must be done manually by the developer. goenv
intentionally doesn't handle this.
@syndbg Same here.
Environment
$ cd ~/.goenv
$ git log --pretty=format:"%C(blue)%ad %C(yellow)%h %C(red)%d %C(reset)%s %C(green)[%an]" --topo-order --date=short -1
2017-10-26 e7ed8e5 (HEAD -> master, tag: 1.7.0, origin/master, origin/HEAD) Merge pull request #35 from kteru/feature/1.9.2_1.8.5 [Anton Antonov]
$ env | grep go
GOENV_ROOT=/Users/myth/.goenv
PATH=/usr/local/sbin:/Users/myth/.goenv/shims:/Users/myth/.goenv/bin:/usr/local/opt/php70/bin:/Users/myth/.nodenv/shims:/Users/myth/.composer/vendor/bin:/Users/myth/.local/bin:/Users/myth/.rbenv/shims:/Users/myth/.pyenv/shims:/Users/myth/.dotfiles/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Library/TeX/texbin:/Applications/Wireshark.app/Contents/MacOS
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/myth/go"
GORACE=""
GOROOT="/Users/myth/.goenv/versions/1.9.0"
GOTOOLDIR="/Users/myth/.goenv/versions/1.9.0/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/vq/k0y6n92j6r5dk_hx_jrl62jh0000gn/T/go-build228413040=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
Reproduce steps
$ vi ~/.goenv/libexec/goenv-which
41 for version in "${versions[@]}"; do
42 if [ "$version" = "system" ]; then
43 PATH="$(remove_from_path "${GOENV_ROOT}/shims")"
44 GOENV_COMMAND_PATH="$(command -v "$GOENV_COMMAND" || true)"
++45 >&2 echo "PATH(gover: system): $PATH"
++46 >&2 echo "GOENV_COMMAND_PATH: $GOENV_COMMAND_PATH"
47 else
48 GOENV_COMMAND_PATH="${GOENV_ROOT}/versions/${version}/bin/${GOENV_COMMAND}"
++49 >&2 echo "PATH(gover: $version): $PATH"
++50 >&2 echo "GOENV_COMMAND_PATH: $GOENV_COMMAND_PATH"
51 fi
52 if [ -x "$GOENV_COMMAND_PATH" ]; then
53 break
54 fi
55 done
$ mv ~/go{,.bak}
$ go get -u github.com/nsf/gocode
PATH(gover: 1.9.0): /Users/myth/.goenv/libexec:/Users/myth/.goenv/plugins/go-build/bin:/usr/local/sbin:/Users/myth/.goenv/shims:/Users/myth/.goenv/bin:/usr/local/opt/php70/bin:/Users/myth/.nodenv/shims:/Users/myth/.composer/vendor/bin:/Users/myth/.local/bin:/Users/myth/.rbenv/shims:/Users/myth/.pyenv/shims:/Users/myth/.dotfiles/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Library/TeX/texbin:/Applications/Wireshark.app/Contents/MacOS:/Users/myth/go/bin
GOENV_COMMAND_PATH: /Users/myth/.goenv/versions/1.9.0/bin/go
$ goenv which gocode
PATH(gover: 1.9.0): /Users/myth/.goenv/libexec:/Users/myth/.goenv/plugins/go-build/bin:/usr/local/sbin:/Users/myth/.goenv/shims:/Users/myth/.goenv/bin:/usr/local/opt/php70/bin:/Users/myth/.nodenv/shims:/Users/myth/.composer/vendor/bin:/Users/myth/.local/bin:/Users/myth/.rbenv/shims:/Users/myth/.pyenv/shims:/Users/myth/.dotfiles/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/opt/X11/bin:/Library/Frameworks/Mono.framework/Versions/Current/Commands:/Library/TeX/texbin:/Applications/Wireshark.app/Contents/MacOS:/Users/myth/go/bin
GOENV_COMMAND_PATH: /Users/myth/.goenv/versions/1.9.0/bin/gocode
goenv: gocode: command not found
$ which ~/go/bin/gocode
/Users/myth/go/bin/gocode
Expected behavior
Can locate program file.
Actual behavior
Cannot locate program file.
@joshuairl (or anyone else who has the same issue), try the following:
goenv global 1.9.4
goenv rehash
now run go env
to check if your env is set up properly.
Documented at https://github.com/syndbg/goenv/blob/master/COMMANDS.md#goenv-rehash
I'll add a FAQ.md
document where this is addressed.
Will close with the PR, once it's made. I'll leave it open until then.
TL;DR: Do I understand correctly that you have to do the following?
- Install the new binary manually to
~/.goenv/versions/<YOUR VERSION>/
- Run
goenv rehash
Details:
As far as I understood, with the current settings go get XXX
will install XXX
to $GOPATH
, which is ~/go
by default. However, goenv rehash
will look in ~/.goenv/versions/<YOUR VERSION>/bin
, so it will not find the new binary.
If I set $GOPATH
to be ~/.goenv/versions/<YOUR VERSION>/
then I get the error message that:
$GOPATH must not be set to $GOROOT
.
From all this, and from what @syndbg wrote
This must be done manually by the developer. goenv intentionally doesn't handle this.
I get that the I must put manually the new binaries to the correct version, as I wrote above.
Remark
@jfrux suggested above, to add the following to .bashrc
:
export GOPATH="$HOME/go" export PATH="$PATH:$GOPATH/bin"
While I see how it fixes the problem, it basically kills the whole purpose of goenv
, by having again one global place for go binaries (at least for the utility programs).
E.g., I'm trying to install gb, which says:
Your gb installation is tightly coupled to the version of Go that built it. If you have multiple versions of Go installed, you will have to build a version of gb for each version installed.
So the above work-around is not good for that tool.
Bump, I don't really get the usefulness of this command if it doesn't segregate the binary installation directory as well. The user can easily add a global go bin directory to their path but goenv should install and hash commands from the current go directory's bin path.
Will respond in a bit
@DuncanHills @attil-io I've released https://github.com/syndbg/goenv/releases/tag/2.0.0beta6
It tackles exactly the problem of managing GOPATH
and GOROOT
.
Check out the changelog for exact changes.
Hey that's awesome! I'll try it out and let you know what I find.
@syndbg thanks for looking into it, I tried it, and this is what I found:
Now the custom binary gets installed to ~/go/1.11.2/bin/
.
However, it is still not available globally, even after doing goenv rehash
. (I.e. it does not get copied to ~/.goenv/shims
.)
Did I miss something?
@attil-io You have to modify your $PATH
env variable to include ~/go/1.11.2/bin/
.
With 2.0.0beta6
I've updated the installation instructions at https://github.com/syndbg/goenv/blob/master/INSTALL.md#basic-github-checkout
The relevant piece of info is
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
export PATH="$GOROOT/bin:$PATH"
export PATH="$GOPATH/bin:$PATH"
However, even then, the first time you install a new version, you have to source your .zshrc
(or whichever you use) again.
I'm initially very hesitant to modify the user's $PATH
when calling goenv rehash
, but if it's inconvenient enough, I am open to trying it out in another beta release.
@syndbg I tried it, but I still don't understand.
I have the following in my .bash_profile
:
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
export PATH="$GOROOT/bin:$PATH"
export PATH="$GOPATH/bin:$PATH"
And indeed, if I install a tool, e.g. gb
I can now use it from the command line. This part is ok.
However, I noticed that now the version of go
which is used always sticks to the path set in ~/.goenv/version
.
Consider the following:
I'm in $HOME
:
$ goenv versions
system
* 1.11.2 (set by /home/attilio/.goenv/version)
1.12.1
$ which go
/home/attilio/.goenv/versions/1.11.2/bin/go
--> OK
However, say I'm in a project using 1.12.1
:
$ goenv versions
system
1.11.2
* 1.12.1 (set by /home/attilio/p/test/.go-version)
$ which go
/home/attilio/.goenv/versions/1.11.2/bin/go
--> NOK
I think dynamically changing the $PATH
is not the best solution either.
Can't we have the extra binaries somehow installed into ~/.goenv/shims
instead? And then get rid of these two lines:
export PATH="$GOROOT/bin:$PATH"
export PATH="$GOPATH/bin:$PATH"
And still have correct go
and binaries versions.
Isn't the usual method of these *env tools to write a shim when installing a new package, shim that will itself run the right version of the package's binary/script?
goenv install VERSION
goenv global VERSION
# installs PACKAGE in VERSION,
# add shim in $GOENV_ROOT/shims, which is in PATH thanks to goenv init
go get -u PACKAGE
# now the shim is available
Then, when executed, the shim searches for the actual binary and execute it. It may also check what is the current version, if the real executable is available for this version, or other logic things, and display useful messages.
I currently have to do the following to make it partially work:
# I installed goenv with basher
export GOENV_ROOT="${BASHER_PACKAGES_PATH}/syndbg/goenv"
eval "$(goenv init -)"
export PATH=${GOPATH}/bin:${PATH}
...but now my PATH is fixed to the first global version I defined. If I change the global order, of I have a different local version defined, my PATH won't be updated and the executables won't be found. I'll have to manually update my PATH each time I change version.
@syndbg @pawamoy @attil-io @DuncanHills Why can't we have the shims support binaries that get created by go get
calls?
I was able to get this to work locally by changing go-rehash.list_executable_names
to:
# List basenames of executables for every Go version
list_executable_names() {
local version file
goenv-versions --bare --skip-aliases | \
while read version; do
for file in "${GOENV_ROOT}/versions/${version}/bin/"*; do
echo "${file##*/}"
done
# --- New Lines
if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then
local gopath="${HOME}/go/${version}"
if [ -n "${GOENV_GOPATH_PREFIX}" ]; then
gopath="${GOENV_GOPATH_PREFIX}/${version}"
fi
for file in "${gopath}/bin/"*; do
echo "${file##*/}"
done
fi
# --- New Lines
done
}
And goenv-whence.whence
to:
whence() {
local command="$1"
goenv-versions --bare | while read version; do
path="$(goenv-prefix "$version")/bin/${command}"
if [ ! -x "$path" ]; then
# --- New Lines
if [ "${GOENV_DISABLE_GOPATH}" != "1" ]; then
local gopath="${HOME}/go/${version}"
if [ -n "${GOENV_GOPATH_PREFIX}" ]; then
gopath="${GOENV_GOPATH_PREFIX}/${version}"
fi
path="${gopath}/bin/${command}"
if [ ! -x "$path" ]; then
continue
fi
else
# --- New Lines
continue
fi
fi
[ "$print_paths" ] && echo "$path" || echo "$version"
done
}
And lastly, goenv-which
to:
for version in "${versions[@]}"; do
if [ "$version" = "system" ]; then
PATH="$(remove_from_path "${GOENV_ROOT}/shims")"
GOENV_COMMAND_PATH="$(command -v "$GOENV_COMMAND" || true)"
else
GOENV_COMMAND_PATH="${GOENV_ROOT}/versions/${version}/bin/${GOENV_COMMAND}"
fi
if [ -x "$GOENV_COMMAND_PATH" ]; then
break
# --- New Lines
elif [[ "$version" != "system" && "${GOENV_DISABLE_GOPATH}" != "1" ]]; then
if [ -n "${GOENV_GOPATH_PREFIX}" ]; then
GOENV_COMMAND_PATH="${GOENV_GOPATH_PREFIX}/${version}/bin/${GOENV_COMMAND}"
else
GOENV_COMMAND_PATH="${HOME}/go/${version}/bin/${GOENV_COMMAND}"
fi
if [ -x "$GOENV_COMMAND_PATH" ]; then
break
fi
# --- New Lines
fi
done
Once that is done, my shim path contains shims for binaries that got create by running go get ...
:
❯ ls -al ~/.zplugin/plugins/syndbg---goenv/shims
.rwxr-xr-x 458 myuser 1 Dec 20:26 go*
.rwxr-xr-x 458 myuser 1 Dec 20:26 godoc*
.rwxr-xr-x 458 myuser 1 Dec 20:26 gofmt*
.rwxr-xr-x 458 myuser 1 Dec 21:17 gox*
.rwxr-xr-x 458 myuser 1 Dec 21:17 smartthings_exporter*
And then goenv which
works:
❯ goenv which gox
/Users/myuser/Source/golang/1.11.3/bin/gox
And goenv whence
works as well:
❯ goenv whence gox
1.11.3
Lastly, running the shimmed command works as well:
~/Source/golang/1.11.3/src/git..com/.../myapp ····························································GO v1.11.3
❯ gox --version
flag provided but not defined: -version
Usage: gox [options] [packages]
...
❯
But if I'm in a different folder and the go version doesn't have gox, then I get the correct response:
~/Source ···········································································
❯ gox
goenv: 'gox' command not found
The 'gox' command exists in these Go versions:
1.11.3
Finally, add the goenv-goget-plugin to goenv and it will automatically rehash when go get
commands complete.
I got the same problem. shim does not link to any bins, except the go and gofmt.
goenv shims
/home/jimmy/.goenv/shims/go
/home/jimmy/.goenv/shims/gofmt
ls ~/go/1.14.1/bin/
fillstruct gocode godef godoc godoctor gogetdoc goimports golangci-lint gomodifytags gopkgs gopls gorename gotests guru impl
goenv which godoc
goenv: 'godoc' command not found
@kadaan Thanks, Your solution works for me.
And, my environment configuration.
export GOENV_ROOT="$HOME/.goenv"
export PATH="$GOENV_ROOT/bin:$PATH"
if command -v goenv 1>/dev/null 2>&1; then
eval "$(goenv init -)"
fi
@yssource Thanks for making the PR!
I can't access shims form another Go version. Every in well configured…
❯ goenv shims # global shims
/Users/quentinlemaire/.goenv/shims/go
/Users/quentinlemaire/.goenv/shims/gofmt
/Users/quentinlemaire/.goenv/shims/spark
❯ goenv versions # current selected version
system
* 1.13.15 (set by /Users/quentinlemaire/Sources/XXX/faascale/.go-version)
1.17.3
❯ which spark # spark in known, well in $PATH
/Users/quentinlemaire/.goenv/shims/spark
❯ spark # but not accessible from another version
goenv: 'spark' command not found
The 'spark' command exists in these Go versions:
1.17.3
❯ cd
❯ spark # accessible from the global one (the one I installed it with)
2021/11/10 16:16:17 Warning: serving files without any filter!
2021/11/10 16:16:17 Serving . on 0.0.0.0:8080/...
^C
Do I need to reinstall binaries from each Go version I want to use ?
Once I added these lines, it seems to have helped.
export GOPATH="$HOME/go" export PATH="$PATH:$GOPATH/bin"
But I'm not sure that should be required if
goenv
works and manages these things but I'll roll with it for now.
This is great, solved an issue that i didn't found solution nowhere else! Thanks!!
We can close this issue since it's been solved