Golang: Installation directory error? - go

I have the error:
go install: no install location for directory /Users/xwilly/Dropbox/go/project/src outside GOPATH
I'm using go version 1.1 on OS X.
I can build & run but can't install packages.
My environment:
GOPATH=/Users/xwilly/Dropbox/go/project
PATH=/Library/Frameworks/Python.framework/Versions/2.7/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/go/bin:/Users/xwilly/Dropbox/go/project/bin
Project tree:
/Users/xwilly/Dropbox/go/project
bin
pkg
src
I can build without error:
..:src xwilly$ go build test.go
..:src xwilly$ go install test.go
go install: no install location for directory /Users/xwilly/Dropbox/go/project/src outside GOPATH
Here is a simple example:
xwilly$ cat test.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Bonjour")
}
xwilly$ go run test.go
Bonjour
xwilly$ go install test.go
go install: no install location for directory /Users/xwilly/Dropbox/go/project/src/learning outside GOPATH

Command go
GOPATH environment variable
Each directory listed in GOPATH must have a prescribed structure:
The src/ directory holds source code. The path below 'src' determines
the import path or executable name.
The pkg/ directory holds installed package objects. As in the Go tree,
each target operating system and architecture pair has its own
subdirectory of pkg (pkg/GOOS_GOARCH).
If DIR is a directory listed in the GOPATH, a package with source in
DIR/src/foo/bar can be imported as "foo/bar" and has its compiled form
installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
The bin/ directory holds compiled commands. Each command is named for
its source directory, but only the final element, not the entire path.
That is, the command with source in DIR/src/foo/quux is installed into
DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped so that you
can add DIR/bin to your PATH to get at the installed commands. If the
GOBIN environment variable is set, commands are installed to the
directory it names instead of DIR/bin.
Here's an example directory layout:
GOPATH=/home/user/gocode
/home/user/gocode/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)
Your directory structure is wrong. You are trying to install a command (package main). It should be in a source directory named after your command. See the quux command above.
In your case, assume your command is going to be named billy.
$ mkdir -p /Users/xwilly/Dropbox/go/project/src/billy
which is inside your GOPATH. Move your test.go file to this directory. Run
$ go install billy
The command billy should, unless you have set GOBIN, be installed in the
/Users/xwilly/Dropbox/go/project/bin
directory inside your GOPATH, which should be in your PATH.

Related

Go get behaving erratically during build and with VScode

