当前位置: 首页 > news >正文

golang静态编译及编译失败排查步骤

文章目录

    • 一、背景
      • 前提
    • 二、静态编译概述
      • 1、执行静态编译
        • 设置CGO_ENABLED方式
        • 指定link方式
      • 2、编译报错分析
        • (1)确认系统上有没有安装libopus
        • (2)设置LD_LIBRARY_PATH
    • 三、详细排查过程
      • 1、下载bpf排查工具bcc, bcc-tools,python-bcc
      • 2、使用opensnoop 排查编译过程查找共享库的路径都有哪些
      • 3、pacman下载opus包
      • 4、查看当前的libopus.so文件的版本
      • 5、下载libopus.a
      • 6、.deb文件解压缩
      • 7、添加LD_LIBRARY_PATH
      • 8、添加LIBRARY_PATH为当前目录
      • 9、LD_LIBRARY_PATH和LIBRARY_PATH的区别

一、背景

      一个简单的音视频解析go程序需要放到一台没有go环境的机器中去运行,都是linux环境,本来以为是可以无缝迁移的。但实际上却发现运行报错,glibc版本不一致。。。

      因此打算直接编一个纯静态的可执行程序,依赖库都直接编译进去,这样就可以做到真正的无视平台限制。谁知道静态编译直接报错,好吧,那就总结一下静态编译相关知识点,并记录一下排查流程吧

前提

博主使用的是manjaro版本的linux,目标服务器是ubuntu版本且版本比较老。

二、静态编译概述

      go默认是使用静态编译的方式,如果go代码中使用的库不依赖C库的话。不过复杂点的go程序使用的包大概率是依赖系统C库的,所以编译出来的文件是动态的,例如可以通过ldd命令查看可执行程序以来的.so文件。

ldd 可执行程序linux-vdso.so.1 (0x00007ffeeaee7000)libresolv.so.2 => /usr/lib/libresolv.so.2 (0x00007ff3838a6000)libc.so.6 => /usr/lib/libc.so.6 (0x00007ff3836bf000)/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007ff3838d3000)

具体为什么会动态编译,原理可以参考:

【go可执行文件的外部依赖】

1、执行静态编译

静态编译有两种方式

设置CGO_ENABLED方式

      默认情况下,goruntime环境变量CGO_ENABLED=1,即默认开始cgo,允许你在go代码中调用C代码,gopre-compiled标准库的.a文件也是在这种情况下编译出来的。
我们可以在命令行指定CGO_ENABLED=0就可以静态编译

CGO_ENABLED=0 go build .

指定link方式

      go默认是使用internal linking,而无需启动外部external linker(如:gcc、clang等)。而external linking机制则是cmd/link将所有生成的.o都打到一个.o文件中,再将其交给外部的链接器,比如gccclang去做最终链接处理。

我们想要静态编译的话,需要在 -ldflags 中指定linkmode参数为external,并且指定是静态链接。

-ldflags '-linkmode "external" -extldflags "-static"' 
忽略'-linkmode "external" ,只设置-extldflags 也是ok的

静态编译一个项目,编译命令:

go build -o myapp -ldflags '-w -s -extldflags "-static"'

编译报错

/usr/lib/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: cannot find -lopus: No such file or directory
collect2: error: ld returned 1 exit status   

2、编译报错分析

/usr/bin/ld 是 Linux 系统中的链接器(linker),用于将目标文件和库文件等链接起
来,生成最终的可执行文件或共享库。在大多数情况下,这个链接器已经默认设置
好,并且可以自动被编译器调用。而对于 Go 语言的静态编译过程,我们需要在编译命令中加入相应的选项,指定使用
外部链接模式和静态链接方式,并将必要的库文件链接到生成的二进制文件中。具体
来说,可以使用 -ldflags 选项传递参数给链接器,包括 -linkmode external 表示启用
外部链接模式、-extldflags "-static" 表示启用静态链接方式等。

看起来是没找到libopus,我们先确认本机上有没有安装libopus

(1)确认系统上有没有安装libopus

ldconfig -p | grep libopus

通过包管理器查询libopus

pacman -Ql opus | grep libopus
opus /usr/lib/libopus.so   
opus /usr/lib/libopus.so.0   
opus /usr/lib/libopus.so.0.8.0

(2)设置LD_LIBRARY_PATH

这个环境变量用于指定程序在运行时动态加载共享库(也称为动态链接库)时所要搜索的路径。当程序需要加载某个共享库时,它会按照以下顺序搜索路径:

程序中已经指定的库路径(如使用 -L 参数指定的路径)
LD_LIBRARY_PATH 中指定的路径
export LD_LIBRARY_PATH=/usr/lib:$LD_LIBRARY_PATH  

继续静态编译,还是寻找libopus失败。 ok,开始有点意思了,我们下面详细排查下。

三、详细排查过程

1、下载bpf排查工具bcc, bcc-tools,python-bcc

      需要指定版本的话,使用这个命令:

sudo /usr/bin/pip install -i https://pypi.org/simple bcc==0.27.0 

