使用GCCGO构建Golang模块的方法与实践

使用GCCGO构建Golang模块的方法与实践 我希望能够使用gccgo构建模块,但无法成功。我使用的是Go 1.13.7和gccgo-9。

给定一个非常简单的模块,包含两个文件:

// go.mod

module github.com/paleozogt/helloworld

go 1.12

// helloworld.go

package main
import "fmt"
import "runtime"
func main() {
    fmt.Println("hello world from " + runtime.Version() + " " + " " + runtime.GOOS + " " + runtime.GOARCH)
}

并按如下方式编译

export GCCGO=gccgo-9
go build -compiler=gccgo -gccgoflags -static

编译失败,错误信息为:

# github.com/paleozogt/helloworld
/tmp/go-build070129611/b001/_gomod_.go:3:3: error: __debug_modinfo__ is not a function; //go:linkname is only supported for functions
    3 | //go:linkname __debug_modinfo__ runtime.modinfo
      |   ^

如果不使用gccgo,则可以正常工作。或者,如果使用gccgo但删除go.mod文件,上述命令也能工作。所以,我似乎只能选择构建模块或使用gccgo,但不能同时进行。这是怎么回事?


更多关于使用GCCGO构建Golang模块的方法与实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

使用 go 1.14rc1 版本同样存在问题,不过错误信息变更为:

# github.com/paleozogt/helloworld
/usr/bin/ld: $WORK/b001/_pkg_.a(_go_.o): in function `main.main..init0':
/tmp/go-build/b001/_gomod_.go:5: undefined reference to `runtime.setmodinfo'
collect2: error: ld returned 1 exit status

更多关于使用GCCGO构建Golang模块的方法与实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我意识到我的问题了。我一直在使用标准的 go 工具(由 gc 构建)。我需要使用的是 gccgo-go(由 gccgo 构建)。

现在我可以执行:

go build -gccgoflags -static
./helloworld
hello world from go1.12.2 gccgo (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008
linux amd64

由于我使用的是 gccgo-go,它自动关联到 gccgo,因此无需定义 GCCGO 环境变量(除非我们要进行交叉编译)。

这是一个已知的GCCGO与Go模块的兼容性问题。GCCGO对Go模块的支持不完整,特别是在处理模块的调试信息时存在问题。

问题出现在__debug_modinfo__符号的处理上。当使用Go模块时,编译器会生成包含模块信息的特殊代码,但GCCGO的链接器实现与标准Go工具链不完全兼容。

解决方案是使用特定的编译标志来禁用模块调试信息:

export GCCGO=gccgo-9
go build -compiler=gccgo -gccgoflags "-static -fgo-debug-modinfo=none"

或者,如果你需要保留其他调试信息但只禁用模块信息:

export GCCGO=gccgo-9
go build -compiler=gccgo -gccgoflags "-static -g -fgo-debug-modinfo=none"

另一个方法是使用GOFLAGS环境变量:

export GCCGO=gccgo-9
export GOFLAGS="-gccgoflags=-fgo-debug-modinfo=none"
go build -compiler=gccgo -gccgoflags "-static"

如果上述方法仍然失败,可以尝试完全禁用调试信息:

export GCCGO=gccgo-9
go build -compiler=gccgo -gccgoflags "-static -g0"

对于你的示例代码,这个修改后的构建命令应该可以工作:

// 构建命令
export GCCGO=gccgo-9
go build -compiler=gccgo -gccgoflags "-static -fgo-debug-modinfo=none"

// 运行验证
./helloworld

输出应该类似于:

hello world from go1.13.7 gccgo linux amd64

注意:GCCGO与标准Go工具链在模块支持方面存在差异。如果遇到其他模块相关问题,可能需要考虑使用vendor目录或调整模块配置:

// go.mod 可以尝试添加replace指令
module github.com/paleozogt/helloworld

go 1.12

replace github.com/paleozogt/helloworld => ./

或者使用更传统的GOPATH模式配合GCCGO:

export GO111MODULE=off
export GCCGO=gccgo-9
go build -compiler=gccgo -gccgoflags "-static"

GCCGO对Go模块的完整支持仍在开发中,建议关注GCC和Go项目的更新日志以获取更好的兼容性支持。

回到顶部