Using Go version go1.17.1 linux/amd64 on my CentOS 7. GOPATH and GOROOT are set in my .bashrc in the order:
export GOPATH="${HOME}/.go"
export GOROOT="/usr/local/go"
export PATH="$PATH:${GOPATH}/bin:${GOROOT}/bin"
Got my project in /home/wsb/_projects/local/parlance:
[wsb#localhost local]$ pwd
/home/wsb/_projects/local
[wsb#localhost local]$ tree
.
└── parlance/
└── main.go
└── utils.go
From the terminal, using go get stores src in /home/wsb/.go/pkg/mod/cache... folder
[wsb#localhost parlance]$ go get -v -u github.com/gorilla/mux
go: downloading github.com/gorilla/mux v1.8.0
github.com/gorilla/mux
[wsb#localhost parlance]$ go build main.go
main.go:3:8: no required module provides package github.com/gin-gonic/gin: go.mod file not found in current directory or any parent directory; see 'go help modules'
[wsb#localhost parlance]$
[root#localhost /]# find -iname gin
./home/wsb/.go/pkg/mod/cache/download/github.com/gin-gonic/gin
Why would it throw error on build?
Using go mod is the key here for managing packages for any particular projects.
go mod is used for installing and tracking external packages outside of packages in GOPATH.
From within existing project root directory parlance we initialize go mod using:
[wsb#localhost parlance]$ go mod parlance
It creates two files within the project root directory: go.mod and go.sum.
Now we can go get any module we will use specifically for our project.
go get github.com/gin-gonic/gin
go get github.com/gofiber/fiber/v2
This creates external package requirement details in go.mod and their respective checksum in go.sum file.
Finally, we can build/run our package like
go build main.go
go run main.go

Building Golang project properly

I have a project structure that looks like so:
I was planning on just using a shell script (build.sh) to set GOPATH and build the project.
I am not sure how to build a Golang project properly, my short term goal is to just to build the packages in the src directory and put the binaries into the bin directory.
I am not sure what go build command can do that, I have tried a few things.
So first my question is - is this a reasonable project structure and second, how can I compile my src directory to bin?
What I have gives me the following error:
can't load package: package .: no buildable Go source files in /home/oleg/WebstormProjects/oresoftware/stack-server
So I believe I need to tell Go to look in the src directory, because Go is only looking for .go files in the project root, but I am not sure how to do that.
If it matters, the main.go file has a package name of "main".
GOPATH=$PROJECT_DIR && cd $PROJECT_DIR && go install main
Also move your main.go file into src/main/main.go.
This will produce a bin/main executable.
If you have multiple executables you wanna build, you have to put each main.go file into a separate folder/package. The name of the generated executable is taken from the directory name the file is inside. The package name of the main.go files must always be main if it should create a binary.
To compile multiple executables you have to use:
GOPATH=$PROJECT_DIR && cd $PROJECT_DIR && go install ...
The ... matches all folders/packages.

go ignoring vendor directory

Everything I read about the vendor directory gives me the understanding that if I have a directory:
$GOPATH/src/vendor
And put my dependencies in there (I am using godeps), when doing go run, go should check in that directory first.
If I run my code in a Docker image I have, this works fine. However now that I try to run the same code on my Windows machine, go simply ignores the vendor/ directory, and fails to find the dependencies.
What am I doing wrong?
main.go:7:2: cannot find package "gopkg.in/alecthomas/kingpin.v2" in any of:
C:\Go\src\gopkg.in\alecthomas\kingpin.v2 (from $GOROOT)
C:\Users\js\dev\my_project\rest\src\gopkg.in\alecthomas\kingpin.v2 (from $GOPATH)
C:\Users\js\dev\go\src\gopkg.in\alecthomas\kingpin.v2
Is the output when I try to do:
go run main.go
A directory vendor/ exists in this directory.
go version go1.7 windows/amd64
The exact commands I run (in windows cmd.exe)
> cd C:\Users\js\dev\my_project\rest\
> set GOPATH=C:\Users\js\dev\my_project\rest\;c:\Users\js\dev\go
> cd src
> dir
...
2016-09-01 23:20 2 923 main.go
...
2016-09-03 01:27 <DIR> vendor
> go run main.go
The reason this did not work is because you are not supposed to put any code directly into the $GOPATH/src/ directory.
The solution is to put your project into a sub-directory like so:
$GOPATH/src/app/*.go
Seems your GOPATH is incorrect?
The GOPATH should specify the location of your workspace i.e. directory containing src, pkg and bin directories at its root.
Try doing
set GOPATH=C:\Users\js\dev\my_project\rest\;c:\Users\js\dev\go
More details at: https://golang.org/doc/code.html
The first thing to understand is that godep save is simply copying dependencies from your $GOPATH to a vendor directory inside your project.
You will have to go get your dependencies first. After you have them in $GOPATH, you can do a godep save to copy the current version to your project, and be assured that even if the version in $GOPATH changes, you will have a fixed version in your project until you explicitly change it via godep.
So, if I have a $GOPATH of /home/me/go_workspace, and a project called $GOPATH/src/github.com/project_x with a dependency of github.com/you/xyz, then I would do go get github.com/you/xyz, and godep save from within my project directory. This would create a vendor folder with the dependency at its current commit inside.

What does go install do?

The docs say nothing about what build vs install does
My expectation was that it's like make install; i.e. it takes the compiled stuff and puts in its final location (/usr/local/bin/my_new_toy or whatever) but it seems that it puts things in GOROOT/bin
Can I tell go to do a make install - i.e. put things elsewhere? Or do I just write a makefile (please tell me no)?
go build vs go install:
go build just compiles the executable file and moves it to the destination.
go install does a little bit more. It moves the executable file to
$GOPATH/bin and caches all non-main packages which are imported to
$GOPATH/pkg. The cache will be used during the next compilation provided the
source did not change yet.
A package tree after go build and go install:
.
├── bin
│ └── hello # by go install
└── src
└── hello
├── hello # by go build
└── hello.go
More detailed information.
If you want binary files to go to a specific location, you can use the environment variable GOBIN :
The bin/ directory holds compiled commands. Each command is named for
its source directory, but only the final element, not the entire path.
That is, the command with source in DIR/src/foo/quux is installed into
DIR/bin/quux, not DIR/bin/foo/quux. The foo/ is stripped so that you
can add DIR/bin to your PATH to get at the installed commands. If the
GOBIN environment variable is set, commands are installed to the
directory it names instead of DIR/bin.
Source : http://golang.org/cmd/go/#hdr-GOPATH_environment_variable
GOBIN=/usr/local/bin/ go install
If you want per-project bin/ directory then you can simply append your project path to GOPATH, however you must have your code under $project-path/src/ and go install will put all the binaries in $project-path/bin.
export GOPATH=/dir1:/dir2:/dir3
If GOBIN is not set, binaries from /dir1/src end up in /dir1/bin,
binaries from /dir2/src end up in /dir2/bin, and so on (and binaries
from $GOROOT/src end up in $GOROOT/bin).
Source : https://groups.google.com/forum/#!topic/golang-nuts/-mN8R_Fx-7M
And you can also just use (thanks JimB):
go build -o /path/binary-name

Go install fails with error: no install location for directory xxx outside GOPATH

~/src/go-statsd-client> echo $GOPATH
/Users/me/gopath
~/src/go-statsd-client> echo $GOROOT
/usr/local/Cellar/go/1.1.1\
~/src/go-statsd-client> go install
go install: no install location for directory /Users/me/src/go-statsd-client outside GOPATH
No matter what structure the project is in this always fails with the same message. Go build works perfectly.
Here is my go env
GOARCH="amd64"
GOBIN=""
GOCHAR="6"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/me/gopath"
GORACE=""
GOROOT="/usr/local/Cellar/go/1.1.1"
GOTOOLDIR="/usr/local/Cellar/go/1.1.1/pkg/tool/darwin_amd64"
CC="gcc"
GOGCCFLAGS="-g -O2 -fPIC -m64 -pthread -fno-common"
CGO_ENABLED="1"
This is on Mac OSX Mountain Lion and go was installed with homebrew.
For any OS X users and future me, you also need to set GOBIN to avoid this confusing message on install and go get
mkdir bin
export GOBIN=$GOPATH/bin
When you provide no arguments to go install, it defaults to attempting to install the package in the current directory. The error message is telling you that it cannot do that, because the current directory isn't part of your $GOPATH.
You can either:
Define $GOPATH to your $HOME (export GOPATH=$HOME).
Move your source to within the current $GOPATH (mv ~/src/go-statsd-client /User/me/gopath).
After either, going into the go-statsd-client directory and typing go install will work, and so will typing go install go-statsd-client from anywhere in the filesystem. The built binaries will go into $GOPATH/bin.
As an unrelated suggestion, you probably want to namespace your package with a domain name, to avoid name clashing (e.g. github.com/you/go-statsd-client, if that's where you hold your source code).
You are using go install on a directory outside the GOPATH folder.
Set your GOBIN env variable, or move src folder inside GOPATH.
GOPATH/
bin/
src/
go-statsd-client/
More info: GO BUILD Source code, line 296
You need to setup both GOPATH and GOBIN. Make sure you have done the following (please replace ~/go with your preferred GOPATH and subsequently change GOBIN). This is tested on Ubuntu 16.04 LTS.
export GOPATH=~/go
mkdir ~/go/bin
export GOBIN=$GOPATH/bin
The selected answer did not solve the problem for me.
You'll want to have 3 directories inside your chosen GOPATH directory.
GOPATH
/bin
/src
/someProgram
program.go
/someLibrary
library.go
/pkg
Then you'll run go install from inside either someProgram (which puts an executable in bin) or someLibrary (which puts a library in pkg).
I had this problem on Windows.
My problem was that my %GOPATH% environment variable was set to
C:\Users\john\src\goworkspace
instead of
C:\Users\john\src\goworkspace\
Adding the missing trailing slash at the end fixed it for me.
For what it's worth, here's my .bash_profile, that works well for me on a mac with Atom, after installing go with Homebrew:
export GOROOT=`go env GOROOT`
export GOPATH=/Users/yy/Projects/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
In my case (OS X) it was because I have set GOPATH to /home/username/go (as per the book) instead of /Users/username/go
I'm on Windows, and I got it by giving command go help gopath to cmd, and read the bold text in the instruction,
that is if code you wnat to install is at ..BaseDir...\SomeProject\src\basic\set, the GOPATH should not be the same location as code, it should be just Base Project DIR: ..BaseDir...\SomeProject.
The GOPATH environment variable lists places to look for Go code. On
Unix, the value is a colon-separated string. On Windows, the value is
a semicolon-separated string. On Plan 9, the value is a list.
If the environment variable is unset, GOPATH defaults to a
subdirectory named "go" in the user's home directory ($HOME/go on
Unix, %USERPROFILE%\go on Windows), unless that directory holds a Go
distribution. Run "go env GOPATH" to see the current GOPATH.
See https://golang.org/wiki/SettingGOPATH to set a custom GOPATH.
Each directory listed in GOPATH must have a prescribed structure:
The src directory holds source code. The path below src determines the
import path or executable name.
The pkg directory holds installed package objects. As in the Go tree,
each target operating system and architecture pair has its own
subdirectory of pkg (pkg/GOOS_GOARCH).
If DIR is a directory listed in the GOPATH, a package with source in
DIR/src/foo/bar can be imported as "foo/bar" and has its compiled form
installed to "DIR/pkg/GOOS_GOARCH/foo/bar.a".
The bin directory holds compiled commands. Each command is named for
its source directory, but only the final element, not the entire path.
That is, the command with source in DIR/src/foo/quux is installed into
DIR/bin/quux, not DIR/bin/foo/quux. The "foo/" prefix is stripped so
that you can add DIR/bin to your PATH to get at the installed
commands. If the GOBIN environment variable is set, commands are
installed to the directory it names instead of DIR/bin. GOBIN must be
an absolute path.
Here's an example directory layout:
GOPATH=/home/user/go
/home/user/go/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)
..........
if GOPATH has been set to Base Project DIR and still has this problem, in windows you can try to set GOBIN as Base Project DIR\bin or %GOPATH%\bin.
Careful when running
export GOPATH=$HOME
Go assume that your code exists in specific places related to GOPATH. So, instead, you can use docker to run any go command:
docker run -it -v $(pwd):/go/src/github.com/<organization name>/<repository name> golang
And now you can use any golang command, for example:
go test github.com/<organization name>/<repository name>
In windows, my cmd window was already open when I set the GOPATH environment variable.
First I had to close the cmd and then reopen for it to become effective.
On OSX Mojave 10.14, go is typically installed at /usr/local/go.
Hence, setup these ENVs and you should be good to go.
export GOPATH=/usr/local/go && export GOBIN=/usr/local/go/bin
Also, add these to your bash_profile or zsh_profile if it works.
echo "export GOPATH=/usr/local/go && export GOBIN=/usr/local/go/bin" >> ~/.bash_profile && source ~/.bash_profile

Resources