同事问了一个FFmpeg编译错误问题,几乎100%复现:
1. Windows msys + mingw工具链环境
2. 编译动态库
报错信息:
以这个问题为例,我们看下编译错误如何分析。
首先可以看到
1. 错误出现在avformat链接过程
2. 报的错误是一个符号找不到
分析编译错误,一定要搞清楚错误出现在哪个阶段:预处理阶段、编译阶段、还是链接阶段。
找不到的符号是哪里实现的呢?我们可以搜下代码。这里做个提示,avformat依赖avcodec,去avcodec里搜索,可以缩小范围。或者ctags clangd工具找定义,直接定位到。
avpriv_split_xiph_headers定义在avcodec/xiph.c中。avpriv前缀含义是给FFmpeg内其他库使用的函数,不是给用户用的。
接下来我们看下libavcodec/Makefile。xiph.o是始终编译链接到avcodec的,不受config影响。其他的这些编解码器会受config enable disable的影响,disable时不编译。
可以看看dll lib文件,确实没有avpriv_split_xiph_headers。
问题变得奇怪了,为什么一个avcodec始终编译的object,avformat会找不到它的定义呢?
没有眉目的时候,我们可以看下编译过程:
1. rm libavcodec/avcodec*
2. make -n libavcodec/avcodec.dll
我们先rm删除一些target,方便测试。再执行make -n,用dryrun观察dll生成过程。
可以看到,生成dll前,先用compat下的makedef工具,生成了一个.def文件。这个.def是一个导出符号列表,只有在这个列表中的符号才会导出。最终生成的dll少了一个符号,是因为这个符号不在def文件中。
接下来看看makedef的实现,其基本步骤可概括如下:
1. 先用所有.o object文件生成一个静态lib文件
2. 用nm -g –defined-only foo.lib列出所有的外部可见符号
3. 根据libavcodec下的规则文件,筛选出所有av_和avpriv_前缀的符号,这就是写入def文件的符号列表。
好了,我们可以手动执行nm
nm -g libavcodev/xiph.o,发现没那个符号。
再用nm libavcodec/xiph.o试试,发现找到了,并且符号类型为T,代表是外部可见函数符号!
nm工具出问题了,-g显示的函数符号不全。
抱着侥幸心理,试试其他nm工具。which -a nm
/mingw64/bin/nm
/usr/bin/nm
/bin/nm
现在用的是mingw64的nm,我们可以试试第二个。结果显示,/usr/bin/nm正常!
我又查看了一下两个nm工具的版本号,版本是一样的。但因为未知原因,导致了mingw版本nm -g丢符号。
我的分析到此为止,不打算再往下追了。感兴趣的同学可以继续往下查。
解决方案简单,换下nm即可,具体怎么做留给读者思考。
作者:quink
来源:Fun With FFmpeg
原文:https://mp.weixin.qq.com/s/yapxIpalzRbZvt4FRtsn_Q
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。