This document is a guide to introduce people to the gb
project structure. A gb
project is conceptually a $GOPATH
per project, but saying that doesn’t really help explain how to set up a new project; hence this document.
A gb
project is defined as any directory that has a src/
subdirectory. The simplest possible gb
project would be:
% mkdir -p ~/project/src/ % cd ~/project % tree . └── src
~/project
is therefore a gb
project.
Source inside a gb
project follows the same rules as the go tool; see the Workspaces section of the Go getting started document. All Go code is placed inside packages, and packages are subdirectories inside the project’s src/
directory.
Let’s create a helloworld
project:
% cd ~/project % mkdir -p src/cmd/helloworld % tree . └── src └── cmd └── helloworld
Next, add a source code file to the project:
% cat <<EOF > src/cmd/helloworld/helloworld.go package main import "fmt" func main() { fmt.Println("Hello world") } EOF % tree . └── src └── cmd └── helloworld └── helloworld.go
Finally, build the small helloworld
command:
% gb build cmd/helloworld cmd/helloworld % tree . ├── bin │ └── helloworld └── src └── cmd └── helloworld └── helloworld.go
This section shows how to construct a gb
project using an existing code base.
In this example we’ll create a gb
project from the github.com/pkg/sftp
code base.
First, create a project:
% mkdir -p ~/devel/sftp % cd ~/devel/sftp
Next, check out github.com/pkg/sftp
to the path it expects:
% mkdir -p src/github.com/pkg/sftp % git clone https://github.com/pkg/sftp src/github.com/pkg/sftp % tree -d . └── src └── github.com └── pkg └── sftp └── examples ├── buffered-read-benchmark ├── buffered-write-benchmark ├── gsftp ├── streaming-read-benchmark └── streaming-write-benchmark
Now, let’s try to build this:
% gb build all FATAL command "build" failed: failed to resolve package "github.com/pkg/sftp": cannot find package "github.com/kr/fs" in any of: /home/dfc/go/src/github.com/kr/fs (from $GOROOT) /home/dfc/devel/sftp/src/github.com/kr/fs (from $GOPATH) /home/dfc/devel/sftp/vendor/src/github.com/kr/fs
The build failed because the dependency github.com/kr/fs
was not found in the project, which was expected. (Ignore the message about $GOPATH
; this is a side effect of reusing the go/build
package for dependency resolution.)
We must fetch these dependencies and place them in the $PROJECT/vendor/src
directory:
% mkdir -p vendor/src/github.com/kr/fs % tree -d . ├── src │ └── github.com │ └── pkg │ └── sftp │ └── examples │ ├── buffered-read-benchmark │ ├── buffered-write-benchmark │ ├── gsftp │ ├── streaming-read-benchmark │ └── streaming-write-benchmark └── vendor └── src └── github.com └── kr └── fs
% git clone https://github.com/kr/fs vendor/src/github.com/kr/fs Cloning into 'vendor/src/github.com/kr/fs'... remote: Counting objects: 18, done. remote: Total 18 (delta 0), reused 0 (delta 0), pack-reused 18 Unpacking objects: 100% (18/18), done. Checking connectivity... done.
Now, let’s try to build this:
% gb build all FATAL command "build" failed: failed to resolve package "github.com/pkg/sftp": cannot find package "golang.org/x/crypto/ssh" in any of: /home/dfc/go/src/golang.org/x/crypto/ssh (from $GOROOT) /home/dfc/devel/demo/src/golang.org/x/crypto/ssh (from $GOPATH) /home/dfc/devel/demo/vendor/src/golang.org/x/crypto/ssh
We’re nearly there, now just missing the golang.org/x/crypto/ssh
package:
% mkdir -p vendor/src/golang.org/x/crypto< % git clone https://github.com/golang/crypto vendor/src/golang.org/x/crypto % tree -d . ├── src │ └── github.com │ └── pkg │ └── sftp │ └── examples │ ├── buffered-read-benchmark │ ├── buffered-write-benchmark │ ├── gsftp │ ├── streaming-read-benchmark │ └── streaming-write-benchmark └── vendor └── src ├── github.com │ └── kr │ └── fs └── golang.org └── x └── crypto ... % gb build all github.com/kr/fs golang.org/x/crypto/ssh golang.org/x/crypto/ssh/agent github.com/pkg/sftp github.com/pkg/sftp/examples/buffered-read-benchmark github.com/pkg/sftp/examples/buffered-write-benchmark github.com/pkg/sftp/examples/gsftp github.com/pkg/sftp/examples/streaming-read-benchmark github.com/pkg/sftp/examples/streaming-write-benchmark
And now it builds.
Notes:
all
matches all the packages inside your project’s src/
directory. It’s a simple way to build everything. You can use other import paths and globs.src/
directory.For the second example we’ll take a project that uses godep
vendoring and convert it to be a gb
project. First, we’ll need to set up a project and get the source:
% mkdir -p ~/devel/confd % cd ~/devel/confd % mkdir -p src/github.com/kelseyhightower/confd % git clone https://github.com/kelseyhightower/confd src/github.com/kelseyhightower/confd % tree -d . └── src └── github.com └── kelseyhightower └── confd ├── backends │ ├── consul │ ├── dynamodb │ ├── env │ ├── etcd │ ├── redis │ └── zookeeper ├── contrib ├── docs ├── Godeps │ └── _workspace │ └── src │ ... ... ├── log └── resource └── template
We know this project uses godep
, so it already includes all its dependencies. We just need to rearrange things a bit:
% mkdir -p vendor/src/ % mv src/github.com/kelseyhightower/confd/Godeps/_workspace/src/* vendor/src/ % tree -d . ├── src │ └── github.com │ └── kelseyhightower │ └── confd │ ├── backends │ │ ├── consul │ │ ├── dynamodb │ │ ├── env │ │ ├── etcd │ │ ├── redis │ │ └── zookeeper │ ├── contrib │ ├── docs │ ├── Godeps │ │ └── _workspace │ │ └── src │ ├── integration │ │ ├── confdir │ │ │ ├── conf.d │ │ │ └── templates │ │ ├── consul │ │ ├── dynamodb │ │ ├── etcd │ │ ├── redis │ │ └── zookeeper │ ├── log │ └── resource │ └── template └── vendor └── src └── github.com ├── awslabs │ └── aws-sdk-go │ ... ├── BurntSushi │ └── toml │ ... ... └── vaughan0 └── go-ini
Let’s see if it builds:
% gb build all github.com/BurntSushi/toml github.com/hashicorp/consul/api github.com/kelseyhightower/confd/backends/env github.com/coreos/go-etcd/etcd github.com/garyburd/redigo/internal github.com/samuel/go-zookeeper/zk github.com/Sirupsen/logrus github.com/kelseyhightower/memkv github.com/garyburd/redigo/redis github.com/kelseyhightower/confd/log github.com/kelseyhightower/confd/backends/etcd github.com/kelseyhightower/confd/backends/consul github.com/kelseyhightower/confd/backends/redis github.com/kelseyhightower/confd/backends/zookeeper github.com/kelseyhightower/confd/integration/zookeeper github.com/kelseyhightower/confd/backends github.com/kelseyhightower/confd/resource/template github.com/kelseyhightower/confd % bin/confd 2015-05-13T20:32:43+10:00 lucky bin/confd[14849]: INFO Backend set to etcd 2015-05-13T20:32:43+10:00 lucky bin/confd[14849]: INFO Starting confd 2015-05-13T20:32:43+10:00 lucky bin/confd[14849]: INFO Backend nodes set to http://127.0.0.1:4001 2015-05-13T20:32:43+10:00 lucky bin/confd[14849]: FATAL cannot connect to etcd cluster: http://127.0.0.1:4001
Setting up or converting code to a gb
project is simple. Once you’ve done this, you should check your $PROJECT
directory into a source control repository. This includes any source you have copied from other projects into your $PROJECT/vendor/src/
directory.