golang / go

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

cmd/link: cgo linking fails on Windows with GCC 11.2.0 + MinGW-w64 9.0.0 (UCRT) from winlibs.com #51007

Closed NewUserHa closed 1 year ago

NewUserHa commented 2 years ago

Original post: https://github.com/mattn/go-sqlite3/issues/1012

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

$ go version
go version go1.17.5 windows/amd64

Does this issue reproduce with the latest release?

maybe

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

go env Output
$ go env
set GO111MODULE=
set GOARCH=amd64
set GOBIN=C:\Users\user\Desktop
set GOCACHE=C:\Users\user\AppData\Local\go-build
set GOENV=C:\Users\user\AppData\Roaming\go\env
set GOEXE=.exe
set GOEXPERIMENT=
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMODCACHE=C:\Users\user\go\pkg\mod
set GONOPROXY=
set GONOSUMDB=
set GOOS=windows
set GOPATH=C:\Users\user\go
set GOPRIVATE=
set GOPROXY=https://goproxy.io,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTMPDIR=
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.17.5
set GCCGO=gccgo
set AR=ar
set CC=gcc
set CXX=g++
set CGO_ENABLED=1
set GOMOD=NUL
set CGO_CFLAGS=-g -O2
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-g -O2
set CGO_FFLAGS=-g -O2
set CGO_LDFLAGS=-g -O2
set PKG_CONFIG=pkg-config
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0 -fdebug-prefix-map=C:\Users\user\AppData\Local\Temp\go-build2697353945=/tmp/go-build -gno-record-gcc-switches

What did you do?

import it and go build or go run .

What did you expect to see?

no output

What did you see instead?

> go run .
# 
C:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\go-link-2621619269\000016.o: in function `_cgo_preinit_init':
c:\go\src\runtime\cgo/gcc_libinit_windows.c:30: undefined reference to `__imp___iob_func'
c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\go-link-2621619269\000016.o: in function `x_cgo_sys_thread_create':
c:\go\src\runtime\cgo/gcc_libinit_windows.c:60: undefined reference to `__imp___iob_func'
c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\go-link-2621619269\000016.o: in function `x_cgo_notify_runtime_init_done':
c:\go\src\runtime\cgo/gcc_libinit_windows.c:101: undefined reference to `__imp___iob_func'
c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\go-link-2621619269\000017.o: in function `x_cgo_thread_start':
c:\go\src\runtime\cgo/gcc_util.c:18: undefined reference to `__imp___iob_func'
c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\user\AppData\Local\Temp\go-link-2621619269\000018.o: in function `_cgo_sys_thread_start':
c:\go\src\runtime\cgo/gcc_windows_amd64.c:31: undefined reference to `__imp___iob_func'
collect2.exe: error: ld returned 1 exit status
toothrot commented 2 years ago

Do you have a sample program that reproduces this issue?

NewUserHa commented 2 years ago

any code that causes go-sqlite3 to compile is enough. maybe https://github.com/mattn/go-sqlite3/blob/master/_example/simple/simple.go, and the problem compiler is "GCC 11.2.0 + LLVM/Clang/LLD/LLDB 13.0.0 + MinGW-w64 9.0.0 (UCRT) - release 2" in that homepage within the original post

bcmills commented 2 years ago

I haven't dug in too far, but I suspect that the problem here is skew between the precompiled runtime/cgo object file and the C compiler that you are using. (The C compiler we use to build the Go distribution is very old; see #35006.)

