golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
123.83k stars 17.65k forks source link

cmd/go: provide better error message when cross-compiling toolchain is required #16395

Open josharian opened 8 years ago

josharian commented 8 years ago
  1. What version of Go are you using (go version)?

510fb6397dfc93067dc90d42c58dfc5f8b995285: tip between 1.7rc1 and 1.7rc2

  1. What operating system and processor architecture are you using (go env)?
GOARCH="amd64"
GOBIN="/Users/josh/bin"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/josh"
GORACE=""
GOROOT="/Users/josh/go/tip"
GOTOOLDIR="/Users/josh/go/tip/pkg/tool/darwin_amd64"
CC="clang"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/pp/0010hzld5b12h_92j5th082r0000gn/T/go-build629103623=/tmp/go-build -gno-record-gcc-switches -fno-common"
CXX="clang++"
CGO_ENABLED="1"
  1. What did you do?

GOOS=android GOARCH=amd64 go install std cmd

  1. What did you expect to see?

Success.

  1. What did you see instead?
# cmd/addr2line
warning: unable to find runtime/cgo.a
/Users/josh/go/tip/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: unknown option: -z
clang: error: linker command failed with exit code 1 (use -v to see invocation)

# cmd/asm
warning: unable to find runtime/cgo.a
/Users/josh/go/tip/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: unknown option: -z
clang: error: linker command failed with exit code 1 (use -v to see invocation)

and so on

Running GOOS=android GOARCH=amd64 go install -ldflags=-v std cmd:

# cmd/cgo
HEADER = -H4 -T0x401000 -D0x0 -R0x1000
searching for runtime.a in $WORK/runtime.a
searching for runtime.a in /Users/josh/go/tip/pkg/android_amd64_shared/runtime.a
searching for runtime/cgo.a in $WORK/runtime/cgo.a
searching for runtime/cgo.a in /Users/josh/go/tip/pkg/android_amd64_shared/runtime/cgo.a
warning: unable to find runtime/cgo.a
 0.00 deadcode
 0.03 pclntab=599713 bytes, funcdata total 119620 bytes
 0.03 dodata
 0.04 dwarf
 0.07 symsize = 0
 0.16 reloc
 0.17 asmb
 0.17 codeblk
 0.17 datblk
 0.18 sym
 0.18 symsize = 122040
 0.19 symsize = 122088
 0.19 dwarf
 0.21 headr
host link: "clang" "-m64" "-gdwarf-2" "-Wl,-z,relro" "-pie" "-o" "/var/folders/pp/0010hzld5b12h_92j5th082r0000gn/T/go-build962217633/cmd/cgo/_obj/exe/a.out" "-rdynamic" "-Qunused-arguments" "/var/folders/pp/0010hzld5b12h_92j5th082r0000gn/T/go-link-534529285/go.o"
/Users/josh/go/tip/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: unknown option: -z
clang: error: linker command failed with exit code 1 (use -v to see invocation)

and so on

This also causes GOOS=android GOARCH=amd64 ./bootstrap.bash to fail.

Maybe this is expected (?), but it doesn't seem right to me.

ianlancetaylor commented 8 years ago

You are trying to cross-compile from darwin/amd64 to android/amd64, but you seem to be using the native compiler rather than a cross-compiler. That can't work.

Note that for android/amd64 the default build mode is -pie which means that cmd/link will always invoke the external linker, so you always need to provide a cross-compiler.

josharian commented 8 years ago

Ah, that makes sense. Thanks. Let's call this issue about the error message, then, if this situation is not too hard to detect.

rsc commented 8 years ago

Not sure how we know whether $CC is a cross compiler.

ianlancetaylor commented 8 years ago
echo "int main { return 0; }" > trivial.c
$CC -o trivial trivial.c
./trivial

If that succeeds you have a normal compiler, if it fails you have a cross-compiler. But it's a bit annoying to have to do this test each time.

minux commented 8 years ago

We could try build an object file with the tool chain and then look at the ELF file header.

We already do trial builds to detect whether gcc supports certain flags (e.g. -fdebug-prefix-map), we can detect the output object file type without even more overhead.

eternaleye commented 7 years ago

@ianlancetaylor:

That test is invalid. On Exherbo, all compilation takes the cross-compilation path, including both compiling for the host architecture and multilib.

We use /usr/$TRIPLE as $PREFIX, always use $TRIPLE-prefixed $CC, etc. Your proposed test will have false positives for:

  1. Native architecture, native runtime (x86_64-pc-linux-gnu on x86_64-pc-linux-gnu)
  2. Native architecture, foreign runtime (x86_64-pc-linux-musl on x86_64-pc-linux-gnu)
  3. Compatible architecture, native runtime (i686-pc-linux-gnu on x86_64-pc-linux-gnu)
  4. Compatible architecture, foreign runtime (i686-pc-linux-musl on x86_64-pc-linux-gnu)

All four are supported and in active use on Exherbo.

ianlancetaylor commented 7 years ago

@eternaleye Does that matter for the purposes of this issue, which is just about issuing a better error message?

eternaleye commented 7 years ago

Ah, was brought here by a google search for a similar error to that which the OP hit. Is there a ticket for that?

My specific case is I noticed (while building 1.7.1 release as an upgrade from 1.6.3) that cgo.a was not being built. This resulted in another package failing to build due to it being missing, similar to what this issue describes (1.6.3 had worked fine)

ianlancetaylor commented 7 years ago

@eternaleye Let's take that question to a forum rather than complicate this issue (https://golang.org/wiki/Questions). I don't know the answer off hand.

rsc commented 7 years ago

Re @ianlancetaylor's comment above:

If that succeeds you have a normal compiler, if it fails you have a cross-compiler.

The second half is likely true. The first half is not necessarily true. If it succeeds maybe your system simply knows how to run cross-compiled binaries. For example building 32-bit binaries on a 64-bit system, or even arm binaries on an x86 system if you have a binfmt module installed to run qemu or some such.

I do agree with Minux that instead of running ./trivial we can open it and inspect the header and sanity check against the target GOOS/GOARCH. If someone wants to send a CL for that (not during a release freeze), that'd be great.

amenzhinsky commented 6 years ago

gcc -v provides the Target section, e.g: arm-linux-gnueabihf or x86_64-pc-linux-gnu so it can be used to determine whether CC is a cross-compiler or not and warn users about target mismatches (not sure that all gcc versions do that).