TL;DR: gb does not use the GOVENDOREXPERIMENT
, vendored code goes in $PROJECT/vendor/src
.
The GOVENDOREXPERIMENT
flag, which is enabled by default in Go 1.6, allows go gettable code to include some or all of its dependencies in a vendor/
folder at the top of its repository.
The GOVENDOREXPERIMENT
flag has no effect on gb.
gb does not use go get
to retrieve dependencies, and gb projects are not go gettable.
You can vendor dependencies (via gb vendor fetch
or manually) that themselves include a vendor/
folder, but gb will ignore them for the purposes of dependency resolution.
To resolve these ignored dependencies, you can either copy them from each dependency’s vendor/
folder to the top level of your $PROJECT/vendor/src
directory, or vendor a fresh copy with gb vendor fetch
.
The latter is the recommended process so the dependencies’ location is recorded in the gb vendor manifest file.
Irrespective of the way you choose to build up your $PROJECT/vendor/src
folder, the responsibility of deciding which copy of a particular dependency’s source to use falls to you, the project owner.
Building or testing with the race detector requires that your Go installation have a current version of the race enabled runtime and standard library. If not, gb will exit with an error like this:
% gb build -race
FATAL: go installation at /Users/dfc/go is missing race support. See https://getgb.io/faq/missing-race-support
To solve this error, you need to install
If you have installed Go from the https://golang.org/ website, your operating system’s distribution, or some mechanism other than compiling Go from source, then you should not receive this error. All Go distributions from https://golang.org/ come with the race runtime properly built. If gb says that your Go installation is missing race support, your Go install may be incorrectly installed.
I strongly recommend using the official binary distributions from https://golang.org/, they are very well tested and known to work.
If you have compiled Go from source using ./make.bash
or ./all.bash
(or the Windows equiv.), the race enabled runtime will not be built.
To build the race enabled runtime and standard library, run the following command:
go install -a -race std
DO NOT RUN THIS COMMAND IF YOU HAVE NOT BUILT GO FROM SOURCE
gb
is only concerned with building code inside your project, how gets there and how that code is updated, is not gb
’s concern.
With that said, the gb-vendor
plugin can help fetch and manage vendored code.
Go code is organised into packages. Every package has a name, which is derived from its package
declaration, and an import path which is derived from its relative location inside $PROJECT/src
(or inside $PROJECT/vendor/src
).
As an example the file a.go
containing the declaration package a
inside the directory $PROJECT/src/github.com/dfc/a
has the name a
, and the import path github.com/dfc/a
.
There exists an ambiguity if Go code is placed directly at the root of the project’s source directory, e.g., $PROJECT/src/a.go
. In this case the package’s name is a
, but the package’s import ../faq/path is _em_blank_/em__ as its directory name is the same as the project_rsquo.css;s source directory, $PROJECT/src
.
It is not possible to use a package with a blank import path: import ""
is a syntax error. A blank import path gives rise to two problems.
First, as gb
always works in terms of package import ../faq/paths_ a package with a blank import path_mdash.css;that is a package whose source is stored in $PROJECT/src
—is invisible when using the globbing operators like gb build all
and gb build github.com/...
.
Second, passing gb
a relative path to the package—i.e., gb build .
or gb build ..
—to explicitly tell gb
to build the source in a particular location (and infer the import path later) will result in an error.
% pwd /home/dfc/devel/demo3/src/a % gb build .. # build the package directly above this directory FATAL command “build” failed: “/home/dfc/devel/demo3/src” is not a package
To avoid this situation, we recommend that all Go code inside gb
projects be placed in subdirectories of $PROJECT/src/
.
Some systems with the git plugin for oh-my-zsh
installed include an alias gb
to git branch
. This conflicts with gb
.
If you see this error running gb
% gb fatal: Not a git repository (or any of the parent directories): .git % which gb gb: aliased to git branch
You can remove the alias with
% unalias gbSee also issue #4
The short answer is yes: you can vendor source from one gb
project to another—just copy the code from your $PROJECT/src/
into the downstream project.
Vendoring dependencies is similar; you’ll need to merge the contents of your libraries $PROJECT/vendor/src/
into the downstream’s vendor directory.
Unfortunately gb
cannot help you with this, as Go projects don’t have any concept of versions; there is no way you can look at the source of a Go package and ask it “What version are you?”
Now you might have commit hashes for both copies of a particular package you are vendoring, and you might be able to take those commit hashes and look them up in the source repository and say, “Hash abced
is newer than hash ed3fc
.”
Ultimately this is down to the project owner—the one consuming the code—and not the library developer—the one producing the code—to solve.
Additionally, if your organisation is happy to use tools like Git submodules or Git subtrees, then this can make it easier for the downstream project to at least know which revision of a vendored dependency it is dealing with.
gb
does not mandate the use of Git subtrees or submodules; all it cares about is that the source is present inside $PROJECT/src
and $PROJECT/vendor/src
.
Yes.
gb
is agnostic to the source control system you use to manage your project. If your source control system has a concept of linking different repositories together, a la, git submodules or svn externals, then you can use that rather than copying code.
The Go authors agree that vendoring, taking a copy of your dependencies, is the path to repeatable builds – we just disagree on the method.
The Go authors are recommending vendoring by copying the source of your dependencies into a folder inside your package, then rewriting the source of those vendored depdendencies to accomodate.
gb
also recommends vendoring, but with its project based approach, it can give the same result – all dependencies are bundled within the project, without rewriting the source code. This is important, and I believe other Go programmers agree.
gb
is a project based tool. Every subcommand works on a list of import ../faq/paths _packages.css) within that project, and most default to “all packages in the project”.
One of my frustrations with the go tool was its inconsistency in this manner, most go commands work on import ../faq/paths_ except for _code_go run_/code_ which takes a file. Actually that_rsquo.css;s not correct, go run
takes a list of files, but your chances of success of using it drops exponentially the more files you pass to go run
.
While I recognise the utility of go run
for simple examples, and it’s a great way to introduce the language, the fact that it works allowed many new gophers to use it well past the point of its original intent and have a confusing and unsatisfactory time. When they ask for help, they have the double wammy that smug experienced gophers tell them “they are holding it wrong” and should learn to restructure their code.
Because gb
is focused on a project workflow, not a package or file workflow; most of the time you are building or testing your project (see digression in #49 ) I felt I could make things simpler and more consistent by not supporting gb run
at all.
I think the fact that gb
does not just wrap the go tool is one if its distinguishing features.
Technically there is nothing that gb
does that couldn’t be done with a shell script. In fact, several tools have been proposed over the last few years that do just this, with the exception of Keith Rarik’s godep
, all have been completely overlooked by the market.
Why is this? Well probably for one, Go programmers want to use tools written in Go. This seems like a bizarre statement, but it’s true, not just for Go programmers, but pretty much most programming communities.
The second reason is, while you can construct an equivalent line of shell script to mimick what gb
does, generalising that shell script with $PROJECT detection from your working directory and then handling the case where you may be several levels deep inside the $PROJECT is difficult. What could have been a one line shell script now becomes a rather complicated shell script, which adds further weight to programmers not wanting to use a tool not written in their language. Then let’s talk about Windows compatibility …
I think there is also value in convention. I chose vendor/src arbitrarily because that’s what it was called in Rails. Without this convention people would use 3pp, external, etc. Everyone would come up with their own naming convention, and suddenly you’re not talking one shell script, but one shell script per project, along with various configuration flags, etc.
So, what does gb
do? Nothing that you couldn’t do by hand. But people don’t want to do things by hand, hence gb
.
Thanks for the feedback.