首页 > 其他分享 >Go构建遇到cgo动态库时解决方案

Go构建遇到cgo动态库时解决方案

时间:2023-03-07 18:33:05浏览次数:53  
标签:r0 cgo musl glibc 37 库时 Installing Go alpine

1. 问题

  1. golang构建程序很简单,当遇到需要调用c库时,如通常使用 net,kafka, sqlite3 程序运行时就会调用当前服务器的 动态库,如果遇到没有库时,通常还需要 下载比如 alpine需要安装sqlite

     apk add --no-cache sqlite-libs sqlite-dev
    
  2. 通常我们构建时使用CGO_ENABLED=1 就能在构建时将代码需要调用C库用动态连接的形势供代码调用

     CGO_ENABLED=1 go build -ldflags "-s -w" -o perception_node ./cmd/
    

  3. 但是这里面会有个问题,如果将编译好的 二进制文件移植到其他服务器,但是服务器上面的动态库版本又和构建时的动态库版本不一样, 或者动态库的路径不一样。可能有想到,升级c库,或降低版本。但是一旦升级或降级C库,很可能导致服务器上原来的服务受影响。


2. 解决

如何解决:

  1. 使用 golang 的 kafka 库:开发人员需要更改代码以切换使用的 kafka sdk。这可以作为替代方案。
  2. 降低 golang:latest 的 glibc 版本:发行版通常修复 glibc 以编译其他工具链,替换 glibc 是不明智的。虽然有这样的工具yum downgrade glibc*可以帮助解决这个问题。
  3. 更改为旧的 glibc 映像:同样,您无法避免一堆旧的 bash 脚本。
  4. 静态链接 c 依赖项

综上所述,使用最新的镜像来编译,但是会依赖所有的静态链接,这样一编译完成后就不用担心c库兼容的问题, 如果使用 glibc,则它不是静态可链接的。

因为 glibc 依赖于支持不同提供程序的 libnss,所以它必须动态链接。

  1. 所以这里替换glibc的唯一方法就是使用musl。librdkafka和 golang 包confluent-kafka-go都支持 musl 构建(构建时指定 –tags musl 即可) alpine 是基于 musl 的发行版,所以这里可以直接用 alpine Linux 构建。

  2. 然后指定外部 ld-staticfor 标志,编译后的二进制文件将完全静态链接。编译过程如下。

    $  docker run -it -v $(pwd):/workspace  golang:1.18-alpine
    /go $ cd /workspace/
    /workspace $ sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories && \
    >     apk add git openssh make build-base alpine-sdk
    fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
    fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
    (1/37) Installing fakeroot (1.25.3-r3)
    (2/37) Installing openssl (1.1.1l-r0)
    (3/37) Installing libattr (2.5.1-r0)
    (4/37) Installing attr (2.5.1-r0)
    (5/37) Installing libacl (2.2.53-r0)
    (6/37) Installing tar (1.34-r0)
    (7/37) Installing pkgconf (1.7.4-r0)
    ...
    $ export GOPROXY="https://goproxy.cn"
    /workspace $ go build -ldflags "-linkmode external -extldflags '-static'" -tags musl -o  perception_node ./cmd/
    /workspace $ ldd  perception_node
    /lib/ld-musl-x86_64.so.1: spex: Not a valid dynamic program
    
  3. windows下使用如下指令

    $ docker run -it -v $(pwd):/workspace  golang:1.18-alpine
    /go $ cd /workspace/
    /workspace $ sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories 
    $ apk add openssh make build-base alpine-sdk mingw-w64-gcc musl-dev gcc build-base
    fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
    fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
    (1/37) Installing fakeroot (1.25.3-r3)
    (2/37) Installing openssl (1.1.1l-r0)
    (3/37) Installing libattr (2.5.1-r0)
    (4/37) Installing attr (2.5.1-r0)
    (5/37) Installing libacl (2.2.53-r0)
    (6/37) Installing tar (1.34-r0)
    (7/37) Installing pkgconf (1.7.4-r0)
    ...
    $ export GOPROXY="https://goproxy.cn"
    $ CGO_ENABLED=1 GOOS=windows CC=x86_64-w64-mingw32-gcc go build -ldflags "-linkmode external -extldflags '-static'"  -tags musl -o seduce_node_agent.exe main.go
    

参考

1.golang动态链接库问题

标签:r0,cgo,musl,glibc,37,库时,Installing,Go,alpine
From: https://www.cnblogs.com/failymao/p/17189120.html

相关文章

  • postgis之ST_MakePolygon
    ST_MakePolygon(geom1)geom1一个GEOMETRY数据类型的值,或一个计算结果为GEOMETRY类型的表达式。子类型必须是LINESTRING。linestring值必须是闭合的或为空。参考......
  • windows下使用nginx + waitress 部署django
    虽然不喜欢IIS,不过有些项目又必须部署在windows上,windows下部署django的方案有IIS+wfastcgi,apache+mod_wsgi,也有超简单的部署方式如:nginx+waitress,本文主要讲的是最......
  • Django项目部署到云端后静态资源无法加载
    1.Django项目在开发阶段一直都是在本地调试,开发的差不多了得部署到云端,然后整个项目打包到云端运行后访问,发现静态资源无法加载。之前seeting.py里面的配置如下:STATIC_UR......
  • percona-server-mongodb-6.0源码安装
    ###################################请注意,预构建的二进制文件可在 mongodb.org上获得,这可能是最简单的入门方式,而不是从源代码构建。要构建MongoDB,您需要:能够编译......
  • django框架
    目录django1、django推导流程2、django介绍及基本使用3、django目录结构、app概念和三板斧的初步介绍4、django静态文件、form表单和request对象5、django连接数......
  • go pprof 性能分析工具
    安装 graphvizyuminstallgraphviz 开始采集:gotoolpprofhttp://192.168.100.100:1000/debug/pprof/heap输出svg文件,web可以查看#gotoolpprofhttp://1......
  • MongoDB找出冗余和未被使用的索引
    找出冗余的索引varldb=db.adminCommand({listDatabases:1});for(i=0;i<ldb.databases.length;i++){if(ldb.databases[i].name!='admin'&&......
  • 谷歌google安装vue插件
    链接:https://github.com/vuejs/devtools默认是main分支,需要切换到add-remote-dev,然后点击下载压缩包zip,解压到某位置解压之后管理员运行cmd命令提示符窗口,cdD:**......
  • GO的学习(3)
    GO的学习(3)指针定义指针,从字面意义上理解就是一个指向的过程。由于变量的创建赋值本质上是在操控内存空间,当新建一个变量并且赋值的时候,内存会创造出一块空间来存放这个......
  • vba 其他循环语句 (goto语句等…)
    (1)Gotoline该语句为跳转到line语句行(2)Onexpressiongosubdestinatioinlist或者onexpressiongotodestinationlist语句为根据exprssion表达式值来跳转到所要的行......