Go: cmd/go: 'go test' on alpine and ubuntu requires gcc in GOPATH mode

Created on 7 Oct 2018  ยท  30Comments  ยท  Source: golang/go

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

golang:1.11.1-alpine3.8:

go version go1.11.1 linux/amd64

Does this issue reproduce with the latest release?

Yes.

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

Also from that docker image:

GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
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 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build610617865=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Run go test on a simple package that imports some network packages like net/http. Expect it to work, even when I don't have gcc installed, which is the case with the Alpine Go images. This worked on 1.10. It broke when we switched to the 1.11 images.

Here is a simple reproducer script:

docker run -i golang:1.11.1-alpine3.8 sh <<-SCRIPT
        mkdir -p src/foo.com/bar
        cd src/foo.com/bar

        cat <<EOF >main.go
        package main

        import _ "net/http"

        func main() {}
        EOF

        go test
SCRIPT

What did you expect to see?

What I see if I use golang:1.11.1-stretch:

$ ./repro.sh
?       foo.com/bar     [no test files]

Note that this has nothing to do with the package not having test files or tests. We encountered this on a package that has plenty of tests.

What did you see instead?

$ ./repro.sh
# runtime/cgo
exec: "gcc": executable file not found in $PATH

Also note that we are not in module-aware mode, so this issue should be different from #26988. I believe this is the same issue that @mfridman and @tylercloke were reporting in that thread.

For the time being, we've just globally set CGO_ENABLED=0 on all of our CI jobs, since we don't use CGO on our production builds anyway. And one could argue that we should have been doing that from the start anyway. Nonetheless, this still seems like a bug or some sort of regression to me.

/cc @bcmills @thepudds @myitcv

GoCommand NeedsInvestigation

Most helpful comment

Hey guys, I think that you can include this short command in yours Dockerfile

ENV CGO_ENABLED=0

All 30 comments

Forgot to mention - the stretch image does have gcc, while the alpine image does not.

This might be better classified as "the official golang:alpine images should install a supported libc" .

From https://github.com/golang/go/issues/27264#issuecomment-416288805

The official Go binaries are known to not work on Alpine because we assume glibc. That is #18773 and #19938.

Are you saying that the Go binary from go get golang.org/dl/go1.10.3 but not from go get golang.org/dl/go1.11? Or did you get your go1.10.3 from somewhere else? (e.g. from Alpine apk)

I don't think this is related. I'm not having any issues with Alpine's musl libc, and Go does otherwise work.

If the official Go docker image based on Alpine required installing glibc, what would be the point of distributing that image to begin with?

Also, I don't think we make any statement as to requiring glibc for Go to work if properly built. That comment is about the Go binary distribution.

Looks like a dupe of #27639

I think this issue should stay open to describe the go test issue as opposed to the go build issue. See https://github.com/golang/go/issues/26988#issuecomment-427573086.

I'm also seeing this behaviour when running go test on Windows (no gcc)

There have been a bunch of related issues, some being fixed and some being closed as duplicates. Note however, that many of them including #26988 require running the Go command in module-aware mode, while this one doesn't.

It does look like #27639 is a very similar issue, but that was closed and didn't have much activity, so I think we should keep this one open for now.

There's something about the Alpine image that makes the go command think rebuilding is necessary. Does pkg/linux_amd64/runtime/cgo.a even exist in the image?

If the Alpine image were built with CGO_ENABLED=0 then I could see that doing a CGO_ENABLED=1 build would do a rebuild. But I don't see that in the Dockerfile.
https://github.com/docker-library/golang/blob/ed78459fac108dab72556146b759516cc65ee109/1.11/alpine3.8/Dockerfile

pkg/linux_amd64/runtime/cgo.a exists yes.

Dump of runtime and http files in the docker image:

# tree pkg/linux_amd64/runtime* pkg/linux_amd64/net/http* pkg/linux_amd64/vendor/golang_org/x/net/http*
pkg/linux_amd64/runtime
โ”œโ”€โ”€ cgo.a
โ”œโ”€โ”€ debug.a
โ”œโ”€โ”€ internal
โ”‚ย ย  โ”œโ”€โ”€ atomic.a
โ”‚ย ย  โ””โ”€โ”€ sys.a
โ”œโ”€โ”€ pprof
โ”‚ย ย  โ””โ”€โ”€ internal
โ”‚ย ย      โ””โ”€โ”€ profile.a
โ”œโ”€โ”€ pprof.a
โ”œโ”€โ”€ race.a
โ””โ”€โ”€ trace.a
pkg/linux_amd64/runtime.a [error opening dir]
pkg/linux_amd64/net/http
โ”œโ”€โ”€ cgi.a
โ”œโ”€โ”€ cookiejar.a
โ”œโ”€โ”€ fcgi.a
โ”œโ”€โ”€ httptest.a
โ”œโ”€โ”€ httptrace.a
โ”œโ”€โ”€ httputil.a
โ”œโ”€โ”€ internal.a
โ””โ”€โ”€ pprof.a
pkg/linux_amd64/net/http.a [error opening dir]
pkg/linux_amd64/vendor/golang_org/x/net/http
โ”œโ”€โ”€ httpguts.a
โ””โ”€โ”€ httpproxy.a
pkg/linux_amd64/vendor/golang_org/x/net/http2
โ””โ”€โ”€ hpack.a

3 directories, 19 files

