Go: cmd/go: With Go 1.4, cannot statically link a program which imports net

Created on 16 Dec 2014  Â·  26Comments  Â·  Source: golang/go

In Go 1.3.x, it was possible to statically link a program which imports the net package. This is important when building programs for cut-down environments, for example busybox.

The problem can be reproduced on Ubuntu as reported by Vasiliy Tolstov:

package main 
import "net" 
func main() { 
        _, _ = net.ResolveIPAddr("ip", "google.com") 
} 

It is possible to statically link this program in Go 1.3.x by issuing:

CGO_ENABLED=0 go build -a -x

but with Go 1.4, the same technique creates the following runtime dependencies:

linux-vdso.so.1 (0x00007fff603fe000) 
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3bd0608000) 
libc.so.6 => /lib64/libc.so.6 (0x00007f3bd0260000) 
/lib64/ld-linux-x86-64.so.2 (0x00007f3bd0825000) 
FrozenDueToAge

Most helpful comment

CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go

Go 1.5.1

LGTM

All 26 comments

Working as intended.

In released version of go, go build/install -a std will not try to
reinstall the standard packages to avoid the common problem of permission
error when go is installed to a system directory.

So is the above static linking behaviour therefore a bug in go 1.3.x?

@minux, just to make it clear, do I understand correctly that using CGO_ENABLED=0 go build -a -x (in older versions of Go) actually rebuilt and reinstalled certain parts of stdlib instead of just affecting the program being built?

To clarify, go install/build -a std won't do anything for standard packages
in a released version of Go.
See commit 8c3005c4929e26cba74c80703123e150fa3fda1a for details.

@minux: when you say "a released version of Go" are you referring to 1.3.x as well as 1.4??

This change in behavior only applies to 1.4.

I see, thanks. Programs which import the net package and need to be statically linked cannot migrate to 1.4. Is there some reason, in principle, why such static linking cannot be supported in 1.4.x or does commit 8c3005c preclude such a solution?

@glyn, if I understood correctly (@minux did not address my question directly), before 1.3, when you performed the encantation being discussed, a part of the Go's stdlib has been silently rebuilt and replaced -- most of folks did not notice it because most have Go built from the source and installed somewhere under ~. Since this behaviour clearly fails with system-wide Go installs (some people do use apt-get install golang), the -a command-line option stopped affecting the Go's own files in 1.4.

The solution is just to build and install another instalce of the Go toolchain and use it via custom $GOROOT where applicable.

IOW, building fully static programs on Linux did not ever do The Right Thing. I think it might be sensible to file a wishlist bug asking to somehow make stdlib support both behaviours out of the box. Dunno if it's feasible to implement.

@glyn, I mean a custom build of the Go toolchain done with CGO_ENABLED=0 (and maybe -tags netgo, if applicable).

No no no. You don't need to set GOROOT, ever. Please see my blog
http://dave.cheney.net/2014/04/20/how-to-install-multiple-versions-of-go

On Thu, Dec 18, 2014 at 6:57 AM, Konstantin Khomoutov <
[email protected]> wrote:

@glyn https://github.com/glyn, if I understood correctly (@minux
https://github.com/minux did not address my question directly), before
1.3, when you performed the encantation being discussed, a part of the Go's
stdlib has been silently rebuilt and replaced -- most of folks did not
notice it because most have Go built from the source and installed
somewhere under ~. Since this behaviour clearly fails with system-wide Go
installs (some people do use apt-get install golang), the -a command-line
option stopped affecting the Go's own files in 1.4.

The solution is just to build and install another instalce of the Go
toolchain and use it via custom $GOROOT where applicable.

IOW, building fully static programs on Linux did not ever do The Right
Thing. I think it might be sensible to file a wishlist bug asking to
somehow make stdlib support both behaviours out of the box. Dunno if it's
feasible to implement.

