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: give a better error message when building Go package with CGO_ENABLED=0 #24068

Open
ikkerens opened this issue Feb 23, 2018 · 22 comments
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@ikkerens
Copy link
Contributor

ikkerens commented Feb 23, 2018

When trying to cross compile the go compiler silently ignores any files that use import "C" statement.
In this example I've tried to compile for windows on a linux host machine, but this issue seems to be present on other host platforms as well.
It seems to do this because it disables CGO_ENABLED being disabled by default when the host and target platform mismatch despite the required toolchains being present (mingw-w64 in my case).

I managed to resolve this issue by enabling CGO_ENABLED and setting CC and CXX, but this issue is more about the unclear error message.

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

go version go1.10 linux/amd64

Does this issue reproduce with the latest release?

Yes.

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

Without GOOS:

GOARCH="amd64"
GOBIN=""
GOCACHE="/home/ikkerens/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/usr/lib/go:/var/git/Go"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
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 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build897508503=/tmp/go-build -gno-record-gcc-switches"

With GOOS=windows

GOARCH="amd64"
GOBIN=""
GOCACHE="/home/ikkerens/.cache/go-build"
GOEXE=".exe"
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="windows"
GOPATH="/usr/lib/go:/var/git/Go"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-m64 -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build822882573=/tmp/go-build -gno-record-gcc-switches"

What did you do?

2 Go files:

// cgo.go
package main

import "C"

func test() {
}
// main.go
package main

func main() {
        test()
}

What did you expect to see?

Some kind of warning that cgo.go is being skipped in compilation due to CGO_ENABLED being 0.

What did you see instead?

# test
./main.go:4:2: undefined: test
@mingrammer
Copy link
Contributor

Did you run go build ?

@ikkerens
Copy link
Contributor Author

ikkerens commented Feb 23, 2018

Yes, the two commands I used for comparison are:

GOOS=linux go build
GOOS=windows go build

The second one produces the "undefined" error message.

@mingrammer
Copy link
Contributor

mingrammer commented Feb 23, 2018

Hmm .. same problem to me. It seems like go can not find source file which import "C" when GOOS=windows

@tklauser tklauser added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Feb 23, 2018
@davecheney
Copy link
Contributor

davecheney commented Feb 23, 2018 via email

@ikkerens
Copy link
Contributor Author

@davecheney I am aware, the issue in question is more about the lack of a proper error message instead of silently ignoring the affected files and thus causing "undefined" errors.

@mvdan
Copy link
Member

mvdan commented Feb 23, 2018

Should all packages using cgo fail to build with CGO_ENABLED=0? That seems wrong to me - some standard library packages build both with and without cgo, such as os/user.

@mvdan
Copy link
Member

mvdan commented Feb 23, 2018

Something else that comes to mind is a static analysis check (in vet?) that would say something along the lines of this package will fail to cross-compile and build with CGO_ENABLED=0. That is, checking if a package typechecks properly both with and without the cgo build tag.

@ikkerens
Copy link
Contributor Author

Even go vet would indeed be very helpful, as I spent quite some time trying to find out why my build wouldn't work.

Regarding letting builds fail, I definitely don't think it should, but even building with -x -v doesn't give any information about skipping the file because there isn't any.

All I'm asking for is more information for when this occurs. And you could potentially suppress any warnings/errors when the //+build cgo is used.

@mvdan
Copy link
Member

mvdan commented Feb 23, 2018

The Go compiler doesn't have a notion of warnings, so -x -v should not affect its output.

I guess another option, which is similar to what you're asking, is to make the compiler give a helpful message in this case. But, for it to know to do that, it would have to know that the package type-checks properly with CGO. That's a non-trivial amount of extra work involved.

@ikkerens
Copy link
Contributor Author

ikkerens commented Feb 23, 2018

I'll leave that one to you/the team, as I have no knowledge of the compiler itself. I opened this issue as someone I had spoken to not too long ago was getting this same error without knowing why, and it wasn't until encountering it myself that I understood the cause of it. Any kind of message either in the compiler or even the documentation would be very helpful.

