cmd/cgo: cgo + static const int results in "undefined reference" on linux

a6b3iqyw  于 2个月前  发布在  Go
关注(0)|答案(6)|浏览(31)

你正在使用的Go版本是什么( go version )?

$ go version
go version go1.14.7 linux/amd64

这个问题在最新版本中是否重现?

尚未尝试

你正在使用什么操作系统和处理器架构( go env )?

go env 输出

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build954734301=/tmp/go-build -gno-record-gcc-switches"
root@06ba4e8d3414:/go/src/bitbucket.org/threattrack/vipre-mac/foo#

你做了什么?

链接一个引用了 static const int 的程序,但在 undefined reference 上失败:
foo.h

static const int BAR = 1;

foo.go

package main

/*
#include "foo.h"
*/
import "C"
import "fmt"

const (
  BAR = int(C.BAR)
)

func main() {
  fmt.Println(BAR)
}

你期望看到什么?

linux上编译成功,就像在darwin上一样

你看到了什么?

go build
/usr/bin/ld: $WORK/b001/_cgo_main.o:/tmp/go-build/cgo-generated-wrappers:2: undefined reference to `BAR'
collect2: error: ld returned 1 exit status
prdp8dxp

prdp8dxp1#

这似乎在1.10.8上起作用,但从1.11开始停止工作。
cc @ianlancetaylor

uqjltbpv

uqjltbpv2#

static 在 C 语言中表示它属于其编译单元。可以认为 C 和 Go 是不同的编译单元(我们确实分别对它们进行编译)。

zqdjd7g9

zqdjd7g93#

在这种情况下,推荐的方法是什么来保持Go常量与其C对应项同步 - 除了重新定义它们,这将是一个维护噩梦?
这段代码在darwin上编译和运行没有问题。

v7pvogib

v7pvogib4#

我认为这也在 #39136 中提到了。一个区别是 GCC 为 BAR 生成了一个 DW_AT_location ,而 clang 生成了一个 DW_AT_const_value 。另一个区别是当编译这段代码时:

static const int BAR = 1;
enum { V = (BAR) * 1 };

clang 在没有错误的情况下编译了代码,但 GCC 报告了

foo.c:2:8: error: enumerator value for ‘V’ is not an integer constant

我不确定为什么在这种情况下 clang 不会产生错误。clang 对于 C++ 的行为似乎是正确的,但对于 C 不是这样。
请注意,使用 #define 应该对这两个编译器都有效。

ih99xse1

ih99xse15#

我找到了破坏它的提交,da76981

0yg35tkg

0yg35tkg6#

已经过去3年了,有什么消息吗?

相关问题