bcc是一种跨平台的工具集,可用于在Linux系统上进行动态追踪和探查。其中的opensnoop工具可以用于监视应用程序打开、读取或写入文件的系统调用,以了解系统中哪些文件被访问,以及它们是如何被访问的。主要监听open()、read()、write()等与文件操作相关的系统调用。

strace也能查看系统调用函数,这里使用opensnoop来进行排查。

2、使用opensnoop 排查编译过程查找共享库的路径都有哪些

# 开启一个窗口,输入这个命令
sudo opensnoop# 开启另一个窗口,进行编译
go build -o myapp -ldflags '-w -s -extldflags "-static -lm"'# 查看opensnoop的输出
结果发现编译过程中查找的是libopus.a文件,我们只有libopus.so文件

3、pacman下载opus包

# 查看安装opus都会安装什么东西
sudo pacman -Ql opus# 结果是没有.a文件

看来只能自己编译出来.a文件或者去其他包管理平台下载了。。。

4、查看当前的libopus.so文件的版本

# 查看.so的版本
sudo pacman -Qo /usr/lib/libopus.so
/usr/lib/libopus.so is owned by opus 1.3.1-3

5、下载libopus.a

https://ubuntu.pkgs.org/20.04/ubuntu-main-amd64/libopus-dev_1.3.1-0ubuntu1_amd64.deb.html

查询到ubuntu上的libopus包是带有libopus.a文件的。版本也能对得上,下载即可。

6、.deb文件解压缩

# 下载地址
https://www.cyberciti.biz/faq/how-to-extract-a-deb-file-without-opening-it-on-debian-or-ubuntu-linux/# 查看下载的.deb包
file libopus-dev_1.3.1-0ubuntu1_amd64.deb
libopus-dev_1.3.1-0ubuntu1_amd64.deb: Debian binary package (format 2.0), with control.tar.xz, data compression xz# 解压缩deb包
ar x libopus-dev_1.3.1-0ubuntu1_amd64.deb 
# 解压完毕后会出现几个文件,主要用到data.tar.gz包,这个是存放二进制文件的压缩包# 解压缩tar
tar -xvf data.tar.xz  # 可以发现libopus.a文件
./usr/lib/x86_64-linux-gnu/libopus.a

7、添加LD_LIBRARY_PATH

直接把libopus.a文件放到当前目录,并设置搜索共享库路径。

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH

执行编译依然报错,好像没有生效。

8、添加LIBRARY_PATH为当前目录

# 执行静态编译成功# 查看静态编译文件
file myapp
myapp: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=8afbe7cba97e5f860ac49cfb6692e5eb5ec18cd5, for GNU/Linux 4.4.0, stripped

9、LD_LIBRARY_PATH和LIBRARY_PATH的区别

      LD_LIBRARY_PATHLIBRARY_PATH 都是用于指定共享库搜索路径的环境变量,但有一些细微的区别。

LD_LIBRARY_PATH 主要用于控制程序运行时加载共享库的路径,
LIBRARY_PATH 则主要用于控制编译器在编译时寻找共享库的路径。

静态编译要链接的是.a文件,LD_LIBRARY_PATH主要是设置.so文件的搜索路径,所以就不生效

end

相关文章:

golang静态编译及编译失败排查步骤

文章目录 一、背景前提 二、静态编译概述1、执行静态编译设置CGO_ENABLED方式指定link方式 2、编译报错分析(1)确认系统上有没有安装libopus(2)设置LD_LIBRARY_PATH 三、详细排查过程1、下载bpf排查工具bcc, bcc-tools,python-bcc…...

2023年7月第4周大模型荟萃

2023年7月第4周大模型荟萃 2023.7.31版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、Cerebras推出全球最强AI超算 AI芯片初创公司Cerebras Systems和总部位于阿联酋的技术控股集团G42于7月20日宣布,携手打造一个由互联的超…...

Meta分析的选题与文献计量分析CiteSpace应用丨R语言Meta分析【数据清洗、精美作图、回归分析、诊断分析、不确定性及贝叶斯应用】

目录 ​专题一、Meta分析的选题与文献计量分析CiteSpace应用 专题二、Meta分析与R语言数据清洗及相关应用 专题三、R语言Meta分析与精美作图 专题四、R语言Meta回归分析 专题五、R语言Meta诊断分析与进阶 专题六、R语言Meta分析的不确定性及贝叶斯应用 专题七、深度拓展…...

vscode eslint配置

