[已解决]Golang静态库问题(CGO_ENABLED=0失效的解决方案)

[已解决]Golang静态库问题(CGO_ENABLED=0失效的解决方案) 大家好

首先,如果这是一个简单的配置问题或类似情况,我表示抱歉,我是一名初学者开发者。

我需要帮助,因为我无法使用静态库。 我编译了我的代码,并在另一台计算机上(显然没有安装Go)执行二进制文件,但我遇到了一个错误:“加载共享库时出错:libgo.so.14:无法打开共享对象文件:没有那个文件或目录” 因此,在谷歌上进行了一些搜索后,我发现需要将 CGO_ENABLED 环境变量更改为“0”以切换到静态库,但这对我无效。

我的 go env:

>> [jordan@jmaster] {11:52:47}  ~$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jordan/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/jordan/go"
GOPROXY=""
GORACE=""
GOROOT="/usr"
GOTMPDIR=""
GOTOOLDIR="/usr/libexec/gcc/x86_64-redhat-linux/9"
GCCGO="/usr/bin/gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
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-build185346707=/tmp/go-build -gno-record-gcc-switches -funwind-tables"

我的 go 版本:

>> [jordan@jmaster] {11:53:16}  ~$ go version
go version go1.12.2 gccgo (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1) linux/amd64

当我编译我的代码时:

>> [jordan@jmaster] {11:56:23}  /var/opt/development/golang/test$ ls
main.go
>> [jordan@jmaster] {11:56:24}  /var/opt/development/golang/test$ go build -a -o app
>> [jordan@jmaster] {11:56:31}  /var/opt/development/golang/test$ ldd app
        linux-vdso.so.1 (0x00007ffdcfdca000)
        libgo.so.14 => /lib64/libgo.so.14 (0x00007f599cef2000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f599cdac000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f599cd92000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f599cbcc000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f599e5f5000)

我期望的结果:

对 app 执行 ldd 返回“不是动态可执行文件”

感谢帮助。


更多关于[已解决]Golang静态库问题(CGO_ENABLED=0失效的解决方案)的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

经过无数次尝试,终于解决了……

Fedora 最新的 Go 版本是 1.12.2。 我刚刚移除了那个 yum 版本,并安装了 Go 官网上的 tar.gz 最新版本 (v1.13.3)。 嗒哒…… 成功了…… 😄

>> [jordan@jmaster] {21:06:55}  /var/opt/development/golang/save$ go version
go version go1.13.3 linux/amd64
>> [jordan@jmaster] {21:07:00}  /var/opt/development/golang/save$ ls
main.go
>> [jordan@jmaster] {21:07:06}  /var/opt/development/golang/save$ go build -a -o app
>> [jordan@jmaster] {21:07:18}  /var/opt/development/golang/save$ ldd app
    not a dynamic executable

更多关于[已解决]Golang静态库问题(CGO_ENABLED=0失效的解决方案)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


根据你的描述,问题在于你使用的是 gccgo 编译器,而不是标准的 Go 编译器。gccgo 默认会生成动态链接的二进制文件,即使设置了 CGO_ENABLED=0。要生成完全静态的二进制文件,你需要使用标准的 Go 编译器(gc)或者为 gccgo 指定额外的链接选项。

解决方案

方案一:使用标准 Go 编译器(推荐)

首先,确保你安装的是标准的 Go 编译器,而不是 gccgo。你可以从 Go 官网 下载并安装。安装后,使用 go version 确认输出不包含 gccgo

$ go version
go version go1.12.2 linux/amd64  # 标准编译器

然后,设置 CGO_ENABLED=0 并重新编译:

$ CGO_ENABLED=0 go build -a -o app main.go
$ ldd app
不是动态可执行文件  # 期望的输出

方案二:使用 gccgo 并指定静态链接

如果你必须使用 gccgo,可以通过传递 -static 标志给链接器来生成静态二进制文件:

$ go build -gccgoflags '-static' -o app main.go
$ ldd app
不是动态可执行文件

或者,你也可以在编译时直接使用 gccgo 命令:

$ gccgo -static -o app main.go
$ ldd app
不是动态可执行文件

示例代码

假设你的 main.go 内容如下:

package main

import "fmt"

func main() {
    fmt.Println("Hello, static binary!")
}

使用标准 Go 编译器编译:

CGO_ENABLED=0 go build -a -o app main.go

使用 gccgo 编译:

go build -gccgoflags '-static' -o app main.go

验证

编译后,使用 file 命令验证二进制文件是否为静态链接:

$ file app
app: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=..., not stripped

使用 ldd 命令确认没有动态依赖:

$ ldd app
不是动态可执行文件

这样,你就可以在没有安装 Go 或其他依赖的机器上运行这个二进制文件了。

回到顶部