multiple binaries from a single directory with go modules?

691 views
Skip to first unread message

Tycho Andersen

unread,
Jan 17, 2019, 8:41:24 PM1/17/19
to golan...@googlegroups.com
Hi everyone,

I'm trying to get an existing project which outputs multiple binaries
to work with go modules. The package follows roughly the recommended
layout: https://github.com/golang-standards/project-layout

That is, it looks like

/go.mod
/go.sum
/code.go
/cmd/foo/main.go
/cmd/bar/main.go

I have a top level make file that looks roughly like:

all: foo bar

foo: ...
go build -o foo ./cmd/foo/...

bar: ...
go build -o bar ./cmd/bar/...

When I type "make", it seems like go.sum and go.mod end up with only
bar's dependencies, because the last go invocation prunes the "unused"
dependencies from the module files. I've tried various ways of using
mutiple go.mod and go.sum files (one in each binary directory), but I
can't quite get the includes of the top level package right.

I see https://github.com/golang/go/issues/14295, which will solve this
problem for me, but it doesn't exist yet.

Is there some clever way of structuring a project like this with go
modules that I haven't figured out yet?

Thanks,

Tycho

Space A.

unread,
Jan 18, 2019, 7:53:40 PM1/18/19
to golang-nuts
Yes/ Don't use make and makefiles.

Tyler Compton

unread,
Jan 18, 2019, 8:12:13 PM1/18/19
to Space A., golang-nuts
What alternative do you recommend?

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sam Whited

unread,
Jan 18, 2019, 8:28:44 PM1/18/19
to 'Than McIntosh' via golang-nuts
On Sat, Jan 19, 2019, at 01:12, Tyler Compton wrote:
> What alternative do you recommend?

Use what you're comfortable with. Make is a great tool, and doesn't appear to be the problem here.

—Sam

Ian Denhardt

unread,
Jan 18, 2019, 9:57:43 PM1/18/19
to Tycho Andersen, golan...@googlegroups.com
You could just do:

go build ./cmd/...
cp ./cmd/foo/foo ./
cp ./cmd/bar/bar ./

..and wrap it up in a script.

Quoting Tycho Andersen (2019-01-17 17:47:35)

Paul Jolly

unread,
Jan 19, 2019, 5:12:12 AM1/19/19
to Tycho Andersen, golang-nuts
Perhaps the most idiomatic way of achieving this is:

GOBIN=$PWD go install ./cmd/{foo,bar}

go install is also more efficient than go build because it will only
perform the link step if the target is out of date.

I'm no expert with make, so I don't know how this sort of approach
maps back onto make.

Returning however to the problem you're seeing with your existing
setup, a change in Go 1.12 should prevent the race condition you're
seeing:

https://go-review.googlesource.com/c/go/+/146380

Tycho Andersen

unread,
Jan 19, 2019, 10:37:13 PM1/19/19
to Ian Denhardt, golan...@googlegroups.com
On Fri, Jan 18, 2019 at 09:54:51PM -0500, Ian Denhardt wrote:
> You could just do:
>
> go build ./cmd/...
> cp ./cmd/foo/foo ./
> cp ./cmd/bar/bar ./
>
> ..and wrap it up in a script.

go build doesn't seem to produce binaries, though? In any case, Paul's
suggestion in a sibling mail works well enough, thanks!

Tycho

Tycho Andersen

unread,
Jan 20, 2019, 2:21:05 PM1/20/19
to Jinwoo Lee, Ian Denhardt, golan...@googlegroups.com
On Sun, Jan 20, 2019 at 11:18:38AM -0800, Jinwoo Lee wrote:
> It looks like "go build ./cmd/..." works when there's only one directory
> under cmd. When there are multiple directories there, the command doesn't
> generate any binaries for me.
>
> I would just do
>
> $ go build ./cmd/foo
> $ go build ./cmd/bar
>
> They create binaries in the current directory so you don't even have to
> copy them.

That's how I have it now. The problem with this is that in the face of
modules, it re-writes the go.mod and go.sum files to not include the
deps of the binary it's not currently building, so you end up with a
bunch of unnecessary churn there. So it really does need to be in one
go command.

Tycho

Jinwoo Lee

unread,
Jan 20, 2019, 2:22:21 PM1/20/19
to Tycho Andersen, Ian Denhardt, golan...@googlegroups.com
It looks like "go build ./cmd/..." works when there's only one directory under cmd. When there are multiple directories there, the command doesn't generate any binaries for me.

I would just do

$ go build ./cmd/foo
$ go build ./cmd/bar

They create binaries in the current directory so you don't even have to copy them.


Jan Mercl

unread,
Jan 20, 2019, 2:33:18 PM1/20/19
to Jinwoo Lee, Tycho Andersen, Ian Denhardt, golan...@googlegroups.com



On Sun, Jan 20, 2019 at 8:22 PM Jinwoo Lee <jinw...@gmail.com> wrote:

> It looks like "go build ./cmd/..." works when there's only one directory under cmd. When there are multiple directories there, the command doesn't generate any binaries for me.

It works on all sub directories. But `go build` puts the binary locally, while `go install cmd/...` should put all the binaries on $GOBIN or $GOPATH/bin if $GOBIN is not set.


--

-j

Jinwoo Lee

unread,
Jan 20, 2019, 2:37:06 PM1/20/19
to Jan Mercl, Tycho Andersen, Ian Denhardt, golan...@googlegroups.com
Did you try? That's not the behavior I'm seeing. When there's multiple directories under cmd, 'go build ./cmd/...' doesn't create any binaries -- either in the current directory or in ./cmd/{foo,bar}. It does seem to do something and emits build errors if any, but no binaries. It does work when there's only one directory, e.g. ./cmd/foo.
 


--

-j

Jinwoo Lee

unread,
Jan 20, 2019, 2:38:37 PM1/20/19
to Tycho Andersen, Ian Denhardt, golan...@googlegroups.com
Sounds annoying. This seems like a good improvement to be made in the toolchain.
 

Tycho

Jakob Borg

unread,
Jan 21, 2019, 1:42:14 AM1/21/19
to Tycho Andersen, golang-nuts
On 20 Jan 2019, at 20:20, Tycho Andersen <ty...@tycho.ws> wrote:

That's how I have it now. The problem with this is that in the face of
modules, it re-writes the go.mod and go.sum files to not include the
deps of the binary it's not currently building, so you end up with a
bunch of unnecessary churn there. So it really does need to be in one
go command.

This is the central problem of yours, but it isn’t how the toolchain works for me and I don’t think it’s how it’s intended to work. Clearly you should be able to build individual packages inside a module without losing dependency information.

Are you sure you don’t have a step in your makefile that removes the go.mod? Can you share a complete module that exhibits this behavior for you?

//jb
Reply all
Reply to author
Forward
0 new messages