go install c shared output path - go

i'm trying to install a library inside a package. However I don't understand where it compiles to.
Structure is like so:
package/cmd/library
I can install other executable targets fine with go install. My paths are set correctly. However now I want to build my shared library target and deploy it somewhere (this deployment step can be done manually). I'm running into two different issues.
Issue one, I can't seem to install it at all:
go install -buildmode=c-shared bpackage/cmd/library#latest
Returns with:
go install: no install location for directory /home/tpm/go/pkg/mod/package/cmd/library outside GOPATH
For more details see: 'go help gopath'
which tells me that it installs somewhere other than in my gopath, I'm just not sure where that might be.
Issue 2, using the -o flag doesn't work with go install, so I can't seem to alter the output location to place it inside the GOPATH (i did try setting the GOBIN to within my gopath, but since other commands work fine I don't think this should be causing any issue)

Quoting Ian from https://github.com/golang/go/issues/24253
Note that it doesn't make a great deal of sense to use go install -buildmode=c-shared. The expectation is that people will use go build -buildmode=c-shared -o foo.so. The only point of using -buildmode=c-shared is to use the shared library somewhere, and using go install without -o will put the shared library in a relatively unpredictable place.

Related

How to `go install` to bin inside module dir?

For example, when I run this
GOOS="windows" GOARCH="386" go install ./something
The executable would be created at
$GOROOT/bin/$GOOS_$GOARCH/something.exe
I want the executable to be created at
path/to/my/module/bin/$GOOS_$GOARCH/something.exe
EDIT
To clarify, I ask the question in the context of cross compiled builds inside a module.
I get the desired result using this command inside my module. I'd like to avoid specifying the path.
GOOS="windows" GOARCH="386" go build -o ./bin/$GOOS_$GOARCH/something.exe ./something
So, is it possible to get the same with go install?
Setting GOBIN results in an error
GOBIN=$(pwd)/bin GOOS="windows" GOARCH="386" go install ./something
# go install: cannot install cross-compiled binaries when GOBIN is set
Don't use go install for cross compiling. Use go build with -o flag.
Here is some history regarding GOBIN, robpike posted an issue stating "I have $GOBIN set but the go tool is ignoring it when installing..."
This article mentions
"When cross compiling, you should use go build, not go install. This is the one of the few cases where go build is preferable to go install...
The reason for this is go install always caches compiled packages, .a files, into the pkg/ directory that matches the root of the source code...
This logic also holds true for the standard library, which lives in /usr/local/go/src, so will be compiled to /usr/local/go/pkg/$GOOS_$GOARCH. This is a problem, because when cross compiling the go tool needs to rebuild the standard library for your target, but the binary distribution expects that /usr/local/go is not writeable.
Using go build rather that go install is the solution here, because go build builds, then throws away most of the result (rather than caching it for later), leaving you with the final binary in the current directory, which is most likely writeable by you"

How to build/install cross-compiled nested packages quickly?

I have a repository with a group of nested go packages organized as follows:
$GOPATH/src/
- mypackage/common/utils.go
- mypackage/app1/main.go
- mypackage/app2/main.go
...
It compiles to a handful of binaries. For releasing, I'm cross-compiling for a multitude of platforms/archs (I deploy repeatedly with a different GOOS and GOARCH). I'm trying to write the compilation results to a directory of my choice, but I'm fighting with the toolchain.
I can:
Combine GOBIN and go install when compiling for my own architecture
(i.e. not cross compiling):
# build + output all binaries in /somedir/bin
# this works great when compiling for my local architecture.
GOBIN=/somedir/bin go install mypackage/app1 mypackage/app2 mypackage/app3
But unfortunately, GOBIN conflicts with cross-compilation e.g:
# Throws: "cannot install cross-compiled binaries when GOBIN is set"
GOBIN=/somedir/bin GOARCH=amdm64 GOOS=darwin go install mypackage/app1 mypackage/app2
Use go build with GOOS=X and GOARCH=Y for each subpackage
# cross compile one of the binaries
cd /output/darwin-386-bin/ && \
GOOS=darwin GOARCH=386 go build mypackage/app1
# but if given multiple binaries, there is no output. (as documented)
GOOS=darwin GOARCH=386 go build mypackage/app1 mypackage/app2
When go build is given multiple packages, it no longer emits binaries -- it just checks that the code compiles. To emit all the binaries, it seems I have to run go build once for each subpackage, so it takes longer, esp when building with -a.
Another possible issue with using go build like this, is that it's potentially mixing binaries and intermediary results across multiple architectures in the same workspace. But maybe that's just a matter of taste. Hopefully the toolchain keeps cached results separate for different architectures.
How is this handled in practice? Should I treat each subpackage as an individual package, despite their shared common code (would it then be safe to build them all in parallel)?
Related articles:
go build vs go install: https://groups.google.com/forum/#!topic/golang-nuts/s8Csz3-7EXA (Little info on cross-compilation, or multipackage setups)
cross compile with go 1.5.: https://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5 (does not specifically address multipackage / common code compilation. Also, the statement about having to recompile the standard library into /usr/local/go/pkg seems to no longer hold in 1.9.1, as far as I can tell)
Go build multiple nested packages: Go build multiple/nested packages? . ( The accepted answer, go build ./... behaves the same as passing multiple packages in a single build command, and therefore outputs no binaries. The thread also does not cover cross compilation)
What I'm about to suggest feels like a hack at best, but it might work for you if you're cross-compiling stuff in a container or an isolated build environment.
You can drop the GOBIN from the install command:
# I'm not on this platform, so this is a cross compile
GOOS=darwin GOARCH=amd64 go install mypackage/app1 mypackage/app2
Assuming your package is in $GOPATH/src/mypackage the above command will install the two binaries to:
$GOPATH/bin/darwin_amd64/{app1, app2}
and the .a compile dependency files in:
$GOPATH/pkg/darwin_amd64/mypackage/{app1,app2,common}
If you're running this in a for loop for all the platforms you plan on supporting, one nuisance with this process is that when you pass GOOS=x GOARCH=y matching your local architecture (i.e. not cross compiling), then the executables will be placed directly in $GOPATH/bin/ and not $GOPATH/bin/x_y/.
(packages on the other hand always end up in $GOPATH/pkg/x_y/, cross compilation or not).
To determine your local architecture, you can follow steps in this answer: https://stackoverflow.com/a/35669816/5556676 .
Simulating GOBIN=/foo/bin GOOS=x GOARCH=y go install mypackage/app{1,2,3}
Changing $GOPATH has little effect on where go install writes output. With some go commands, like go get, you tweak where packages are installed by adding a new component at the front of $GOPATH. But in go 1.9, go install will always copy binaries in the bin/ folder that's a sibling of the src/ which contains the packages to install.
Instead of using GOBIN=/foo/bin, you can pretend your source files are in /foo/src/mypackage (you may use a symlink), and then do GOPATH=/foo GOOS=x GOARCH=y go install mypackage/app{1,2,3}. This will put binaries in /foo/bin, because of the behavior I describe in the previous paragraph.
It's probably simpler to just grab the binaries from where you expect them to be though, than mucking with copying source trees around.

Issues installing a go program

Im new to go and I have been unable to find any thing online for my issue.
I have downloaded this code https://github.com/hashicorp/http-echo and I would like to set it up so I can run this command.
$ http-echo -listen=:8080 -text="hello world"
I have been getting quite a few different path issues.
Currently I have the code sitting in this directory.
/Users/jon/go/src/github.com/hashicorp
When I try and install it I get this error
$ go install http-echo
can't load package: /usr/local/go/src/http-echo/handlers.go:9:2: non-standard import "github.com/hashicorp/http-echo/version" in standard package "http-echo"
Where should I keep go projects on an OSX computer, and how do I get this to install or compile?
The code currently seems to be in /usr/local/go/src/http-echo. Packages should always reside in the directory $GOPATH/src/package-name, e.g.: $GOPATH/src/github.com/hashicorp/http-echo. (unless you're using go modules).
It should work if you move the source to the correct path (/Users/jon/go/src/github.com/hashicorp/http-echo). Then execute:
go install github.com/hashicorp/http-echo
Even easier would be to use go get to download the package in the first place. Simply run the following command from any directory:
go get github.com/hashicorp/http-echo
And http-echo is automagically installed.
If you still get an error after this, make sure $GOPATH/bin is in your $PATH.

Go lang: how to install libxml2/gokogiri on windows

If there a relatively simple way to make go + libxml2 + gokogiri work on windows?
I mean that I may be can install it (but at the moment I can not, stuck with Package libxml-2.0 was not found in the pkg-config search path), but then I need to provide my utilite to other people, who will never be able (or would wish ) to install lall libxml2 dependencies, modify PATH etc on windows...
It work flawless on Ubuntu...
I found this https://github.com/moovweb/gokogiri/issues/49 thats funny with installation of Gimp 2 (what?!), but I still cannot make it run with such error, I guess might be issue with PATH, but all PATH are set
$ go get github.com/moovweb/gokogiri
# github.com/moovweb/gokogiri/help
Documents\go\src\github.com\moovweb\gokogiri\help\help.go:6:25: fatal error: lib
xml/tree.h: No such file or directory
#include <libxml/tree.h>
^
compilation terminated.
# github.com/moovweb/gokogiri/xpath
Documents\go\src\github.com\moovweb\gokogiri\xpath\expression.go:4:26: fatal err
or: libxml/xpath.h: No such file or directory
#include <libxml/xpath.h>
^
compilation terminated.
You are struggling because it is hard to combine packages that were built by different people for different purposes and get your environment set up correctly. I think it is best to use MSYS2, an environment for Windows that provides a consistent set of packages for things like gcc, go, libxml2, and iconv. MSYS2 has a package manager (pacman) that helps you easily install them and keep them updated.
I don't do much programming with Go, but I am familiar with MSYS2 and it seems like I was able to get gokogiri installed using MSYS2. You should open MSYS2's "MinGW-w64 Win64 Shell" from the Start menu (mingw64_shell.bat), and try running these commands:
pacman -S mingw-w64-x86_64-{gcc,go,libxml2,iconv}
export GOROOT=/mingw64/
export GOPATH=/c/Users/David/Documents/goproj/
mkdir -p $GOPATH
go get github.com/moovweb/gokogiri
I think GOPATH should be set to the directory of your project. If you run into an error, it might be because some pacman package is required that I didn't list here.
The string mingw-w64-x86_64-{gcc,go,libxml2,iconv} gets expanded by Bash into the following list of packages:
mingw-w64-x86_64-gcc
mingw-w64-x86_64-go
mingw-w64-x86_64-libxml2
mingw-w64-x86_64-iconv
If you are actually using 32-bit Windows, replace x86_64 with i686 in the instructions above.
If you are curious, the scripts for building those packages are here: https://github.com/Alexpux/MINGW-packages
As a disclaimer, I haven't actually compiled any go programs in MSYS2, so there could be big problems I am unaware of.
Also, one of the main developers of MSYS2 (alexpux) said this in the #msys2 IRC chat on 2015-06-21:
We not build go for a long time.
This package in very WIP state
Also see
https://github.com/Alexpux/MINGW-packages/issues/421
So you might need to fix some issues with the MSYS2 Go package and recompile it yourself to really make this work. But you have the PKGBUILD script that was used to build it, so maybe that will be less hard than what you are trying to do right now, which involves compiling/collecting every dependency of gokogiri.
MSYS2 would make your other installation of go, libxml2, and iconv obsolete. You can delete those things once you get your MSYS2 environment working.
If you are using visual studio and want to add dependency to your project then just install it using NuGet Package Manager it's easiest method.
Install command: Install-Package libxml2

"go build" became very slow after installing a new version of Go

After upgrading from Go 1.2.1 to 1.3 (Windows 7 64 bit) "go build" execution time has increased from around 4 to over 45 seconds. There were no other changes except the go version update. Switching off the virus scanner seems to have no effect. Any clues?
You probably have dependencies that are being recompiled each time. Try go install -a mypackage to rebuild all dependencies.
Removing $GOPATH/pkg also helps to ensure you don't have old object files around.
Building with the -x flag will show you if the toolchain is finding incompatible versions.
I have the exact same problem, running this command solves it:
go get -u -v github.com/mattn/go-sqlite3
Another tip: http://kokizzu.blogspot.co.id/2016/06/solution-for-golang-slow-compile.html
Using go1.6,
Simply run go build -i.
It will compile all the dependencies and store them at $GOPATH/pkg/*/* as .a files.
Later when you run go run main.go, everything is much faster.
What s really great is that if you use vendored dependencies (IE: a vendor folder in your project), deps are built appropriately within $GOPATH/pkg/**/yourproject/vendor/**
So you don t have to go get install/get/whatever and have a mix of vendor / global dependencies.
I suspect you got to re-build .a files after deps update (glide update or smthg like this), but i did not test that yet.
After Go 1.10, you'd just need to type go build. You'd not need to type: go build -i.
From the draft Go 1.10 document, here.
Build & Install
The go build command now detects out-of-date packages purely based on the content of source files, specified build flags, and metadata stored in the compiled packages. Modification times are no longer consulted or relevant. The old advice to add -a to force a rebuild in cases where the modification times were misleading for one reason or another (for example, changes in build flags) is no longer necessary: builds now always detect when packages must be rebuilt. (If you observe otherwise, please file a bug.)
...
The go build command now maintains a cache of recently built packages, separate from the installed packages in $GOROOT/pkg or $GOPATH/pkg. The effect of the cache should be to speed builds that do not explicitly install packages or when switching between different copies of source code (for example, when changing back and forth between different branches in a version control system). The old advice to add the -i flag for speed, as in go build -i or go test -i, is no longer necessary: builds run just as fast without -i. For more details, see go help cache.
I just experienced the same problem - updating from 1.4 to 1.5. It seems that the olds versions are somehow incompatible or are being rebuild every time as go build -x shows. Executing go get -v invalidates all packages or refetches them, I am not quite sure and go build -x shows quite less output.
You can build sqlite3 like this:
cd ./vendor/github.com/mattn/go-sqlite3/
go install
After that your project will b built much faster.
If you try as all other said but still not work, I suggest removing the directory of $GOPATH such as :
sudo rm -rf $GOPATH
cd yourproject
go get -d
go get -u -v github.com/mattn/go-sqlite3

Resources