Building multiple executables from one module

1,556 views
Skip to first unread message

Brian Candler

unread,
Jun 30, 2020, 6:58:05 AM6/30/20
to golang-nuts
Suppose I have a tree of files like this, to build two executables:

==> ./go.mod <==

go 1.14

==> ./shared.go <==
package example

const Answer = 42

==> ./bin/test1/main1.go <==
package main

import (
"fmt"
)

func main() {
fmt.Printf("%s, answer is %d\n", Message, Answer)
}

==> ./bin/test1/dep1.go <==
package main

const Message = "hello"

==> ./bin/test2/main2.go <==
package main

import (
"fmt"
)

func main() {
fmt.Printf("%s, answer was %d\n", Message, Answer)
}

==> ./bin/test2/dep2.go <==
package main

const Message = "goodbye"

Ideally I'd like a way to build the executables in a single command.  Currently I enter each directory and build explicitly, i.e.

for d in bin/*; do (cd $d && go build); done

If at the top level I do "go build ./...", the executables don't get built.  Something happens, because it takes a fraction of a second to return, but nothing is written out as far as I can see.

The documentation says:

-buildmode=default
	Listed main packages are built into executables and listed
	non-main packages are built into .a files (the default
	behavior).

This implies multiple "main packages" can be built into multiple "executables" in one command.

But how is a main package "listed"?  I tried:

$ go build bin/test1
can't load package: package bin/test1 is not in GOROOT (/usr/local/go/src/bin/test1)
$ go build bin/test1/main
can't load package: package bin/test1/main is not in GOROOT (/usr/local/go/src/bin/test1/main)
$ go build bin/test1/...
go: warning: "bin/test1/..." matched no packages
go: warning: "bin/test1/..." matched no packages
$ go build bin/test1/main1.go
# command-line-arguments
bin/test1/main1.go:9:35: undefined: Message

The following is accepted, but as far as I can see does not create any files:


Just like "go build ./...", it takes a noticeable fraction of a second, but nothing is written out.  I've look in the top level, inside the bin/test[12] directories, and  "find ~/go -mtime -1"

If I build one at a time, it works, yay!

$ ls
bin  go.mod  shared.go test1  test2

... but the documentation says I ought to be able to list multiple main packages, so I'm clearly missing something.

It seems when I build a single package, it gets moved to the final location:

$ go build -x example.com/test/bin/test1
...
/usr/local/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out test1
rm -r $WORK/b001/

but not when I build two:

...
/usr/local/go/pkg/tool/linux_amd64/buildid -w $WORK/b033/exe/a.out # internal
/usr/local/go/pkg/tool/linux_amd64/buildid -w $WORK/b001/exe/a.out # internal

That's as far as I've got.  (Incidentally, I see the same with "go build -x ./...")

Any clues?

Thanks,

Brian.

P.S.
$ go version
go version go1.14.4 linux/amd64

seank...@gmail.com

unread,
Jun 30, 2020, 10:13:34 AM6/30/20
to golang-nuts
go build -o output_directory ./...

Brian Candler

unread,
Jun 30, 2020, 11:38:35 AM6/30/20
to golang-nuts
Thank you!

go build -o . ./...

does the trick.  And now I know what I'm looking for, I can find it in the documentation:

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.


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.


Thanks again,

Brian.
Reply all
Reply to author
Forward
0 new messages