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.