7
votes

I've seen this discussed in various places, with answers like 'use a cmd/foo, cmd/bar' type folder structure.

This does not work for me.

This works:

$ du -a
8   ./src/cmd/bin1/main.go
8   ./src/cmd/bin1
8   ./src/cmd/bin2/main.go
8   ./src/cmd/bin2
16  ./src/cmd
8   ./src/shared/foo/foo.go
8   ./src/shared/foo
8   ./src/shared
24  ./src

and building it:

go build ./src/cmd/bin2
go build ./src/cmd/bin1

However, I can't figure out what variation on:

go build ./src/...

I might need to build all such binaries in one step.

This layout:

$ du -a
8   ./cmd/bin1/main.go
8   ./cmd/bin1
8   ./cmd/bin2/main.go
8   ./cmd/bin2
16  ./cmd
8   ./src/shared/foo/foo.go
8   ./src/shared/foo
8   ./src/shared
8   ./src
24  .

Seems totally unusable. No combination of go build ... commands seems to build bin1 or bin2.

The best I can get is go build cmd/bin1/main.go which gives me a binary called 'main'. Not helpful.

So, specifically and in detail, including the go build command, that actually builds the individual binaries, how do you do this?

...and why is the default advice that people keep giving to use a top level cmd folder? How do you build these binaries if you do?

4
check out https://github.com/spf13/cobra you will point it at cmd/main.go and other command source files will be used as e.g. main doX main printYPlato
You can add subcommands with cobra, but it does not produce multiple binaries as intended.T. Claverie

4 Answers

15
votes

If you don't want to install the binaries into $GOPATH/bin, you could do what other open source projects do, which is create a script.

Most of the projects out there have make files and build scripts for producing multiple binaries.

In your case, you could build a script that iterates over the packages in cmd, and run go build on each.

cd $GOPATH/someProject
for CMD in `ls cmd`; do
  go build ./cmd/$CMD
done

This results in:

[root@node1 test]# ls $GOPATH/someProject
bin1  bin2  cmd

Couple of trending projects that you can look at:

9
votes

The command:

go install ./...

should build all binaries under your current directory (i.e. ./...) and put them on $GOPATH/bin.

9
votes

From the go build help:

When compiling multiple packages or a single non-main package, build compiles the packages but discards the resulting object, serving only as a check that the packages can be built.

In order to build all packages under a directory, you can run go install ./.... All of your packages will be built and installed (i.e. put under $GOPATH/bin).

With your example, you'd have two executables produced: $GOPATH/bin/bin1 and $GOPATH/bin/bin2

There is also the alternative of writing a simple Makefile to do what you want.

5
votes

You can use -o flag of go build. From official documentation:

The -o flag forces build to write the resulting executable or object to the named output file or directory, instead of the default behavior described in the last two paragraphs. If the named output is a directory that exists, then any resulting executables will be written to that directory.

So you can try something like:

go build  -o . ./...

This essentially making Go to write resulting executables in current folder (the . value of -o) for all packages in the current module/folder/project.