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/link: cross compile from MacOS to Windows with CGO_ENABLED=1 and -buildmode=c-archive not working #59221

Closed
awsong opened this issue Mar 24, 2023 · 16 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@awsong
Copy link

awsong commented Mar 24, 2023

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

@awsong awsong changed the title affected/package: Cross compile from MacOS to Windows with CGO_ENABLED and -buildmode=c-archive not working affected/package: Cross compile from MacOS to Windows with CGO_ENABLED=1 and -buildmode=c-archive not working Mar 24, 2023
@heschi heschi changed the title affected/package: Cross compile from MacOS to Windows with CGO_ENABLED=1 and -buildmode=c-archive not working cmd/compile: cross compile from MacOS to Windows with CGO_ENABLED=1 and -buildmode=c-archive not working Mar 24, 2023
@heschi
Copy link
Contributor

heschi commented Mar 24, 2023

cc @golang/compiler

@heschi heschi added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Mar 24, 2023
@heschi heschi added this to the Go1.21 milestone Mar 24, 2023
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Mar 24, 2023
@cherrymui
Copy link
Member

What version of C toolchain do you use? Thanks.

cc @thanm

@awsong
Copy link
Author

awsong commented Mar 24, 2023

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) 

@thanm thanm self-assigned this Mar 27, 2023
@thanm
Copy link
Contributor

thanm commented Mar 27, 2023

@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
$

@awsong
Copy link
Author

awsong commented Mar 27, 2023

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

@thanm
Copy link
Contributor

thanm commented Mar 27, 2023

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.

@thanm
Copy link
Contributor

thanm commented Mar 27, 2023

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".

@awsong
Copy link
Author

awsong commented Mar 28, 2023

Verified that the workaround works on my system.

Thanks

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/479775 mentions this issue: cmd/link: use "ar" path derived from querying CC for -buildmode=c-archive

@thanm thanm changed the title cmd/compile: cross compile from MacOS to Windows with CGO_ENABLED=1 and -buildmode=c-archive not working cmd/link: cross compile from MacOS to Windows with CGO_ENABLED=1 and -buildmode=c-archive not working Mar 28, 2023
@thanm thanm added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Mar 28, 2023
johanbrandhorst pushed a commit to Pryz/go that referenced this issue Mar 28, 2023
…mode

When external linking with -buildmode=c-archive, the Go linker
eventually invokes the "ar" tool to create the final archive library.
Prior to this patch, if the '-extar' flag was not in use, we would
just run "ar". This works well in most cases but breaks down if we're
doing cross-compilation targeting Windows (macos system "ar"
apparently doesn't create the windows symdef section correctly). To
fix the problem, capture the output of "cc --print-prog-name ar" and
invoke "ar" using the path returned by that command.

Fixes golang#59221.

Change-Id: I9de66e98947c42633b16fde7208c2958d62fe7cc
Reviewed-on: https://go-review.googlesource.com/c/go/+/479775
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
@thanm
Copy link
Contributor

thanm commented Mar 28, 2023

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.

@cherrymui cherrymui reopened this Mar 28, 2023
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/480675 mentions this issue: env/corellium/ios: special case "--print-prog-name=ar" in clang wrapper

gopherbot pushed a commit to golang/build that referenced this issue Mar 31, 2023
Intercept the "--print-prog-name=ar" flag in the clang wrapper and
return "ar" from the system path, as opposed to the "ar" selected
by clang. This is needed to avoid bypassing the ar wrapper installed
in /var/root/bin, which is the one we want.

Updates golang/go#59221.

Change-Id: I907a6d6be2e6439901b36d6f7f8669939fd82e94
Reviewed-on: https://go-review.googlesource.com/c/build/+/480675
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/488576 mentions this issue: cmd/link: use path from "cc --print-prog-name ar" for c-archive buildmode

@mknyszek
Copy link
Contributor

mknyszek commented Jun 9, 2023

Hey @thanm, any update here? Do you still plan to do this for Go 1.21? Thanks.

@thanm thanm modified the milestones: Go1.21, Backlog Jun 9, 2023
@thanm
Copy link
Contributor

thanm commented Jun 9, 2023

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.

@cherrymui
Copy link
Member

If we want to do something for this cycle, we could do it only for Windows.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/592375 mentions this issue: cmd/link: use path from "cc --print-prog-name ar" for c-archive buildmode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. NeedsFix The path to resolution is known, but the work has not been done.
Projects
Development

No branches or pull requests

6 participants