Getting started

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.

Creating An Empty Project

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

Converting An Existing Project

This section shows how to construct a gb project using an existing code base.

Simple Example

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:

  • The package alias 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.
  • There is no way to build your vendored source; it will be built if required to build your code in the src/ directory.

A More Complicated Example

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

Wrapping up

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.