The documentation ( https://golang.org/cmd/cgo/#hdr-Using_cgo_with_the_go_command ) currently specifies that CGO_ENABLED will be disabled if the target platform is different from the host, but fails to mention that any files still using import "C" will be ignored as if //+build cgo is implied.

So even if the amount of work required to add a helpful compiler message is non-trivial, I'd imagine a slight addition to the documentation wouldn't be.

@mvdan
Copy link
Member

mvdan commented Feb 23, 2018

Agreed that improving the documentation is an easy win - if you'd like to help, you're most welcome to. Should be easy now that we accept pull requests.

@gopherbot
Copy link

Change https://golang.org/cl/96655 mentions this issue: cmd/cgo: clarify implicit "cgo" build constraint

@ianlancetaylor
Copy link
Contributor

One way we could do better would be for the go tool, if there is a compilation error, to report that some files were excluded due to build constraints (we already do that for the case where build constraints exclude all files). We could perhaps even pay closer attention to the cgo build constraint, and explicitly point the user to docs about the CGO_ENABLED environment variable.

@ianlancetaylor
Copy link
Contributor

That is, we don't have the type check the package assuming a different set of build constraints. We just note that the compilation failed and print "by the way, the following files were not passed to the compiler due to build constraints: x.go ...".

gopherbot pushed a commit that referenced this issue Feb 26, 2018
When using the special import "C", the "cgo" build constraint is implied for the go file,
potentially triggering unclear "undefined" error messages.
Explicitly explain this in the documentation.

Updates #24068

Change-Id: Ib656ceccd52c749ffe7fb2d3db9ac144f17abb32
GitHub-Last-Rev: 5a13f00
GitHub-Pull-Request: #24072
Reviewed-on: https://go-review.googlesource.com/96655
Reviewed-by: Ian Lance Taylor <iant@golang.org>
@ianlancetaylor ianlancetaylor changed the title cmd/compile: bad error message when cross-compiling while using cgo cmd/go: give a better error message when building Go package with CGO_ENABLED=0 Mar 28, 2018
@ianlancetaylor ianlancetaylor added the NeedsFix The path to resolution is known, but the work has not been done. label Mar 28, 2018
@ianlancetaylor ianlancetaylor added this to the Go1.11 milestone Mar 28, 2018
@gopherbot gopherbot removed the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 28, 2018
@ianlancetaylor ianlancetaylor modified the milestones: Go1.11, Go1.12 Jul 6, 2018
@bcmills bcmills modified the milestones: Go1.12, Go1.13 Nov 13, 2018
@bcmills
Copy link
Contributor

bcmills commented Jan 18, 2019

One way we could do better would be for the go tool, if there is a compilation error, to report that some files were excluded due to build constraints (we already do that for the case where build constraints exclude all files).

Compare #26967.

@ikkerens
Copy link
Contributor Author

While I can't speak for the complexity/reward ratio as rsc mentions, personally it would've saved me a few hours of debugging. That said, my personal problem was more along the lines of the cgo build tag being implied moreso than a build tag being enforced.

@triztian
Copy link

triztian commented Jun 1, 2019

I just recently experienced something similar when trying to cross-compile, I think that the error message should also print the build constraints being applied, i.e.:

# $ go env
#    GOOS=windows
#    GOARCH=386
#    CGO_ENABLED=1
go build -tags "abc" ./subpkg

if the constraints happen to exclude all files, then it'd be great if it printed something like the following:

go build example.com/mainpkg/subpkg: build constraints ("cgo windows 386 abc")  exclude all Go files in /path/to/sources/example.com/mainpkg/subpkg

In my case I was cross-compiling from Windows Subsystem for Linux to a windows target that had CGO files, I initially had not set CGO_ENABLED=1 and it took me a while to realize it b.c. the only build constraints I had in mind where windows, 386 and abc and the error message did not bring it up.

Getting the applied build constraints would allow one to do the following:

$ go list -tags 'cgo windows 386 abc' -f '{{.IgnoredGoFiles}}' ./subpkg
[important.go]

It'd be great if the go list command supported printing also the non-go files that are ignored, something like:

$ go list -tags 'cgo windows 386 abc' -f '{{.IgnoredFiles}}' ./subpkg
[important.go bindings.c]

@thewilli
Copy link

imho the result is even worse if you consider the example of @ikkerens with any external package imported, e.g.

// cgo.go
package main

import "C"
import "github.com/pkg/errors" // just an arbitrary package

func test() {
        _ = errors.New("my error")
}

Instead of ./main.go:4:2: undefined: test the error message will be cannot find module for path github.com/pkg/errors. This just took me literally hours, because I was expecting an imported package to be dependent on CGO, while the actual issue was just me forgetting about an import "C" in the code.

This is really misleading and hard to track down...

zchee pushed a commit to zchee/golang-wiki that referenced this issue Sep 21, 2019
@rsc rsc modified the milestones: Go1.14, Backlog Oct 9, 2019
@StarpTech
Copy link

StarpTech commented Mar 28, 2020

I can reproduce it without CGO_ENABLED involved. This compiler error is not precise.

https://repl.it/@StarpTech/UnderstatedSpatialSysadmin

@anoduck
Copy link

anoduck commented Nov 7, 2021

Just referencing this error is occurring in OpenBSD with the pkg pistol.

doronbehar/pistol#76

After reviewing the thread, it appears a resolution was reached for this particular instance and Nixos, but it is unapparent if a resolution was reached regarding other operating systems and/or packages. Regardless of which, the proposed resolution...

Solved this problem by putting package main in first line of my .go script

...was not successful.

@jhillhouse92
Copy link

@jsoneaday

This comment was marked as off-topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests