What does go install do? - go

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

Related

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 install creates directory os_arch - select different output directory

I have this folder structure for my fib package:
$ tree
.
└── src
└── fib
├── fib
│   └── main.go
├── fib.go
└── fib_test.go
(main.go is in package main, fib(_test).go is in package fib)
GOPATH is set to $PWD/src, GOBIN is set to $PWD/bin. When I run go install fib/fib, I get a file called fib in the directory bin (this is what I expect):
$ tree bin/
bin/
└── fib
But when I set GOOS or GOARCH, the directory in the form GOOS_GOARCH is created:
$ GOARCH=386 GOOS=windows go install fib/fib
$ tree bin/
bin/
└── windows_386
└── fib.exe
This is not what I want. I'd like to have the file fib.exe in the bin directory, not in the sub directory bin/windows_386.
(How) is this possible?
That doesn't seem possible, as illustrated in issue 6201.
GOARCH sets the kind of binary to build.
You might be cross-compiling: GOARCH might be arm.
You definitely don't want to run the arm tool on an x86 system.
The host system type is GOHOSTARCH.
To install the api tool (or any tools) you need to use
GOARCH=$(go env GOHOSTARCH) go install .../api
and then plain 'go tool' will find them.
In any case (GOARCH or GOHOSTARCH), the go command will install in a fixed location that you cannot change.
The phrase "I (don't) want" is incompatible with the go tool; the go tool works how it works. You can a) copy the file to where you want it to be after installing it with the go tool or b) compile it yourself, e.g. by invoking 6g manually (here you can specify the output). If you are unhappy with how the go tool works, just switch to a build tool of your liking, e.g. plain old Makefiles. Note that the go tool helps you there too, e.g. by invoking the compiler via go tool 6g

Install a Go binary, keep dependencies / packages

When I build a Go binary, I usually do something like this:
go build -ldflags "-X main.basedir somevar" -o mybuilddir/bin/myfile mypackage/main"
this builds the binary and places it in a custom directory. But this doesn't keep the "intermediate" package files beneath pkg/, which would speed up the next compilation runs.
The solution would be go install, but I cannot specify an output directory. It seems to be possible to set the binary directory with GOBIN, but I am unable to specify the name of the executable (always main).
What is a possible solution to this problem?
Custom destionation directory
Custom name (not main)
Keep intermediate generated package files (.a)
This is the src directory of GOPATH:
GOPATH/src$ tree
.
└── mypackage
├── packagea
│   └── packagea.go
├── packageb
│   └── packageb.go
└── main
   └── mypackage.go
With go install, the package files (.a) are created in $GOPATH/pkg, with go build, I can't find the .a files anywhere.
Update Nov. 2017: Go 1.10 (Q1 2018) will add caching for go build and go install: see "go build rebuilds unnecessarily".
Original answer (2014)
With go install, the package files (.a) are created in $GOPATH/pkg, with go build, I can't find the .a files anywhere.
As mentioned in "How does the go build command work ?"
The final step is to pack the object file into an archive file, .a, which the linker and the compiler consume.
Because we invoked go build on a package, the result is discarded as $WORK is deleted after the build completes.
If we invoke go install -x two additional lines appear in the output
mkdir -p /home/dfc/go/pkg/linux_arm/crypto/
cp $WORK/crypto/hmac.a /home/dfc/go/pkg/linux_arm/crypto/hmac.a
This demonstrates the difference between go build and install;
build builds,
install builds then installs the result to be used by other builds.

GOPATH and Go Web Server: 'go run myserver.go'

I'm at the point where want to organize my Go web server into packages. Currently I have everything in a few files and I simply type: 'go run server.go foo.go bar.go'
How do I organize my files so I don't need to keep adding files to the command line. I've investigated the GOPATH variable but it doesn't seem to work.
export GOPATH=$HOME/myserver
I moved my files to the src/ subdirectory.
myserver/src/server.go
myserver/src/foo.go
myserver/src/bar.go
Shouldn't 'go run' search $HOME/myserver/src for all go files?
I've tried these examples but they don't work.
go run server.go; # Doesn't work
go run src/server.go; # Doesn't work
By the way, all files are in 'package main'
This info is covered really well on golang.org
Read this about how to write Go code
And this about organizing go code
Tip: you can run go run * to run all files in a folder
Your above example should look something like this
$GOPATH=$HOME
The GOPATH should have:
$GOPATH
src/
pkg/
bin/
$GOPATH/src is where you would store your source code for each go project
$GOPATH/src/myserver would contain your myserver program
cd to $GOPATH/src/myserver and run go install and you would now have your myserver binary located at $GOPATH/bin/myserver
Add the location of your bin to your path export PATH=$PATH:$GOPATH/bin and you can run myserver to start your go program
go run will look for a file (or wildcard) in your current working directory.
If you would like to run your programs from anywhere, either use go build same as you would go run and move the binaries where appropriate or, better yet, set your $GOBIN environment variable and add it your $PATH -- then run go install * in your project directory.
It's also probably a good idea to make specific directories for projects instead just dumping it all in $GOPATH/src

Correct directory structure for a Go Project?

I'm relatively new to Go and I've recently created a project that's going up on GitHub. I've tried to follow guides but there's a pressing question of why my binaries end up in src/?
My layout is like this:
ssm/ - Name of project
LICENSE
README.md
src/ - Source Code
files.go - All my source code is here.
src - The compiled binary ends up here
bin/ - Binaries
I set my $GOPATH to ~/Documents/Programming/Go/. From my gopath, I can't type go build ssm because it cannot find package. If I cd into the directory, it complains it can't load package: package .: no Go source files.
I have to actually go into src and compile there, which means the binary isn't in bin/.
What am I doing wrong?
See https://code.google.com/p/go-wiki/wiki/GithubCodeLayout
To be compatible with go get, your project's package name needs to be fully-qualified under the github.com domain:
$GOPATH/
src/github.com/<user>/ssm/
.git
LICENSE
README.md
files.go
bin/
Note that the base of the git repository (.git) is not the same as the $GOPATH.
Also, go build <package> will output a compiled executable to the current directory. If you want the exe to go to bin/, use go install <package> instead.
Your go code you can kept in a workspace. A workspace contains many source files (git, hg, svm, etc.). The Go tool understand the layout. We don't require Makefile or build.xml here. The basic directory layout is everything. If in any case if you are going to change the file layout, accordingly you need to change the build.
This is the general structure you can follow,
$GOPATH/
src/
github.com/username/repo/
mypkg/
mysrc1.go
mysrc2.go
cmd/mycmd/
main.go
bin/
mycmd
And, this is the standard workspace
$GOPATH/
bin/fixhub # installed binary
pkg/darwin_amd64/ # compiled archives
code.google.com/p/goauth2/oauth.a
github.com/...
src/ # source repositories
code.google.com/p/goauth2/
.hg
oauth # used by package go-github
...
github.com/
golang/lint/... # used by package fixhub
.git
google/go-github/... # used by package fixhub
.git
dsymonds/fixhub/
.git
client.go
cmd/fixhub/fixhub.go # package main
go get fetch many repositories whereas go install builds a binary out of them. It's convenient and easy to go for go development quickly. And, everyone in the go community follows the same. This puts src, bin and pkg into the home directory. And, $HOME/bin is already in our path before creating our workspace.

Resources