When we stop shipping precompiled object files (#47257) then version skew should no longer be an issue.

@NewUserHa, in the meantime you may be able to work around the problem by installing Go from source. Could you give that a try and post the results?

NewUserHa commented 2 years ago

I don't have any toolchain for that except the only pre-build gcc compiler. so probably needs others to test

bcmills commented 2 years ago

You shouldn't need much else on top of the gcc toolchain — just git to clone the Go repo, really.

NewUserHa commented 2 years ago

Should follow which part of https://go.dev/doc/install/source? it says "There are two official Go compiler toolchains."

NewUserHa commented 2 years ago
``` all.bat Building Go cmd/dist using C:\Program Files\Go Building Go toolchain1 using C:\Program Files\Go. Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1. Building Go toolchain2 using go_bootstrap and Go toolchain1. Building Go toolchain3 using go_bootstrap and Go toolchain2. Building packages and commands for windows/amd64. ##### Testing packages. ok archive/tar 0.852s ok archive/zip 0.967s ok bufio 0.395s ok bytes 0.626s ok compress/bzip2 0.499s ok compress/flate 1.465s ok compress/gzip 0.479s ok compress/lzw 0.419s ok compress/zlib 0.713s ok container/heap 0.406s ok container/list 0.362s ok container/ring 0.363s ok context 0.403s ok crypto 0.360s ok crypto/aes 0.438s ok crypto/cipher 0.455s ok crypto/des 0.381s ok crypto/dsa 0.389s ok crypto/ecdsa 0.473s ok crypto/ed25519 0.573s ok crypto/ed25519/internal/edwards25519 7.214s ok crypto/ed25519/internal/edwards25519/field 2.868s ok crypto/elliptic 0.486s ok crypto/elliptic/internal/fiat 0.364s ok crypto/hmac 0.340s ok crypto/internal/subtle 0.377s ok crypto/md5 0.321s ok crypto/rand 0.376s ok crypto/rc4 0.382s ok crypto/rsa 0.852s ok crypto/sha1 0.359s ok crypto/sha256 0.341s ok crypto/sha512 0.432s ok crypto/subtle 0.469s ok crypto/tls 2.519s ok crypto/x509 3.518s ok database/sql 1.244s ok database/sql/driver 0.400s ok debug/dwarf 0.651s ok debug/elf 0.597s ok debug/gosym 0.464s ok debug/macho 0.517s --- FAIL: TestInternalLinkerDWARF (4.33s) file_test.go:389: building test executable for linktype 2 failed: exit status 2 # command-line-arguments c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmsvcrt.a(/697): duplicate symbol reference: fprintf in both libgcc(.text) and libgcc(.data) runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined FAIL FAIL debug/pe 23.802s ok debug/plan9obj 0.325s ok embed/internal/embedtest 0.353s ok encoding/ascii85 0.499s ok encoding/asn1 0.465s ok encoding/base32 0.439s ok encoding/base64 0.425s ok encoding/binary 0.455s ok encoding/csv 0.441s ok encoding/gob 0.649s ok encoding/hex 0.506s ok encoding/json 1.146s ok encoding/pem 0.599s ok encoding/xml 0.542s ok errors 0.516s ok expvar 0.596s ok flag 1.144s ok fmt 0.558s ok go/ast 0.528s ok go/build 11.913s ok go/build/constraint 0.399s ok go/constant 0.371s ok go/doc 1.566s ok go/format 0.464s ok go/importer 1.084s ok go/internal/gccgoimporter 0.919s ok go/internal/gcimporter 1.168s ok go/internal/srcimporter 19.412s ok go/parser 0.608s ok go/printer 1.036s ok go/scanner 0.377s ok go/token 0.918s ok go/types 8.574s ok hash 0.438s ok hash/adler32 0.364s ok hash/crc32 0.443s ok hash/crc64 0.348s ok hash/fnv 0.348s ok hash/maphash 0.559s ok html 0.418s ok html/template 0.822s ok image 0.720s ok image/color 0.372s ok image/draw 0.460s ok image/gif 1.995s ok image/jpeg 1.313s ok image/png 0.857s ok index/suffixarray 0.608s ok internal/abi 0.979s ok internal/cpu 0.374s ok internal/execabs 0.458s ok internal/fmtsort 0.378s ok internal/itoa 0.414s ok internal/poll 0.457s ok internal/profile 0.493s ok internal/reflectlite 0.614s ok internal/singleflight 0.382s ok internal/syscall/windows 0.616s ok internal/syscall/windows/registry 0.373s ok internal/trace 0.842s ok internal/unsafeheader 0.409s ok internal/xcoff 0.583s ok io 0.423s ok io/fs 0.383s ok io/ioutil 0.441s ok log 0.359s ok math 0.380s ok math/big 2.177s ok math/bits 0.487s ok math/cmplx 0.379s ok math/rand 0.723s ok mime 0.469s ok mime/multipart 0.728s ok mime/quotedprintable 0.502s ok net 11.028s ok net/http 17.491s ok net/http/cgi 2.778s ok net/http/cookiejar 1.272s ok net/http/fcgi 1.219s ok net/http/httptest 2.955s ok net/http/httptrace 0.486s ok net/http/httputil 1.683s ok net/http/internal 0.436s ok net/http/internal/ascii 0.411s ok net/http/pprof 5.961s ok net/internal/socktest 0.362s ok net/mail 0.397s ok net/rpc 0.782s ok net/rpc/jsonrpc 0.589s ok net/smtp 0.665s ok net/textproto 0.411s ok net/url 0.748s ok os 11.524s # runtime/cgo.test c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmsvcrt.a(/697): duplicate symbol reference: fprintf in both libgcc(.text) and libgcc(.data) runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined ok os/exec 26.003s ok os/signal 5.534s ok os/user 0.363s ok path 0.332s ok path/filepath 5.598s ok plugin 0.554s ok reflect 0.978s ok regexp 0.742s ok regexp/syntax 0.806s ok runtime 225.056s FAIL runtime/cgo [build failed] ok runtime/debug 0.488s ok runtime/internal/atomic 0.369s ok runtime/internal/math 0.634s ok runtime/internal/sys 0.369s ok runtime/metrics 0.349s ok runtime/pprof 18.631s ok runtime/trace 1.720s ok sort 0.404s ok strconv 0.782s ok strings 0.658s ok sync 2.788s ok sync/atomic 3.048s ok syscall 29.554s ok testing 2.061s ok testing/fstest 0.444s ok testing/iotest 0.408s ok testing/quick 0.471s ok text/scanner 0.445s ok text/tabwriter 0.450s ok text/template 0.883s ok text/template/parse 0.494s ok time 3.451s ok unicode 0.441s ok unicode/utf16 0.408s ok unicode/utf8 0.723s ok cmd/addr2line 17.369s ok cmd/api 28.216s ok cmd/asm/internal/asm 3.019s ok cmd/asm/internal/lex 0.524s ok cmd/compile/internal/dwarfgen 7.364s ok cmd/compile/internal/importer 3.238s ok cmd/compile/internal/ir 1.277s ok cmd/compile/internal/logopt 13.477s ok cmd/compile/internal/noder 0.664s ok cmd/compile/internal/ssa 0.880s ok cmd/compile/internal/ssagen 0.094s ok cmd/compile/internal/syntax 0.425s ok cmd/compile/internal/test 23.373s ok cmd/compile/internal/typecheck 1.999s ok cmd/compile/internal/types 0.152s ok cmd/compile/internal/types2 1.906s ok cmd/cover 10.132s ok cmd/doc 0.615s ok cmd/fix 38.606s ok cmd/go 147.079s ok cmd/go/internal/auth 0.171s ok cmd/go/internal/cache 0.954s ok cmd/go/internal/fsys 0.568s ok cmd/go/internal/generate 0.280s ok cmd/go/internal/get 0.423s ok cmd/go/internal/imports 0.520s ok cmd/go/internal/load 0.316s ok cmd/go/internal/lockedfile 0.865s ok cmd/go/internal/lockedfile/internal/filelock 0.768s ok cmd/go/internal/modconv 0.220s ok cmd/go/internal/modfetch 0.306s ok cmd/go/internal/modfetch/codehost 0.294s ok cmd/go/internal/modfetch/zip_sum_test 0.305s ok cmd/go/internal/modload 0.330s ok cmd/go/internal/mvs 0.240s ok cmd/go/internal/par 0.301s ok cmd/go/internal/search 0.269s ok cmd/go/internal/str 0.457s ok cmd/go/internal/test 0.404s ok cmd/go/internal/txtar 0.355s ok cmd/go/internal/vcs 0.712s ok cmd/go/internal/web 0.854s ok cmd/go/internal/work 0.503s ok cmd/gofmt 0.556s ok cmd/internal/archive 22.850s ok cmd/internal/buildid 0.636s ok cmd/internal/dwarf 0.522s ok cmd/internal/edit 0.549s ok cmd/internal/goobj 0.535s ok cmd/internal/moddeps 8.203s ok cmd/internal/obj 1.691s ok cmd/internal/obj/ppc64 2.910s ok cmd/internal/obj/riscv 3.074s ok cmd/internal/obj/s390x 0.624s ok cmd/internal/obj/x86 23.545s ok cmd/internal/objabi 0.621s ok cmd/internal/pkgpath 2.596s ok cmd/internal/src 0.911s ok cmd/internal/sys 0.375s ok cmd/internal/test2json 0.483s ok cmd/link 69.161s ok cmd/link/internal/benchmark 0.604s --- FAIL: TestWindowsBuildmodeCSharedASLR (0.00s) --- FAIL: TestWindowsBuildmodeCSharedASLR/no-aslr (15.25s) ld_test.go:223: IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA flag should not be set ld_test.go:232: IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE flag should not be set FAIL FAIL cmd/link/internal/ld 40.757s ok cmd/link/internal/loader 0.741s --- FAIL: TestInternalLinkerCgoExec (29.84s) nm_test.go:121: building test executable failed: exit status 2 # command-line-arguments c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/lib/../lib/libmsvcrt.a(/697): duplicate symbol reference: fprintf in both libgcc(.text) and libgcc(.data) runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined runtime/cgo(.text): relocation target __imp___acrt_iob_func not defined FAIL FAIL cmd/nm 39.402s ok cmd/objdump 41.741s ok cmd/pack 34.414s ok cmd/pprof 5.465s ok cmd/trace 0.691s ok cmd/vet 25.478s FAIL go tool dist: Failed: exit status 2 ```
bcmills commented 2 years ago

Thanks!

Perhaps not surprisingly, many of those test failures are the same tests (but with different failure modes) as what @thanm observed in https://github.com/golang/go/issues/35006#issuecomment-1022473787.

bcmills commented 2 years ago

The failure mode for cmd/link/internal/ld.TestWindowsBuildmodeCSharedASLR is identical with both updated C toolchains.

The link errors in debug/pe.TestInternalLinkerDWARF, runtime/cgo.test, and cmd/nm.TestInternalLinkerCgoExec are different, but the correlation between those tests is a bit uncanny. 😅

bcmills commented 2 years ago

Intriguingly, the string "__imp___acrt_iob_func" is hard-coded into the Go linker: https://cs.opensource.google/go/go/+/master:src/cmd/link/internal/loadpe/ldpe.go;l=505;drc=69262d48717771cedb1da86563eb3f1b094b4e92

NewUserHa commented 2 years ago

ok. will that issue get fixed anytime soon? will go support MSVC?

bcmills commented 2 years ago

will that issue get fixed anytime soon?

No idea, but I would really like it to be fixed before Go 1.19 because I want to be able to test cgo build reproducibility on Windows. 😅

will go support MSVC?

That is tracked in #20982. It is currently milestoned Unplanned, so I would not expect it to happen unless a contributor outside the Go project steps up to implement it.

NewUserHa commented 2 years ago

thanks.

thanm commented 2 years ago

I have a CL that should (in theory) take care of this problem, https://go-review.googlesource.com/c/go/+/382837. When I get that stack checked in (other parts still need work) I'll be sure to test this scenario (winlib + gosqlite). Thanks.

steowens commented 1 year ago

This message seems to happen in any program that uses featurs such as import "C" and import '

Here is a simple go file which will cause go build to fail with this error:

` package main

import "C"
import (
    "log"
    "golang.org/x/sys/windows"
)

var hModule windows.Handle

func init() {
    err := windows.GetModuleHandleEx(0x01, nil, &hModule)
    if err != nil {
        panic(err)
    }
}

func main() {
    log.Println("Hello")
}

`

go build

github.com/steowens/goWebview

C:\Program Files\Go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1 c:/program files/winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-14.0.6-mingw-w64ucrt-10.0.0-r2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\steve\AppData\Local\Temp\go-link-2891155275\000005.o: in function _cgo_preinit_init': \\_\_\runtime\cgo/gcc_libinit_windows.c:40: undefined reference toimp___iob_func' c:/program files/winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-14.0.6-mingw-w64ucrt-10.0.0-r2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\steve\AppData\Local\Temp\go-link-2891155275\000005.o: in function x_cgo_notify_runtime_init_done': \\_\_\runtime\cgo/gcc_libinit_windows.c:105: undefined reference toimp_iob_func' c:/program files/winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-14.0.6-mingw-w64ucrt-10.0.0-r2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\steve\AppData\Local\Temp\go-link-2891155275\000005.o: in function _cgo_beginthread': \\_\_\runtime\cgo/gcc_libinit_windows.c:149: undefined reference toimp_iob_func' c:/program files/winlibs-x86_64-posix-seh-gcc-12.2.0-llvm-14.0.6-mingw-w64ucrt-10.0.0-r2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\steve\AppData\Local\Temp\go-link-2891155275\000006.o: in function x_cgo_thread_start': \\_\_\runtime\cgo/gcc_util.c:18: undefined reference to_impiob_func' collect2.exe: error: ld returned 1 exit status

thanm commented 1 year ago

@steowens thanks for the note.

Much work has been done on the Go linker's windows host object loading phase since this issue was filed last February. Things are better now on Go tip (e.g. the version about to be released as Go 1.20). I tested your example by hand using Go 1.20 RC1 and these compilers from winlibs.com, and things work ok for me.

If you get a change, perhaps you can download the release candidate and try it yourself, see this email.

seankhliao commented 1 year ago

note 1.20rc1 doesn't have precompiled object files, which appeared to be the issue with @steowens / #57455

thanm commented 1 year ago

@seankhliao Ah thanks, yes, now that I read a little more carefully that does indeed look like the underlying cause.

Klaus-Tockloth commented 1 year ago

May helpful ...

NOK (go version go1.19.4 windows/amd64):

C:\Users\ABCDEFG\go-dev\src\lssc>go build -o build/windows-amd64/lssc.exe
# develop.vwg/lssc
C:\Users\ABCDEFG\go1.19.4\go\pkg\tool\windows_amd64\link.exe: running gcc failed: exit status 1
c:/users/ABCDEFG/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ABCDEFG\AppData\Local\Temp\go-link-2746559253\000007.o: in function `_cgo_preinit_init':
\\_\_\runtime\cgo/gcc_libinit_windows.c:40: undefined reference to `__imp___iob_func'
c:/users/ABCDEFG/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ABCDEFG\AppData\Local\Temp\go-link-2746559253\000007.o: in function `x_cgo_notify_runtime_init_done':
\\_\_\runtime\cgo/gcc_libinit_windows.c:105: undefined reference to `__imp___iob_func'
c:/users/ABCDEFG/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ABCDEFG\AppData\Local\Temp\go-link-2746559253\000007.o: in function `_cgo_beginthread':
\\_\_\runtime\cgo/gcc_libinit_windows.c:149: undefined reference to `__imp___iob_func'
c:/users/ABCDEFG/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ABCDEFG\AppData\Local\Temp\go-link-2746559253\000008.o: in function `x_cgo_thread_start':
\\_\_\runtime\cgo/gcc_util.c:18: undefined reference to `__imp___iob_func'
collect2.exe: error: ld returned 1 exit status

C:\Users\ABCDEFG\go-dev\src\lssc>go version
go version go1.19.4 windows/amd64

OK (go1.20rc1 windows/amd64):

C:\Users\ABCDEFG\go-dev\src\lssc>go build -o build/windows-amd64/lssc.exe

C:\Users\ABCDEFG\go-dev\src\lssc>go version
go version go1.20rc1 windows/amd64
YOU54F commented 1 year ago

Hello @thanm and all.

I can confirm that I have the same issue as the OP with 1.19.4 and @Klaus-Tockloth,

and resolved with go1.20rc1

This is my example file https://github.com/YOU54F/hello_ffi/blob/main/go/helloFfi.go

I am just going through my examples and getting them working on windows.

note, my system deps were

choco install --yes golang mingw

Screenshot 2023-01-02 164936

This page was useful for me in working out how to install the release candidate

go install golang.org/dl/go1.20rc1@latest
go1.20rc1 download
thanm commented 1 year ago

Thanks. I am going to go ahead and close out this issue.

binarytrails commented 1 year ago

as a hot fix to keep working in the meantime this worked:

go install golang.org/dl/go1.20rc1@latest
go1.20rc1 download
go1.20rc1 get .
go1.20rc1 build .
go1.20rc1 run ....
AMDG2 commented 1 year ago

I was reaching the same issue, and it got fixed with go 1.20 too. But I have now new related error, the linker cannot find __mingw_vfprintf symbol. I'm not sure if I should open new issue for it or not.

You can reproduce it with the following files:

golib/go.mod ``` module example.com/test_module go 1.20 ```
golib/lib.go ``` package main import "C" import ( "fmt" ) //export SayHello func SayHello(name *C.char) { fmt.Println("Hello", name) } func main() {} ```
build.ps1 ``` # This requires MSVC, go, tdm-gcc and clang in PATH. Set-PSDebug -Trace 1 rm golib.lib rm golib.h rm main.d rm main.o rm main.obj # Build the go static library # Commented out, so the header changes don't get overriden. cd golib $env:GODEBUG="cgocheck=2" go version go build -buildmode=c-archive -o ../golib.lib . cd .. # Patch the header, otherwise both MSVC and Clang complains about the complex types. Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern '#include ' -NotMatch) Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Fcomplex GoComplex64;' -NotMatch) Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Dcomplex GoComplex128;' -NotMatch) # Build the C++ executable with MSVC # =========================================== # Generate object file. cl.exe /c /std:c++20 /Wall /WX /MP /MD /EHsc main.cpp # Link link.exe main.obj golib.lib /out:main-msvc.exe # Build the C++ executable with Clang # =========================================== # Generate object file. clang.exe --version clang.exe -std=c++20 -Weverything -Werror -MP -MD -Xclang --dependent-lib=msvcrt -Wno-reserved-identifier -Wno-c++98-compat-pedantic -c main.cpp # Link lld-link.exe --version lld-link.exe main.o golib.lib /out:main-clang.exe Set-PSDebug -Trace 0 ```
main.cpp ``` #include "golib.h" int main(const int, char* argv[]) { SayHello(argv[1]); return 0; } ```

Invoking build.ps1 on my machine results in the following output:

`build.ps1` output ``` DEBUG: 4+ >>>> rm golib.lib DEBUG: 5+ >>>> rm golib.h DEBUG: 6+ >>>> rm main.d DEBUG: 7+ >>>> rm main.o DEBUG: 8+ >>>> rm main.obj DEBUG: 12+ >>>> cd golib DEBUG: 13+ >>>> $env:GODEBUG="cgocheck=2" DEBUG: 14+ >>>> go version go version go1.20rc2 windows/amd64 DEBUG: 15+ >>>> go build -buildmode=c-archive -o ../golib.lib . DEBUG: 16+ >>>> cd .. DEBUG: 19+ >>>> Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern '#include ' -NotMatch) DEBUG: 20+ >>>> Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Fcomplex GoComplex64;' -NotMatch) DEBUG: 21+ >>>> Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Dcomplex GoComplex128;' -NotMatch) DEBUG: 26+ >>>> cl.exe /c /std:c++20 /Wall /WX /MP /MD /EHsc main.cpp Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31933 for x64 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp DEBUG: 28+ >>>> link.exe main.obj golib.lib /out:main-msvc.exe Microsoft (R) Incremental Linker Version 14.34.31933.0 Copyright (C) Microsoft Corporation. All rights reserved. golib.lib(000005.o) : error LNK2019: unresolved external symbol __mingw_vfprintf referenced in function fprintf golib.lib(000006.o) : error LNK2001: unresolved external symbol __mingw_vfprintf main-msvc.exe : fatal error LNK1120: 1 unresolved externals DEBUG: 33+ >>>> clang.exe --version clang version 15.0.3 Target: x86_64-pc-windows-msvc Thread model: posix InstalledDir: C:\Corona\tmp\conan-windows\.conan\data\llvm\15.0.3\legion\20221108\package\cc04f447872ac4d8c0f858193dd82ce97bad89bf\bin DEBUG: 34+ >>>> clang.exe -std=c++20 -Weverything -Werror -MP -MD -Xclang --dependent-lib=msvcrt -Wno-reserved-identifier -Wno-c++98-compat-pedantic -c main.cpp DEBUG: 36+ >>>> lld-link.exe --version LLD 15.0.3 DEBUG: 37+ >>>> lld-link.exe main.o golib.lib /out:main-clang.exe lld-link: error: undefined symbol: __mingw_vfprintf >>> referenced by golib.lib(000005.o):(.text) >>> referenced by golib.lib(000006.o):(.text) DEBUG: 39+ >>>> Set-PSDebug -Trace 0 ```

Please let me know if you need more information, or if I should open new issue.

thanm commented 1 year ago

@AMDG2

Your compile/link recipe doesn't look right. In general for C++ programs it is not a viable strategy to invoke the linker directly -- one needs to invoke the C++ driver during the link stage, and then the C++ driver will run the linker passing the right flags and libraries.

Here is an example (linux machine):

thanm@cetina:~$ cat himom.cpp
#include <iostream>
int main(int argc, char **argv) {
  std::cout << "hi mom\n";
  return 0;
}
$ clang++ -c himom.cpp
$ ld.lld -o himom.exe himom.o 
ld.lld: error: undefined symbol: std::cout
ld.lld: error: undefined symbol: std::basic_ostream<char, std::char_traits<char> >& std::operator<<<std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)
ld.lld: error: undefined symbol: std::ios_base::Init::Init()
...
$ clang++ -o himom.exe himom.o
$ ./himom.exe
hi mom

