如何解决链接对抗静态 32 位 3rd 方库
我正在使用下面的标志
#cgo CFLAGS: -I.
#cgo LDFLAGS: -L. -lcluto
#include <malloc.h>
#include "cluto.h"
当我编译时
go build clutod.go
编译器失败并报错
/usr/bin/ld: pulando ../../../../gopkg/src/dawn/plugins/cluto/clutobot/libcluto.a incompatível ao pesquisar para -lcluto
/usr/bin/ld: não foi possível localizar -lcluto
collect2: error: ld returned 1 exit status
这意味着它发现 libcluto.a 不兼容,因为它是一个 32 位库,而我的系统正在编译转到 amd64 架构。
但是当我编译时
GOARCH=386 go build clutod.go
在定义 'import "C"' 的同一源文件中定义的方法被简单地忽略。
我用reflect检查过,该方法不存在:
Goose.New.Logf(5,"|methods|=%d",typ.NumMethod())
Goose.New.Logf(5,"type=%s.%s",typ.PkgPath(),typ.Name())
for j=0; j<typ.NumMethod(); j++ {
mt := typ.Method(j)
Goose.New.Logf(5,"%d: %s",j,mt.Name)
}
Goose.New.Logf(5,"*|methods|=%d",typPtr.NumMethod())
Goose.New.Logf(5,"*type=%s.%s",typPtr.PkgPath(),typPtr.Name())
for j=0; j<typPtr.NumMethod(); j++ {
mt := typPtr.Method(j)
Goose.New.Logf(5,"%d: *%s",mt.Name)
}
Goose.New.Logf(1,"Method not found: %s,Data: %#v",methodName,typ)
return nil,errors.New(fmt.Sprintf("Method not found: %s",methodName))
上面的代码产生以下输出:
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(296): |methods|=10
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(297): type=dawn/plugins/cluto/clutobot.ServiceT
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 0: CRLListenAddress
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 1: CertKit
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 2: GetConfig
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 3: GetHost
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 4: GetMasterConfig
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 5: HttpsClient
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 6: ListenAddress
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 7: PageNotFound
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 8: SavePending
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(300): 9: Stop
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(303): *|methods|=21
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(304): *type=.
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 0: *CRLListenAddress
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 1: *CertKit
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 2: *GetConfig
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 3: *GetHost
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 4: *GetId
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 5: *GetMasterConfig
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 6: *GetRest
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 7: *HttpsClient
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 8: *InitConn
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 9: *ListenAddress
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 10: *LoadClientCert
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 11: *LoadConfig
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 12: *NewCK
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 13: *NewSshClientConfig
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 14: *PageNotFound
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 15: *PingAt
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 16: *SavePending
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 17: *SetRest
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 18: *Start
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 19: *Stop
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(307): 20: *Version
2021/02/21 14:33:50 {stonelizard}[New.go]<New>(310): Method not found: VP_ClusterDirect,Data: &reflect.rtype{size:0x100,ptrdata:0x100,hash:0xcfbeab05,tflag:0x7,align:0x4,fieldAlign:0x4,kind:0x19,equal:(func(unsafe.Pointer,unsafe.Pointer) bool)(nil),gcdata:(*uint8)(0x86467d8),str:85076,ptrToThis:937664}
在我看来,当我设置 GOARCH=386 时,它会禁用 CGO,默默地忽略任何引用 C 符号的代码。
那么,如何将 Go 静态链接到 32 位 (.a) 库?
解决方法
我也在 Golang-nuts list 上问过这个问题,并从 Elias Naur 那里得到了解决方案:
"Go 在交叉编译时禁用 Cgo(GOARCH 与你的原生不同 GOARCH)。您可以使用 CGO_ENABLED=1 手动启用 Cgo。"
所以,解决方案是
CGO_ENABLED=1 GOARCH=386 go build clutod.go
之后,由于缺少标头,我遇到了一些编译错误,我解决了安装其 32 位版本的问题:
sudo apt-get install gcc-multilib
然后链接器抱怨未定义对 log 的引用(在 libm.a 中找到的数学对数函数)。 起初我以为这只是一个缺少的 32 位库。 但是后来我发现我的系统上安装了这个库。 所以我认为问题是如何显示链接器如何找到它。但没有工作。然后我找到了这个链接 linking 3rd party static libs in cgo library 并意识到我没有解析引用,因为包含它的库首先出现,然后我切换了位置并且它起作用了。 LDFLAGS 以这种方式结束:
#cgo LDFLAGS: -L/usr/lib32 -L . -lcluto -lm
因此,libcluto.a 中未定义的引用通过在 -lcluto 之后放置 -lm 得到解决。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。