modern-go / reflect2

reflect api without runtime reflect.Value cost
Apache License 2.0
758 stars 73 forks source link

undefined reference to `reflect.unsafe_New' #21

Open eat-swap opened 3 years ago

eat-swap commented 3 years ago

Hello! I have tried to compile my own project which has a dependency of "reflect2" package with the most recent gccgo but failed with a message of "undefined reference". Is it possible to make it compile using gccgo?

Details shown below:

What version of "reflect2" is used to compile?

The most recent commit (commit 333559e1834b0c1840d283d79220bf121d704022).

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

go version go1.16.3 gccgo (GCC) 11.0.1 20210423 (prerelease) linux/amd64

Additionally, gccgo --version tells:

gccgo (GCC) 11.0.1 20210423 (prerelease)
Copyright (C) 2021 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.

What operating system and processor architecture are you using?

$ cat /etc/issue
Arch Linux \r (\l)
$ uname -a
Linux 5.11.16-arch1-1 #1 SMP PREEMPT Wed, 21 Apr 2021 17:22:13 +0000 x86_64 GNU/Linux

What did you do?

Trying to build some code that depends on this package.

What is expected to see?

The code successfully compiles.

What you see instead?

/usr/bin/ld: /home/lam/.cache/go-build/fd/fd4891df5167b3e9b000124e5b53c9fccc0f3aa55647fda5583b97f1c087b5d9-d(_go_.o): in function `github_0com_1modern_x2dgo_1reflect2.UnsafeSliceType.UnsafeMakeSlice':
/home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_slice.go:78: undefined reference to `reflect.unsafe_NewArray'
/usr/bin/ld: /home/lam/.cache/go-build/fd/fd4891df5167b3e9b000124e5b53c9fccc0f3aa55647fda5583b97f1c087b5d9-d(_go_.o): in function `github_0com_1modern_x2dgo_1reflect2.unsafeType.UnsafeNew':
/home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_type.go:48: undefined reference to `reflect.unsafe_New'
/usr/bin/ld: /home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_type.go:48: undefined reference to `reflect.unsafe_New'
/usr/bin/ld: /home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_type.go:48: undefined reference to `reflect.unsafe_New'
/usr/bin/ld: /home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_type.go:48: undefined reference to `reflect.unsafe_New'
/usr/bin/ld: /home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_type.go:48: undefined reference to `reflect.unsafe_New'
/usr/bin/ld: /home/lam/.cache/go-build/fd/fd4891df5167b3e9b000124e5b53c9fccc0f3aa55647fda5583b97f1c087b5d9-d(_go_.o):/home/lam/go/pkg/mod/github.com/modern-go/reflect2@v1.0.1/unsafe_type.go:48: more undefined references to `reflect.unsafe_New' follow
collect2: error: ld returned 1 exit status

Thanks for your patient and effort.

mymedia2 commented 3 years ago

For some reason, in GCC 11 reflect.unsafe_New function was renamed to reflect.unsafe__New with two underscore. Compare:

mymedia@freesia:~$ nm -D --defined-only /usr/lib/gcc/x86_64-linux-gnu/10/libgo.so | grep 'unsafe_*New'
0000000000f05d00 T internal..z2freflectlite.unsafe_New
0000000000f05cc0 T reflect.unsafe_New
0000000000f03150 T reflect.unsafe_NewArray
mymedia@freesia:~$ nm -D --defined-only /usr/lib/gcc/x86_64-linux-gnu/11/libgo.so | grep 'unsafe_*New'
000000000100c920 T internal_1reflectlite.unsafe__New
000000000100c8e0 T reflect.unsafe__New
000000000100ca30 T reflect.unsafe__NewArray
nganhkhoa commented 2 years ago

I can verify this, and unfortunately, the problem only happens in gccgo or gollvm. Both are using a different port of libgo in gofrontend.

The mainstream go compiler: https://github.com/golang/go/blob/41b9d8c75e45636a153c2a31d117196a22a7fc6c/src/runtime/malloc.go#L1201

The libgo port for gccgo and gollvm: https://github.com/golang/gofrontend/blob/f5bc28a30b7503015bbef38afb5812313184e822/libgo/go/runtime/malloc.go#L1295

It is not clear how to fix this issue. Because go doesn't have a quick check over the defined/undefined symbols.

For people building gccgo or gollvm: It is best to make a copy of these functions and make both verions available unsafe_ and unsafe__.

For people using a distributed version of gccgo or gollvm: Fix the library call in unsafe_link.go into using unsafe__.

A related issue, if you use https://github.com/ugorji/go, fix codec/helper_unsafe.go as above.