Maybe this is unrelated to the Alpine image, as I experience the same issue with go 1.11.1 on Ubuntu 18.04.1 LTS, using vanilla go downloaded from https://dl.google.com/go/go1.11.1.linux-amd64.tar.gz.

I am on Ubuntu 18.04 and encountered the same error :
_runtime/cgo
exec: "gcc": executable file not found in $PATH_
when I run "go test".

Solution: sudo apt install gcc

Hi @mvdan (and/or anyone else on this issue)

Good chance you already saw this, but it seems #26988 is now hopefully fixed in tip (where this issue #28065 was originally spun out from #26988).

I haven't personally seen anything that explicitly suggests that this issue #28065 might also be addressed, but it could be worth a quick try off of tip to see the situation here has improved.

Thanks - I'll build tip on Alpine, and see if this bug is still present.

Still appears to happen. New script:

docker run -i golang:1.11.2-alpine3.8 sh <<SCRIPT

cd /
apk add --no-cache --virtual .build-deps bash gcc musl-dev openssl git
go version
export GOROOT_BOOTSTRAP="$(go env GOROOT)"
git clone --depth=1 https://go.googlesource.com/go tip
cd tip/src
./make.bash
apk del .build-deps
/tip/bin/go version

cd /go
mkdir -p src/foo.com/bar
cd src/foo.com/bar

cat <<EOF >main.go
package main

import _ "net/http"

func main() {}
EOF

/tip/bin/go test

SCRIPT

Output:

[...]
go version devel +ba2e8f6 Thu Nov 29 18:18:51 2018 +0000 linux/amd64
# runtime/cgo
exec: "gcc": executable file not found in $PATH

Hey guys, I think that you can include this short command in yours Dockerfile

ENV CGO_ENABLED=0

@MatheusViniciusAndrade please read the previous comments - CGO_ENABLED is already mentioned multiple times.

I have been experiencing this issue in attempting to upgrade from Go 1.10 with my application build (not using Go modules), which runs in Alpine docker. As others are experiencing, go test fails with the dreaded:

# runtime/cgo
exec: "gcc": executable file not found in $PATH

Looking through the changes for Go 1.11 (where this issue originally surfaces), I found that one of those changes is that when vetting test packages, they are 'rebuilt as needed': https://github.com/golang/go/commit/804d03281c04096fca7f73dc33d1d62e09a86892#diff-acaf53a9cd478507ebbcf85037940b4d

Disabling vet during go test proved to avoid the issue for my case, i.e. go test -v -vet=off ./...

As part of our Go builds, we already run vet along with other static checks, and we also run tests with the race detector enabled in a 'stretch' image (which will still have vet enabled), so I don't think we've lost any checks by doing this.

Is this still being worked on?
Most related issues have been closed as of now.

@JAicewizard, this issue is not assigned to anyone and is milestoned to Unplanned. If someone wants to investigate and send a fix that'd be great, but at the moment the impact seems small enough that other issues are higher priority.

@dackroyd thank you very much, it works like a charm!

I was looking into this briefly and came across the build log and script for the Go package for alpine linux:

Build log: https://build.alpinelinux.org/buildlogs/build-edge-x86/community/go/go-1.13.3-r0.log
Build script: https://git.alpinelinux.org/aports/tree/community/go/APKBUILD

It seems to me this goes through a lot of steps that are likely to break the build cache. It ignores a lot of so-called "broken tests" related to runtime and cgo. The build log has a lot of errors related to not being able to find runtime/cgo. A lot of compiled pkg objects are deleted at the end of the build.

It's not clear to me why all these steps are being taken. Maybe somebody with more insight into the Go build process could share which part(s) of these build steps are likely to break the build cache for go test? And if someone from Alpine could shed some light on why these steps are being taken that would be nice.

@eandre Happy to answer specific questions but in general I do not know why the Alpine build script is making those choices. I think you need to ask the author of the script.

@ianlancetaylor I guess the main question is why -vet=on (whether passed explicitly or by default) to go test causes runtime/cgo to be rebuilt?

I don't know. Is the problem easy to reproduce? Does it happen every time? Can you run GODEBUG=gocachehash=1 go test -x and attach the output?

Sure, here's the output of that command: https://gist.github.com/eandre/da1fc79f1fe78179869583a80c9d4fcb

Yes, it happens every time.

Here's GODEBUG=gocachehash=1 go test -vet=off -x for comparison: https://gist.github.com/eandre/d71a237df88d11ba32a6eefbcaeaf11a

Thanks. The hash is the same, so that wasn't it.

I think the problem is that vet wants to collect information, known as "facts", for runtime/cgo (as well as all the other packages that the problem depends on). That information can be cached, but it hasn't been cached on your system. For a package that uses cgo, vet needs to run cgo to see the generated files. So vet invokes cgo. But on your system, which does not have "gcc" installed, that fails.

@dackroyd worked ๐Ÿ‘๐Ÿ‘

Not sure if this was made clear so far or not, but I'm experiencing this issue on all alpine based official golang docker images. Of course it can be mitigated by setting CGO_ENABLED=0 or using go test -vet=off. This issue is not present on the buster based images.

This throws me back to https://github.com/golang/go/issues/28065#issuecomment-427664236. What's the point of distributing an official golang Docker image if the image is incomplete or set improperly?

Was this page helpful?
0 / 5 - 0 ratings