goenv icon indicating copy to clipboard operation
goenv copied to clipboard

go get binaries: command not found

Open jfrux opened this issue 6 years ago • 20 comments

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?

jfrux avatar Aug 15 '17 12:08 jfrux

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.

jfrux avatar Aug 15 '17 12:08 jfrux

@joshuairl Hey, sorry for the late reply.

This must be done manually by the developer. goenv intentionally doesn't handle this.

syndbg avatar Aug 17 '17 08:08 syndbg

@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.

twlz0ne avatar Oct 31 '17 06:10 twlz0ne

@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.

ajmeyghani avatar Feb 13 '18 06:02 ajmeyghani

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.

syndbg avatar Dec 27 '18 02:12 syndbg

TL;DR: Do I understand correctly that you have to do the following?

  1. Install the new binary manually to ~/.goenv/versions/<YOUR VERSION>/
  2. 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.

attil-io avatar Mar 06 '19 14:03 attil-io

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.

DuncanHills avatar Mar 08 '19 21:03 DuncanHills

Will respond in a bit

syndbg avatar Mar 08 '19 22:03 syndbg

@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.

syndbg avatar Mar 10 '19 23:03 syndbg

Hey that's awesome! I'll try it out and let you know what I find.

DuncanHills avatar Mar 11 '19 07:03 DuncanHills

@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 avatar Mar 12 '19 16:03 attil-io

@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 avatar Mar 12 '19 16:03 syndbg

@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.

attil-io avatar Apr 02 '19 11:04 attil-io

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.

pawamoy avatar Apr 18 '19 14:04 pawamoy

@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.

kadaan avatar Dec 02 '19 05:12 kadaan

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

yssource avatar Mar 29 '20 13:03 yssource

@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 avatar Mar 29 '20 14:03 yssource

@yssource Thanks for making the PR!

kadaan avatar Mar 29 '20 15:03 kadaan

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 ?

SkYNewZ avatar Nov 10 '21 15:11 SkYNewZ

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!!

magalhaes-andre avatar Mar 02 '22 19:03 magalhaes-andre

We can close this issue since it's been solved

ChronosMasterOfAllTime avatar Feb 19 '23 05:02 ChronosMasterOfAllTime