GOPATH, GOBIN, go install, go build, cross-compiles

663 views
Skip to first unread message

Tim Hockin

unread,
Jan 20, 2023, 12:31:07 PM1/20/23
to golang-nuts
I'm trying to make kubernetes' codebase easier to navigate by people who have muscle-memory for go.  In the past we said "you have to call our Makefile" to build things.  I'd like to make \`go install\` work but I'm struggling to find a pattern that really works - am I missing something?

First, GOPATH is dead.  I hate that Go silently writes to my home directory, which is ALMOST NEVER what I really wanted. 

Aside: is there any way to get `go install` and `go build` to tell me what they wrote?  Would that be a reasonable feature request?  E.g. 

```
$ go install --print-result <pkg/path/to/cmd>
/home/thockin/go/bin/cmd
```

I usually set GOPATH=/dev/null.

```
$ GOPATH=/dev/null \
  go install <pkg>
go install <pkg>: mkdir /dev/null: not a directory
```

Good.  I want to install to a repo-local dir so all of our CI and stuff can find it.

```
$ GOPATH=/dev/null \
  GOBIN=./bin \
  go install <pkg>
```

That works.

```
$ GOPATH=/dev/null \
  GOBIN=./bin \
  GOARCH=arm \
  go install <pkg>
go: cannot install cross-compiled binaries when GOBIN is set
```

Well, shoot.  I can't find any other way for `go install` to work.

```
$ GOPATH=/dev/null \
  GOBIN=./bin \
  GOARCH=arm \
  go build <pkg>
```

That works, but splats the file into the current dir.  To be fair, that is documented behavior.

```
$ GOPATH=/dev/null \
  GOARCH=arm \
  go build -o ./bin <pkg>
```

That works, except when ./bin doesn't exist, in which case it becomes the output file (if I am building 1 thing) or I get an error (if I am building multiple things):

```
$ GOPATH=/dev/null \
  GOARCH=arm \
  go build -o ./bin <pkg1> <pkg2>
go: cannot write multiple packages to non-directory ./foo
```

I can specify a directory by adding a trailing `/` it seems:

```
$ GOPATH=/dev/null \
  GOARCH=arm \
  go build -o ./bin/ <pkg1> <pkg2>
```

That seems to work, but I have to get the invocation JUST RIGHT 100% of the time or risk causing weird errors and CI fails.  The obvious answer is "wrap it in a script or Makefile", which puts me right back where I started.

Is there a better answer?

Tim

Sean Liao

unread,
Jan 20, 2023, 1:39:12 PM1/20/23
to golang-nuts
in module mode, 
GOPATH is really only used for deriving default locations for GOBIN and GOMODCACHE
setting it to /dev/null might not be great for caching dependencies if GOMODCACHE isn't set

cross compile to GOBIN was recently (re)opened

There are open requests to print out the directory where it would be installed,
(presumably to update PATH) but not for the actual binaries built.

-o dir/ ending in a slash is documented as:
> If the named output is an existing directory or
> ends with a slash or backslash, then any resulting executables
> will be written to that directory.

- sean


--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/d04fca5a-8b85-4386-9bae-50853f317fccn%40googlegroups.com.

Tim Hockin

unread,
Jan 20, 2023, 2:31:13 PM1/20/23
to Sean Liao, golang-nuts
Thanks Sean.

On Fri, Jan 20, 2023 at 10:39 AM 'Sean Liao' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> in module mode,
> GOPATH is really only used for deriving default locations for GOBIN and GOMODCACHE
> setting it to /dev/null might not be great for caching dependencies if GOMODCACHE isn't set

I think it would bring some closure if we could definitively say
"GOPATH isn't needed".

GOCACHE seems to default to ~/.cache/go-build on my machine.
Shouldn't GOMODCACHE do the same?

> cross compile to GOBIN was recently (re)opened
> https://go.dev/issue/57485

Great - I voted it up, but I don't know if that helps at all. Setting
GOBIN would be a better solution for k8s, if it only worked.

Another thing that we end up writing scripts for is the various sets
of build flags. Like, if you want to build debug binaries there are
something like 4 flags to change. It would be super interesting to
have in-repo or in-module metadata that could be used for these flags.

For example, what if I could add something that said "GOBIN=./bin" or
even more flexible.

> There are open requests to print out the directory where it would be installed,
> (presumably to update PATH) but not for the actual binaries built.
> https://go.dev/issue/45546

Also voted up, but it seems stalled.

> -o dir/ ending in a slash is documented as:
> > If the named output is an existing directory or
> > ends with a slash or backslash, then any resulting executables
> > will be written to that directory.

Sure, it's documented, but one mistake and all subsequent invocations
fail. It works, but it's just fragile.

Tim
> You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Vhd4OZ6vfHc/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAGabyPocd8cx%3Dyg1arT74ULHoLjB4eNrUm17dqAw6KG8SazmPA%40mail.gmail.com.

Sean Liao

unread,
Jan 20, 2023, 5:10:47 PM1/20/23
to Tim Hockin, golang-nuts
> GOCACHE seems to default to ~/.cache/go-build on my machine.
> Shouldn't GOMODCACHE do the same?

That was decided against: 

> ... It would be super interesting to
> have in-repo or in-module metadata that could be used for these flags.

General build configurations have been declined:

There may be appetite for a single set of per-project default config though:

Right now, GOENV=path/to/file for every config could work in combination with GOFLAGS,
now that quoting is allowed after https://go.dev/issue/26849

- sean

Tim Hockin

unread,
Jan 20, 2023, 5:44:50 PM1/20/23
to Sean Liao, golang-nuts
You're a living index! Thanks.

On Fri, Jan 20, 2023 at 2:09 PM Sean Liao <se...@liao.dev> wrote:
>
> > GOCACHE seems to default to ~/.cache/go-build on my machine.
> > Shouldn't GOMODCACHE do the same?
>
> That was decided against:
> https://go.dev/issue/34527#issuecomment-559185776

I'm not sure I buy the rationale, or at least it doesn't (IMO) justify
relying on GOPATH. Still, I can set GOMODCACHE someplace and then set
GOPATH=/dev/null and then I KNOW when I screwed up and go *would have*
splatted files into GOPATH. I'd call that a win. Thanks.

> > ... It would be super interesting to
> > have in-repo or in-module metadata that could be used for these flags.
>
> General build configurations have been declined:
> https://go.dev/issue/39005
> https://go.dev/issue/42343

The first is going where I want, and it's unfortunate it was withdrawn (IMO).

> There may be appetite for a single set of per-project default config though:
> https://go.dev/issue/57179#issuecomment-1345398917

It seems like the per-project part was declined (which would give me a
lot of what I want, indeed).
Reply all
Reply to author
Forward
0 new messages