7
votes

We are compiling our Go code to be run on docker and we were investigating why our binary was not executing. We found that it was missing some dynamic libraries (although we want statically linked binaries).

This is how it was compiled.

env GOOS=linux CGO_ENABLED=1 GO111MODULE=on GOPRIVATE=github.com/ourrepo GOPROXY=https://proxy.golang.org go build --installsuffix cgo --ldflags='-extldflags=-static' -o program main.go

Using the same build command with CGO_ENABLED=0 ended up fixing the issue, and the output binary was statically linked.

Now the weird part is we have another program that is using the same build command, this time with CGO_ENABLED=1 and... it is statically linked!

So I'm very confused why in some cases CGO_ENABLED=1 produces dynamic linking, and sometimes static linking. Happy to provide more details.

1
The binary is only dynamically linked if it needs to be. If you're not using cgo, then CGO_ENABLED=1 makes no difference.JimB
I'm not sure what the question is here. If the binary from CGO_ENABLED=0 is what you want, what are you trying to accomplish with the original go build command? (that original command looks like a combination of random things just pasted together)JimB
@JimB I'm trying to understand why in one case (cgo_enabled=1) the binary is dynamically linked and in the other it is not. to your question "is CGO_ENABLED=0 what we want?" not really. We want static. CGO_ENABLED=0 only magically makes this happen and I don't get why. Does it make more sense? Do you suggest to remove --installsuffix cgo and GO111MODULE and CGO altogether?Thomas
Because one is using cgo and one is not. The command itself doesn't make sense, you're passing -static to an external linker that you're not calling (there's no -linkmode external), you don't seem to be cross-compiling, but you have GOOS defined, though no GOARCH; and you have GO111MODULE=on but you're not building a package. It looks like you added a bunch of options without knowing what they do, and it's causing confusion.JimB
CGO_ENABLED=0 doesn't "magically" make it happen, it prevents the use of cgo, which will result in a static binary, which sounds like what you want.JimB

1 Answers

5
votes

Some Go packages use CGO under the hood, leveraging (very) common C libraries for broader compatibility across environments and edge cases encountered at runtime.

These common libraries are found on most major OS distributions - but obviously are not included in the Scratch image (which is by nature completely empty).

CGO_ENABLED is set to 1 by default, which means that it must be explicitly disabled with CGO_ENABLED=0 to avoid it, even when using the -static flag.