Frequently asked questions

  • Does gb use the GOVENDOREXPERIMENT flag?
  • My Go installation is missing -race support
  • How can I track a vendor package's git version?
  • Why can't I place source in $PROJECT/src?
  • gb conflicts with zsh's git branch alias
  • Can I use gb if I am working on a Go library?
  • Copying code is gross! Can I use git submodules?
  • Why didn’t you contribute back to the go tool?
  • Why isn't there a gb run command?
  • Why not wrap the go tool?
  • Your project is crap! Why would you do this?
  • Does gb use the GOVENDOREXPERIMENT flag?

    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.

    My Go installation is missing -race support

    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

    Packaged versions of Go

    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.

    Source compiled Go

    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

    How can I track a vendor package's git version?

    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.

    Read more about gb-vendor.

    Why can't I place source in $PROJECT/src?

    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 path is blank, as its directory name is the same as the project’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 paths, a package with a blank import path—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/.

    gb conflicts with zsh's git branch alias

    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 gb
    See also issue #4

    Can I use gb if I am working on a Go library?

    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.

    See issue 70.

    Copying code is gross! Can I use git submodules?

    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.

    Why didn’t you contribute back to the go tool?

    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 dependencies to accommodate.

    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.

    Why isn't there a gb run command?

    gb is a project based tool. Every subcommand works on a list of import paths (packages) 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 paths, except for go run which takes a file. Actually that’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.

    See also issue 51.

    Why not wrap the go tool?

    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.

    Your project is crap! Why would you do this?

    Thanks for the feedback.