Try running the last command above with "-v" and you can see all of the various libraries being passed to the linker by the driver.

Also want to add that the use of MSVC (e.g. cl.exe, link.exe) is something that is not supported/test by the Go team at the moment; I would recommend instead sticking with mingw-based compilers and linkers.

AMDG2 commented 1 year ago

@thanm Thank you for the quick reply! I tried to make it simpler, but you are right, we usually link through the compiler.

I changed my build script for this repro to build and link with the compiler in one step, and I also added building with GCC (I also fixed the Go code, so it actually prints the string instead of the address, but it does not matter).

new build.ps1 ``` # This requires MSVC, go, tdm-gcc and clang in PATH. Set-PSDebug -Trace 1 # Build the go static library # Commented out, so the header changes don't get overriden. cd golib $env:GODEBUG="cgocheck=2" go version go build -buildmode=c-archive -o ../golib.lib . cd .. # Patch the header, otherwise both MSVC and Clang complains about the complex types. Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern '#include ' -NotMatch) Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Fcomplex GoComplex64;' -NotMatch) Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Dcomplex GoComplex128;' -NotMatch) # Build the C++ executable with MSVC # =========================================== # Generate object file. cl.exe /MP /MD /EHsc main.cpp /link golib.lib /out:main-msvc.exe if ($?) { ./main-msvc.exe "MSVC" } # Build the C++ executable with Clang # =========================================== # Generate object file. clang-cl.exe --version clang-cl.exe /MP /MD /EHsc main.cpp /link golib.lib /out:main-clang.exe if ($?) { ./main-clang.exe "Clang" } # Build the C++ executable with GCC # =========================================== # Generate object file. g++.exe --version g++.exe main.cpp -lgolib -L. -o main-gcc.exe if ($?) { ./main-gcc.exe "GCC" } Set-PSDebug -Trace 0 ```

