-
Notifications
You must be signed in to change notification settings - Fork 18.4k
Description
What version of Go are you using (go version
)?
$ go version go version go1.15.7 linux/amd64
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 GOARCH="amd64" GOHOSTOS="linux"
What did you do?
Enable link time optimization CFLAGS when building a Go program containing an //export
directive.
package main
import "fmt"
import "C"
//export add
func add(x int32, y int32) int32 {
return x + y
}
func main() {
fmt.Println(add(1,1))
}
The above program builds normally using go build
without additional CFLAGS. However, building with CGO_CFLAGS='-flto -ffat-lto-objects' go build
produces the following error.
_cgo_export.c:21:13: error: variable ‘_cgoexp_c166a99bca60_add’ redeclared as function
cgo-generated-wrappers:1:5: note: previously declared here
lto1: fatal error: errors during merging of translation units
compilation terminated.
lto-wrapper: fatal error: /usr/bin/gcc returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
This is due to the same symbol name being used in separate contexts as both a function and an integer.
What did you expect to see?
Program builds when enabling link time optimization via CFLAGs.
What did you see instead?
Generated intermediate C code for //export
is incompatible with link time optimization.
Notes
Additional conflicting symbols may be created if the program binds the value of an exported function's C handle to a Go variable. The following program demonstrates the behavior.
package main
import "fmt"
// extern int add(int, int);
import "C"
//export add
func add(a int32, b int32) int32 {
return a + b
}
func main() {
fn := C.add
fmt.Printf("%v\n", fn)
}
When built with CGO_CFLAGS='-flto -ffat-lto-objects' go build
, the linker yields the following error.
cgo-generated-wrappers:1:13: error: function ‘add’ redeclared as variable
_cgo_export.c:24:9: note: previously declared here
_cgo_export.c:21:13: error: variable ‘_cgoexp_2526879f8d2a_add’ redeclared as function
cgo-generated-wrappers:4:5: note: previously declared here
lto1: fatal error: errors during merging of translation units
compilation terminated.
lto-wrapper: fatal error: /usr/bin/gcc returned 1 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
The interesting aspect to note is the redeclaration of the add
symbol in addition to the previously encountered _cgoexp*_add
symbol. This comes from introducing the assignment statement of C.add
to the variable fn
, and causes cgo to emit an additional pair of matching symbols with conflicting types via another code path.