What version of Go are you using (go version
)?
$ go version go version go1.20.2 darwin/arm64
Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (go env
)?
go env
Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/wsong/Library/Caches/go-build" GOENV="/Users/wsong/Library/Application Support/go/env" GOEXE=".exe" GOEXPERIMENT="" GOFLAGS="" GOHOSTARCH="arm64" GOHOSTOS="darwin" GOINSECURE="" GOMODCACHE="/Users/wsong/go/pkg/mod" GONOPROXY="" GONOSUMDB="" GOOS="windows" GOPATH="/Users/wsong/go" GOPRIVATE="" GOPROXY="https://goproxy.cn" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_arm64" GOVCS="" GOVERSION="go1.20.2" GCCGO="gccgo" GOAMD64="v1" AR="x86_64-w64-mingw32-gcc" CC="x86_64-w64-mingw32-gcc" CXX="clang++" CGO_ENABLED="1" GOMOD="/Users/wsong/Development/test/go.mod" GOWORK="" CGO_CFLAGS="-O2 -g" CGO_CPPFLAGS="" CGO_CXXFLAGS="-O2 -g" CGO_FFLAGS="-O2 -g" CGO_LDFLAGS="-O2 -g" PKG_CONFIG="pkg-config" GOGCCFLAGS="-m64 -mthreads -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/var/folders/lr/s8_5072s6cs602ksv8tv5myh0000gn/T/go-build2849677897=/tmp/go-build -gno-record-gcc-switches"
What did you do?
I have following files in my folder:
example/ go.mod test.c test.go ./example: main.c
wsong@Work: ~/Development/test $ cat go.mod module test go 1.20 wsong@Work: ~/Development/test $ cat test.c // Functions exported by Go. extern int Test(); int test() { Test(); return 0; } wsong@Work: ~/Development/test $ cat test.go package main //#include "errno.h" import "C" func main() {} //export Test func Test() C.int { return 0 } wsong@Work: ~/Development/test $ cat example/main.c extern int test(); int main(void) { test(); return 0; }
I run go build like this:
CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build -v -a -buildmode=c-archive .
Then go into example folder and run:
x86_64-w64-mingw32-gcc main.c ../test.a
What did you expect to see?
a.exe is generated.
What did you see instead?
/opt/homebrew/Cellar/mingw-w64/10.0.0_5/toolchain-x86_64/bin/x86_64-w64-mingw32-ld: /var/folders/lr/s8_5072s6cs602ksv8tv5myh0000gn/T//ccHcSIoc.o:main.c:(.text+0xe): undefined reference to `test' collect2: error: ld returned 1 exit status
Comment From: heschi
cc @golang/compiler
Comment From: cherrymui
What version of C toolchain do you use? Thanks.
cc @thanm
Comment From: awsong
It's mingw-w64 from homebrew, on M1 Mac.
wsong@Work: ~/Development/test/example $ x86_64-w64-mingw32-gcc -v Using built-in specs. COLLECT_GCC=x86_64-w64-mingw32-gcc COLLECT_LTO_WRAPPER=/opt/homebrew/Cellar/mingw-w64/10.0.0_5/toolchain-x86_64/libexec/gcc/x86_64-w64-mingw32/12.2.0/lto-wrapper Target: x86_64-w64-mingw32 Configured with: ../configure --target=x86_64-w64-mingw32 --with-sysroot=/opt/homebrew/Cellar/mingw-w64/10.0.0_5/toolchain-x86_64 --prefix=/opt/homebrew/Cellar/mingw-w64/10.0.0_5/toolchain-x86_64 --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --enable-languages=c,c++,fortran --with-ld=/opt/homebrew/Cellar/mingw-w64/10.0.0_5/toolchain-x86_64/bin/x86_64-w64-mingw32-ld --with-as=/opt/homebrew/Cellar/mingw-w64/10.0.0_5/toolchain-x86_64/bin/x86_64-w64-mingw32-as --with-gmp=/opt/homebrew/opt/gmp --with-mpfr=/opt/homebrew/opt/mpfr --with-mpc=/opt/homebrew/opt/libmpc --with-isl=/opt/homebrew/opt/isl --with-zstd=no --disable-multilib --disable-nls --enable-threads=posix Thread model: posix Supported LTO compression algorithms: zlib gcc version 12.2.0 (GCC)
Comment From: thanm
@awsong Thanks for the report.
If you could dump out the symbols from your test.a
and post it here, that would be helpful, e.g. something like
$ CGO_ENABLED=1 go build -buildmode=c-archive
$ llvm-objdump-14 -t test.a | fgrep test | fgrep .text
0000000000011200 l F .text 00000000000000ef runtime.gcTrigger.test
000000000003ade0 l F .text 00000000000001f0 runtime.testAtomic64
0000000000000000 g F .text 000000000000000c test
$
Comment From: awsong
wsong@Work: ~/Development/test $ x86_64-w64-mingw32-objdump -t test.a | fgrep test | fgrep .text wsong@Work: ~/Development/test $ x86_64-w64-mingw32-objdump -t test.a | fgrep test In archive test.a: [228](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000012900 runtime.gcTrigger.test [697](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000000000003e620 runtime.testAtomic64 [1544](sec 4)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000053678 runtime.test_z64 [1545](sec 4)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000053670 runtime.test_x64 [1569](sec 4)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000534a9 runtime.testingWER [ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x0000000000000000 test.cgo2.c [ 0](sec -2)(fl 0x00)(ty 0)(scl 103) (nx 1) 0x0000000000000000 test.c [ 2](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x0000000000000000 test
Comment From: thanm
Thanks. No red flags there, not immediately sure what the issue is. I'll work on setting up a test machine of some sort to see if I can repro. Stay tuned.
Comment From: thanm
OK, I think I see what the issue is. I'll send a CL tomorrow morning.
If you need a workaround for the time being, you can do this:
$ ARPATH=`x86_64-w64-mingw32-gcc --print-prog-name ar`
$ CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc AR=x86_64-w64-mingw32-gcc GOOS=windows GOARCH=amd64 go build -ldflags="-extar=$ARPATH" -buildmode=c-archive .
$
Problem here is that the Go linker is invoking the system "ar" instead of the cross-compiler's "ar".
Comment From: awsong
Verified that the workaround works on my system.
Thanks
Comment From: gopherbot
Change https://go.dev/cl/479775 mentions this issue: cmd/link: use "ar" path derived from querying CC for -buildmode=c-archive
Comment From: thanm
Hmm, I've had to send a revert for https://go.dev/cl/479775 since it causes a failure on our ios-arm64-corellium
builder... hopefully after I figure out what is going on I can resubmit CL 479775.
Comment From: gopherbot
Change https://go.dev/cl/480675 mentions this issue: env/corellium/ios: special case "--print-prog-name=ar" in clang wrapper
Comment From: gopherbot
Change https://go.dev/cl/488576 mentions this issue: cmd/link: use path from "cc --print-prog-name ar" for c-archive buildmode
Comment From: mknyszek
Hey @thanm, any update here? Do you still plan to do this for Go 1.21? Thanks.
Comment From: thanm
I've moved to backlog. The main sticking points here are the problems with the ios correllium builders-- needs more investigation as to why the change doesn't work with their custom wrappers.
Comment From: cherrymui
If we want to do something for this cycle, we could do it only for Windows.
Comment From: gopherbot
Change https://go.dev/cl/592375 mentions this issue: cmd/link: use path from "cc --print-prog-name ar" for c-archive buildmode