I get the following output:

build.ps1 output ``` DEBUG: 6+ >>>> cd golib DEBUG: 7+ >>>> $env:GODEBUG="cgocheck=2" DEBUG: 8+ >>>> go version go version go1.20rc2 windows/amd64 DEBUG: 9+ >>>> go build -buildmode=c-archive -o ../golib.lib . DEBUG: 10+ >>>> cd .. DEBUG: 13+ >>>> Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern '#include ' -NotMatch) DEBUG: 14+ >>>> Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Fcomplex GoComplex64;' -NotMatch) DEBUG: 15+ >>>> Set-Content -Path "golib.h" -Value (get-content -Path "golib.h" | Select-String -Pattern 'typedef _Dcomplex GoComplex128;' -NotMatch) DEBUG: 20+ >>>> cl.exe /MP /MD /EHsc main.cpp /link golib.lib /out:main-msvc.exe Microsoft (R) C/C++ Optimizing Compiler Version 19.34.31933 for x64 Copyright (C) Microsoft Corporation. All rights reserved. main.cpp Microsoft (R) Incremental Linker Version 14.34.31933.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:main.exe golib.lib /out:main-msvc.exe main.obj golib.lib(000005.o) : error LNK2019: unresolved external symbol __mingw_vfprintf referenced in function fprintf golib.lib(000006.o) : error LNK2001: unresolved external symbol __mingw_vfprintf main-msvc.exe : fatal error LNK1120: 1 unresolved externals DEBUG: 21+ if ( >>>> $?) { ./main-msvc.exe "MSVC" } DEBUG: 26+ >>>> clang-cl.exe --version clang version 15.0.3 Target: x86_64-pc-windows-msvc Thread model: posix InstalledDir: C:\Corona\tmp\conan-windows\.conan\data\llvm\15.0.3\legion\20221108\package\cc04f447872ac4d8c0f858193dd82ce97bad89bf\bin DEBUG: 27+ >>>> clang-cl.exe /MP /MD /EHsc main.cpp /link golib.lib /out:main-clang.exe clang-cl: warning: argument unused during compilation: '/MP' [-Wunused-command-line-argument] golib.lib(000005.o) : error LNK2019: unresolved external symbol __mingw_vfprintf referenced in function fprintf golib.lib(000006.o) : error LNK2001: unresolved external symbol __mingw_vfprintf main-clang.exe : fatal error LNK1120: 1 unresolved externals clang-cl: error: linker command failed with exit code 1120 (use -v to see invocation) DEBUG: 28+ if ( >>>> $?) { ./main-clang.exe "Clang" } DEBUG: 33+ >>>> g++.exe --version g++.exe (tdm64-1) 10.3.0 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. DEBUG: 34+ >>>> g++.exe main.cpp -lgolib -L. -o main-gcc.exe DEBUG: 35+ if ( >>>> $?) { ./main-gcc.exe "GCC" } DEBUG: 35+ if ($?) { >>>> ./main-gcc.exe "GCC" } Hello GCC DEBUG: 37+ >>>> Set-PSDebug -Trace 0 ```

So, it still does not work with MSVC and Clang, but it works with GCC as one would expect. Is there any plan to extend the support to at least Clang & LLVM toolchain, if not MSVC?

thanm commented 1 year ago

@AMDG2 you are using clang-cl.exe, which is the MSVC-compatible version of clang. Please use a mingw-based version of clang (such as https://github.com/mstorsjo/llvm-mingw)