1. 全局安装 eslint npm install -g eslint 2. control shift p 输入 settings 打开设置进行配置 3. 添加配置 {"workbench.colorTheme": "One Dark Pro","eslint.debug": true,"eslint.execArgv": null,"eslint.alwaysShow…...

C++ 对象模型 C++ Object Model

C 对象模型 C Object Model 文章目录 C 对象模型 C Object ModelC语言的数据及函数C的类C对象模型 C语言的数据及函数 C语言中,数据和函数是分开声明的。 数据 typedef struct point2d {float x;float y; } Point2d;函数 打印Point2d的数值 void Point2d_print…...

leetcode做题笔记47

给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 思路一:回溯 int* Source NULL; int Source_Size 0;int** Result NULL; int* Retcolsizes NULL; int Result_Index 0;int* Path NULL; int Path_Index 0;bool* Used …...

Linux Day04

目录 一、文件压缩与解压命令 1.1 tar cvf 文件名 ---打包命令生成.tar 1.2 tar xvf 文件名 ----解开包 生成文件 1.3 gzip .tar 压缩 生成.tar.gz压缩包 1.4 gzip -d .tar.gz 解压成包 1.5 直接把压缩包解压成文件 tar zxf .tar.gz 二、Linux 系统上 C 程序的…...

上海亚商投顾:沪指冲高回落 两市成交重回万亿

上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 市场情绪 三大指数今日冲高回落,盘初一度集体涨超1%,随后涨幅明显回落,上证50午后一度翻…...

2023最新版本~十分钟零基础搭建EMQX服务器

购买服务器 已知服务器大厂商 1 阿里云 点击直接访问 2 华为云点击直接访问 3 腾讯云 点击直接访问 还是比较推荐大公司 不会跑路 这里我购买的是一年的华为云服务器(新用户 64一年) 镜像推荐乌班图18 登陆服务器(需要重置密码!!&…...

SpringBoot2.5.6整合Elasticsearch7.12.1

SpringBoot2.5.6整合Elasticsearch7.12.1 下面将通过SpringBoot整合Elasticseach,SpringBoot的版本是2.5.6,Elasticsearch的版本是7.12.1。 SpringBoot整合Elasticsearch主要有三种方式,一种是通过elasticsearch-rest-high-level-client&am…...

准大一信息安全/网络空间安全专业学习规划

如何规划? 学习需要一个良好的学习习惯,建议刚开始一定要精通一项程序语言,学习其他的就会一通百通。过程中是按步骤学习,绝不半途看见苹果丢了梨,一定要强迫自己抵制新鲜技术的诱惑。 网络安全其实是个广而深的领域…...

WEB:php_rce

背景知识 Linux命令 thinkPHPv5漏洞 题目 打开页面,页面显示为thinkphp v5的界面,可以判断框架为thinkPHP,可以去网上查找相关的漏洞 由题目可知,php rec是一个通过远程代码执行漏洞来攻击php程序的一种方式 因为不知道是php版…...

问题:idea启动项目错误提示【command line is too long. shorten command line】

问题:idea启动项目错误提示【command line is too long. shorten command line】 参考博客 问题描述 启动参数过长,启动项目,错误提示 原因分析 出现此问题的直接原因是:IDEA集成开发环境运行你的“源码”的时候&#xff08…...

xshell连接Windows中通过wsl安装的linux子系统-Ubuntu 22.04

xshell连接Windows中通过wsl安装的linux子系统-Ubuntu 22.04 一、安装linux子系统 1.1、 启动或关闭Windows功能-适用于Linux的Windows子系统 1.2 WSL 官方文档 使用 WSL 在 Windows 上安装 Linux //1-安装 WSL 命令 wsl --install//2-检查正在运行的 WSL 版本:…...

子域名收集工具OneForAll的安装与使用-Win

子域名收集工具OneForAll的安装与使用-Win OneForAll是一款功能强大的子域名收集工具 GitHub地址:https://github.com/shmilylty/OneForAll Gitee地址:https://gitee.com/shmilylty/OneForAll 安装 1、python环境准备 OneForAll基于Python 3.6.0开发和…...

报数游戏、

描述 有n人围成一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来的第几号的那位。。 输入 初始人数n 输出 最后一人的初始编号 输入样例 1 3 输出样例 1 2 输入样例 …...

规约模式:优雅设计与灵活应用

引言: 规约模式是软件开发中的重要设计原则,它们提供了一种优雅的、灵活的方式来构建高质量的系统。本文将通过实例演示规约模式的具体应用,带你了解这些原则的实战价值。 一、开放封闭原则 // 图形接口 public interface Shape {void dra…...

Ubuntu Server版 之 apache系列 安装、重启、开启,版本查看

安装之前首先要检测是否安装过 apt list --installed | grep tool tool:要检测的名称,如mysql、apache 、ngnix 等 安装 apache sudo apt install apache2 安装apache 默认是开启的 可以通过浏览器 检测一下 service apache stop # apache 停止服务…...

Redis学习路线(4)—— Redis实现项目缓存

一、什么是缓存 (一)概念:缓存就是数据交换的缓冲区(称为Cache),是存储数据的临时区域,一般读写性能较高。 (二)常见缓存: 浏览器缓存,服务器缓…...

【Unity造轮子】实现一个类csgo的武器轮盘功能

文章目录 前言素材导入开始1.放背景和中间的圆圈,调整合适的宽高和位置2.添加选择图像框3.添加一些武器道具选择4.书写脚本RadialMenuManager5.绑定脚本和对象6.运行效果,按tab键开启关闭轮盘7.优化添加显示选中的武器文本8.添加鼠标选中放大的效果9.添加…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...

AI,如何重构理解、匹配与决策?

AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...