Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/go: can't build a static binary since Go 1.15 #40711

Closed
AkihiroSuda opened this issue Aug 12, 2020 · 5 comments
Closed

cmd/go: can't build a static binary since Go 1.15 #40711

AkihiroSuda opened this issue Aug 12, 2020 · 5 comments
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@AkihiroSuda
Copy link
Contributor

What version of Go are you using (go version)?

$ go version
go version go1.15 linux/amd64

Does this issue reproduce with the latest release?

Yes (Go 1.15)

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="off"
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build855769531=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Can't build a static binary since Go 1.15.

Dockerfile:

ARG GO_VERSION=1.14
ARG CONTAINERD_VERSION=v1.4.0-rc.1

FROM golang:${GO_VERSION}-alpine
RUN apk add -q --no-cache build-base file git 
RUN git clone https://github.com/containerd/containerd.git /go/src/github.com/containerd/containerd
WORKDIR /go/src/github.com/containerd/containerd
ARG CONTAINERD_VERSION
RUN git checkout ${CONTAINERD_VERSION}
ENV GO111MODULE=off
ENV CGO_ENABLED=0
RUN go build \
      -o /ctr \
      -buildmode pie \
      -ldflags '-extldflags "-fno-PIC -static"' \
      -tags "netgo osusergo static_build no_devmapper no_btrfs no_aufs no_zfs" \
      github.com/containerd/containerd/cmd/ctr
CMD ["file", "/ctr"]

✅ Go 1.14.7 produces a static binary as expected

$ docker build --build-arg GO_VERSION=1.14.7 -t foo . && docker run --rm foo 
/ctr: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, Go BuildID=Bg43Nf6C1WHrELPD6ZtJ/eeTRjAjO6AJn5NcyocKS/Poc-qUhs8xS_8EfPqFXC/ew3uJjFlP6ccdnV6pOgw, not stripped

❌ Go 1.15 produces a dynamic binary

$ docker build --build-arg GO_VERSION=1.15 -t foo . && docker run --rm foo
/ctr: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, Go BuildID=sziYlJYx90CbegTtvmWk/5_xOsu-1dsLyeXMPO6wY/IRGuYqM_1FFdSR4cvtH4/8SCwinUDPBgQ8N3LZWmm, not stripped

What did you expect to see?

Go 1.15 should produce a static binary

What did you see instead?

Go 1.15 produced a dynamic binary

@ALTree
Copy link
Member

ALTree commented Aug 12, 2020

From the Go 1.15 release notes:

The linker now defaults to internal linking mode for -buildmode=pie on linux/amd64

So your -buildmode=pie flag is forcing internal linking. If you change this part:

-ldflags '-extldflags "-fno-PIC -static"'

to force external linking, like this:

-ldflags '-linkmode external -extldflags "-fno-PIC -static"'

it should produce a static binary. Does this work?

@ALTree ALTree changed the title Can't build a static binary since Go 1.15 cmd/go: can't build a static binary since Go 1.15 Aug 12, 2020
@ALTree ALTree added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Aug 12, 2020
@AkihiroSuda
Copy link
Contributor Author

Yes, thanks, any chance to have this explained in the release note?

AkihiroSuda added a commit to AkihiroSuda/containerd that referenced this issue Aug 12, 2020
* `-linkmode external` is required since Go 1.15 for static builds: golang/go#40711
* Clarify the meaning of "loading plugins"

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
@ALTree
Copy link
Member

ALTree commented Aug 12, 2020

Thank you for confirming. I've opened #40719 to track a possible release notes addition.

thaJeztah pushed a commit to thaJeztah/containerd that referenced this issue Sep 11, 2020
* `-linkmode external` is required since Go 1.15 for static builds: golang/go#40711
* Clarify the meaning of "loading plugins"

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
(cherry picked from commit 43cbdf8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
tussennet pushed a commit to tussennet/containerd that referenced this issue Sep 11, 2020
* `-linkmode external` is required since Go 1.15 for static builds: golang/go#40711
* Clarify the meaning of "loading plugins"

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
@danield20
Copy link

danield20 commented Dec 23, 2020

-ldflags '-linkmode external -extldflags "-fno-PIC -static"'

Hi, I am trying to obtain a simple helloworld elf from go code that is both statically linked and is position independent. Untill now I managed to get one or the other but not both.

If I use something like this:
go build -buildmode=pie -ldflags '-linkmode external -extldflags "-static"'
it is statically linked but not PIE.

If I use something like this:
go build -buildmode=pie -ldflags '-extldflags "-static"'
it is PIE but it is not statically linked.

What is the correct way to do this? I am using version 1.15.6 linux/amd64

Update:
go build -buildmode=pie -ldflags '-linkmode external -extldflags "-static-pie"' does the trick but is there another way to achieve this with cgo disabled? If I disable cgo and run this command I get loadinternal: cannot find runtime/cgo

@ianlancetaylor
Copy link
Contributor

@danield20 We prefer to keep our issues focused on a single problem. Please don't raise different problems on an existing issue.

We also don't use our issue tracker for questions. Please see https://golang.org/wiki/Questions. Thanks.

pingleig added a commit to pingleig/amazon-cloudwatch-agent that referenced this issue May 3, 2021
When PIE mode is enabled, CGO_ENABLED=0 does not give a static link
binary, extra ld flags are required golang/go#40711
haojhcwa added a commit to haojhcwa/amazon-cloudwatch-agent-1 that referenced this issue May 18, 2021
Go compiler has switched to internal linking mode when building in PIE
mode since version 1.15 (https://golang.org/doc/go1.15#linker). This had
a side effect of not able to compile a purely statically linked PIE
binary with CGO disabled, see: golang/go#40711

As a result, the agent binaries build with PIE mode will fail to run in
a container that is built from SCRATCH. In this CR we allow the users to
override the build mode with environment variable `CWAGENT_BUILD_MODE`,
allowing a non-PIE binary to be built to be used in a container without
libc.
For example, a non-pie agent can be built with:
```
CWAGENT_BUILD_MODE=default make
```
pingleig pushed a commit to aws/amazon-cloudwatch-agent that referenced this issue May 19, 2021
Go compiler has switched to internal linking mode when building in PIE
mode since version 1.15 (https://golang.org/doc/go1.15#linker). This had
a side effect of not able to compile a purely statically linked PIE
binary with CGO disabled, see: golang/go#40711

As a result, the agent binaries build with PIE mode will fail to run in
a container that is built from SCRATCH. In this CR we allow the users to
override the build mode with environment variable `CWAGENT_BUILD_MODE`,
allowing a non-PIE binary to be built to be used in a container without
libc.
For example, a non-pie agent can be built with:
```
CWAGENT_BUILD_MODE=default make
```
@golang golang locked and limited conversation to collaborators Dec 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

5 participants