—
Reply to this email directly or view it on GitHub
https://github.com/golang/go/issues/9344#issuecomment-67383137.

2014-12-17 22:57 GMT+03:00 Konstantin Khomoutov [email protected]:

@glyn, if I understood correctly (@minux did not address my question directly), before 1.3, when you performed the encantation being discussed, a part of the Go's stdlib has been silently rebuilt and replaced -- most of folks did not notice it because most have Go built from the source and installed somewhere under ~. Since this behaviour clearly fails with system-wide Go installs (some people do use apt-get install golang), the -a command-line option stopped affecting the Go's own files in 1.4.

This is not true. I'm use go from package system (that install it in
system-wide /usr/lib/go) and -a works fine under user rebuild all
inside /tmp and doing static linking after all deps recompiled.

Vasiliy Tolstov,
e-mail: v.[email protected]
jabber: [email protected]

@vtolstov I'm not sure how that can be. If you read the source code at https://github.com/golang/go/commit/8c3005c4929e26cba74c80703123e150fa3fda1a you can see it expllicitly doesn't recompile std packages for a released version of Go.

What version are you running your test on?

@iand i say for go 1.3 not for 1.4.
I'm not understand why breaks static linking from 1.3 to 1.4. If you don't do go install -a all works fine and nothing rewrited....

@vtolstov the behaviour of go install -a was changed in 1.4 so it doesn't recompile the std library if you are using a release version of Go.

This issue looks like an unfortunate side effect of that change. There seems to be no way to recompile the standard library in a release version of Go without recompiling all of Go from source. While that's not onerous for those who regularly use the source version it will cause problems for those who want or need to use pre-packaged versions.

This discussion from golang-dev is relevant: https://groups.google.com/d/msg/golang-dev/2ZUi792oztM/Q0rg_DkF5HMJ

One solution might be to skip building the std library except when the -tags argument is used and any of the specified tags are used by the std library.

See #9369.

Thanks @mikioh, although I'm not sure why it was necessary for #9369 to be raised since it's a duplicate of this bug.

@glyn Ah, you do not understand: this issue is a _bug report_, but #9369 is a _feature request_. By definition, there are no bugs in the Go lang implementations: every behaviour is intentional.

I simply didn't notice this issue when I opened 9369. I'll leave them both open for now since there are useful comments on both.

Fair enough.

Work around: use -installsuffix.

CGO_ENABLED=0 go build -a -installsuffix cgo

Edited to add: while this workaround was useful for old versions of Go, it is completely unnecessary for Go 1.10 and later. If you have been using it, you can stop.

I don't think we are going to do anything--using -installsuffix fixes the problem.

Hi.

It should be well documented, thanks for the effort.

I'm really puzzled about this. The primary reason I built my app was for static linking which I thought was the default behaviour and now I find that forever more I'll need to use what seems like a kludge to compile:

CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go

I'm using Go 1.5.1

If you want static compilation always then I recommend installing Go from
source

env CGO_ENABLED=0 ./all.bash

That will disable cgo permanently.

On Tue, Oct 20, 2015 at 4:55 PM, dukedougal [email protected]
wrote:

I'm really puzzled about this. The primary reason I built my app was for
static linking which I thought was the default behaviour and now I find
that forever more I'll need to use what seems like a kludge to compile:

CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s'
src/myapp/myapp.go

I'm using Go 1.5.1

—
Reply to this email directly or view it on GitHub
https://github.com/golang/go/issues/9344#issuecomment-149441532.

CGO_ENABLED=0 go build -a -installsuffix cgo -ldflags '-s' src/myapp/myapp.go

Go 1.5.1

LGTM

Was this page helpful?
0 / 5 - 0 ratings

Related issues

go101 picture go101  Â·  3Comments

enoodle picture enoodle  Â·  3Comments

ashb picture ashb  Â·  3Comments

longzhizhi picture longzhizhi  Â·  3Comments

natefinch picture natefinch  Â·  3Comments