AC_CHECK_LIB的工作原理

AC_CHECK_LIB就是告诉configure我们需要检查哪些lib,并根据检查结果做什么处理。正是在这里遇到了问题并有所收获,才促使我写这篇blog记录一下。

问题是这样,我想检查一下libXv.so这个库是否存在,不存在的话就让configure直接退出。你可能要问人家是so你为啥要在编译阶段检查一个动态库是否存在,答案是因为代码里静态链接了libXv.so里的某些function.

于是乎,我在configure.in里写了如下代码:

1 ....
2 AC_CHECK_LIB(Xv, XvGetVideo , [], [
3         echo "Error! You need to have libXv installed!"
4         exit -1
5         ])
6 ....
  • AC_CHECK_LIB的第一个参数是库名,我们这里依赖libXv,自然是填Xv。
  • 第二个参数是函数名,填的要么是你代码里真正reference到的function;如果你不知道或者懒得去查代码的话,用nm -D查看这个so,随便挑一个出来填上即可。
  • 第三个参数是如果check结果为yes,做什么操作。我想继续,所以啥也不填。
  • 第四个参数代表如果check结果为no,做什么处理。你也看到了——我打印一条报错信息,然后exit。

看上去没什么问题,我也由此生成了configure,但是在执行configure时却有了如下的报错:

1 checking for XvGetVideo in -lXv... no

没道理啊!我是用yum install libXv安装的Xv库呀,而且XvGetVideo 这个名字都是通过

1 nm -D /usr/lib64/libXv.so.1

得到的啊。

路径问题?不能啊,我/usr/lib和/usr/lib64下面都有libXv.so.1啊。虽然我确信我这个64bit的机器用的只会是/usr/lib64.

好在configure执行期间会输出config.log,这也顺便让我知道了AC_CHECK_LIB的工作原理。

打开config.log,找到下面出错的片段:

1 configure:4415: checking for XvGetVideo in -lXv
2 configure:4440: gcc -o conftest -g -O2   conftest.c -lXv >&5
3 /tmp/ccFbn6ak.o: In function `main':
4 /home/kongc/workspace/haohao/conftest.c:23: undefined reference to `XvGetVideo'
5 collect2: ld returned 1 exit status
6 configure:4440: $? = 1
7 configure: failed program was:
8 |
9 | /* Override any GCC internal prototype to avoid an error.
10 |    Use char because int might match the return type of a GCC
11 |    builtin and then its argument prototype would still apply.  */
12 | #ifdef __cplusplus
13 | extern "C"
14 | #endif
15 | char XvGetVideo ();
16 | int
17 | main ()
18 | {
19 | return XvGetVideo ();
20 |   ;
21 |   return 0;
22 | }
23 configure:4449: result: no

原来AC_CHECK_LIB这个宏是生成了一个.c程序,在里面调用我们指定的函数,再让gcc编译这个.c程序通过-l去link我们指定的库,如果link成功,则代表check通过。

而我们之所以没有通过check,log里也给出了原因:ld returned 1 exit status

ld哪里出错了呢?为了找到原因,我手动创建了这个test.c:

1 #ifdef __cplusplus
2 extern "C"
3 #endif
4 char XvGetVideo ();
5 int
6 main ()
7 {
8 return XvGetVideo ();
9   ;
10   return 0;
11 }

然后执行

1 gcc -g -O2 test.c -lXv

这下得到了ld失败的真正原因:

1 /usr/bin/ld: cannot find -lXv

路径问题??No,刚才已经否定了这个因素了。

软连接问题??No. 我ls看了,/usr/lib64/libXv.so.1 -> libXv.so.1.0.0 一点问题都没有,两个文件都好好的。

就连ldconfig -p也显示libXv被成功load了啊啊!

上下求索了好久,最终在stackoverflow找到了答案:
对于一个so来说,在程序执行时被动态link,这时link对象的名字叫做SONAME,对于一个so来说它的SONAME可以通过objdump看到:

1 $ objdump -p /usr/lib64/libXv.so.1 | grep SONAME
2   SONAME      libXv.so.1

这个SONAME的用途:是程序在执行时,在LD_LIBRARY_PATH下查找这个SONAME,找到对应的so文件,再进行动态绑定执行。这篇说绿色软件的文章依照的就是这个原理。
这也是为何我用yum安装libXv,/usr/lib和/usr/lib64下面各被安置了一个libXv.so.1的原因。

所以你也看到了,我一直在说执行和动态链接。显然调用gcc时并不是在执行,也不是在动态链接。对于ld来说,-l{libname} 这个参数只会让ld去系统库目录,也就是/usr/lib或/usr/lib64下以及通过-L指定的目录下去找lib{libname}.so这个文件,然后静态链接。如果找不到就会报usr/bin/ld: cannot find -lxxxxxd 的错误!而我的/usr/lib64/和/usr/lib下面都是没有libXv.so这个文件的。

所以解决办法很简单,创建一个/usr/lib64/libXv.so 的软连接指向/usr/lib64/libXv.so.1即可。

上面那个stackoverflow的帖子里同时也提供了另一个解决方案,那就是安装对应库的devel包。对于libXv来说,就是安装libXv-devel。装好后的效果其实是一样:

1 $ yum install libXv-devel
2 ls -la /usr/lib64/libXv.so
3 lrwxrwxrwx 1 root root 14 09-25 13:45 /usr/lib64/libXv.so -> libXv.so.1.0.0

虽然有点杀鸡用牛刀的感觉,但也很好解释了devel阶段的link跟使用时的link的区别——说白了就是对于so来说,静态链接和动态链接时使用的名字不一样。静态链接使用libxxxx.so,动态连接使用SONAME。

总结

说的东一句西一句貌似没有什么主题,但这次折腾让我明白了:

  1. AC_CHECK_LIB的工作原理
  2. 对于一个so来说ld时使用的名字和执行时被动态绑定时,使用的名字是不一样的
  3. 对于一个技术问题,80%中文搜索结果都是重复且无用的(况且我用的还是google)
  4. 对于技术问题,更快得到更好答案的方式可能是search in stackoverflow rather than in google. 当然,case by case:)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434026.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac json格式化工具_一个在 MAC 上 iOS/Flutter 开发的辅助工具

大家好,我是章鱼猫。今天给大家推荐的这个开源项目,是来自于我们公众号读者的投稿,这个东西还挺好的。如果你作为读者,也有自己的开源项目或者你也有想推荐的开源项目,都可以向我们投稿,我们就是致力于帮助…

php 开启fsockopen函数,巧用php的fsockopen函数

这几天闲着没事,用PHP的fsockopen写了几个文件为我的酷我音乐盒的帐户加分。获得途径 积分音乐盒完整的听一首歌曲 1(每天最高200)音乐坊成功上传一张歌单 50(每天最高200)酷我音乐空间空间被访问1次 1(每天最高50)有人打招呼1次 2(每天最高50)有人留言(非主人) 5(每…

java中多维数组的clone容易引起误解

int[][] arr1 new int[][]{{1,2},{1,2}}; int[][] arr2 arr1.clone(); 因为arr1!arr2所以我的意图是 修改arr2 在确定修改结束后 将arr2赋给arr1依此保证在arr2修改过程中arr1不变,,,但神奇的是竟然变了后来才注意到虽然arr1!arr2但arr1[0]…

python编写界面遍历_python和pywin32实现窗口查找、遍历和点击的示例代码

Pywin32是一个Python库,为python提供访问Windows API的扩展,提供了齐全的windows常量、接口、线程以及COM机制等等。1.通过类名和标题查找窗口句柄,并获得窗口位置和大小import win32guiimport win32apiclassname "MozillaWindowClass&…

termcap-1.3.1的configure.in文件逐行分析

AC_INIT(termcap.h) 每个configure文件第一个需要调用的宏,他处理所有的命令行参数并且寻找源代码目录。termcap.h是包含在源代码目录下的文件,configure在目录中检查这些文件是否存在以确定该目录是否包含源代码。 AC_ARG_ENABLE(install-termcap, [ …

php转换图片属性a,PHP 提取图片img标记中的任意属性

/* PHP正则提取图片img标记中的任意属性 */$str PHP正则提取或更改图片img标记中的任意属性;//1、取整个图片代码preg_match(/]*?src\s*\s*(\|\")(.*?)\\1[^>]*?\/?\s*>/i,$str,$match);echo $match[0];//2、取width属性preg_match(//i,$str,$match);echo $mat…

OOP三言两语

OOP面向对象编程,主要特点:封装、继承、多态,一切即对象。 多态:编译时多态-- 方法重载 (方法名称相同,签名不同)。 运行时多态--子类override 父类的(vitural、abstract&#xff09…

交叉编译termcap1.3.1

修改Makefile文件其中两行即可 CC gcc 改为 CC arm-linux-gcc AR ar 改为 AR arm-linux-ar 编译后生成libtermcap.a文件,将其拷贝到交叉工具链的lib文件夹下即可使用。

python实现数字时钟_Python 写的全屏数字时钟软件,看看还有什么改进的地方

zgzb:软件启动图: https://s1.ax1x.com/2020/09/25/096RzV.png链接: https://www.lanzoux.com/i2vCzgwo0xawjj5728:啥都不说,先瞎为敬。黑色字看不到呀rglee:这配色绝了galileo1214:这全屏有啥用…

php ajax无刷新分页源码,ajax实现无刷新分页(php)

投票结果function GetXmlHttpObject(){var xmlHttpnull;try{// Firefox, Opera 8.0, SafarixmlHttpnew XMLHttpRequest();}catch (e){// Internet Explorertry{xmlHttpnew ActiveXObject("Msxml2.XMLHTTP");}catch (e){xmlHttpnew ActiveXObject("Microsoft.XML…

SQL嵌套语句执行顺序

首先我们要了解一下SQL语句的执行过程。 SELECT 字段 FROM 表名 WHERE 条件表达式 那它们是按什么顺序执行呢?分析器会先看语句的第一个词,当它发现第一个词是SELECT关键字的时候,它会跳到FROM关键字,然后通过FROM关键字找到表名并…

fatal error: Python.h: No such file or directory

ubuntu下编译libxml2时,报错. 执行apt-get install python-dev即可

php 计划任务 不执行,CentOS 系统下 Laravel 计划任务 PHP artisan schedule:run 不执行,应该如何处理?...

服务器是centos系统,现在遇到一个很奇怪的问题,计划任务不能执行,本来设的是定时检查用户表,给当天过生日的用户发生日祝福短信,日志记录计划任务执行了,但没有短信发送,laravel日志中也没有记录…

(转)Win7下如何硬盘安装Ubuntu

1.下载Linux镜像及EasyBCD   以Ubuntu为例:http://www.ubuntu.com/desktop/get-ubuntu/download  系统引导软件EasyBCD:http://neosmart.net/EasyBCD/  2.设置NeoGrub启动项   1)ubuntu下载文件放在C:\ubuntu-10.10-desktop-i386.iso&…

编译libxml2-2.6.26 __open_missing_mode 错误

调用open函数,因为使用open函数的时候,如果在第二个参数中使用了 O_CREAT,就必须添加第三个参数:创建文件时赋予的初始权。 解决方案:在调用open函数的那一行的参数里加个“0666”或者“0777”均可! 如&…

卡巴斯基授权许可文件_制片方未提供电视台授权证明,构成根本违约吗?

在制作娱乐法101课程的过程中,需要检索很多案例,有时候也也看到一些似乎不太合理的判决书。在一起电视播映权纠纷中,合同中一般会常规约定制作方需要向电视台提交确保其在合同授权区域、授权范围、授权期限内具有合法播映权的证明文件的合同义…

月头月尾oracle取数,Oracle分析函数Over()的使用

今天为完成客户成品仓盘点的统计功能,做了盘点统计表,这个功能有点复杂,要将生产数据与库存的差异做成一个统计报表,报表要反映出差异的明细。其实,这个项目拖了也挺久了,本来客户计划用于2018年终盘点&…

一个快递小伙子带给我们的启示:认真有力量

今天加班一天,合肥漫天飞雪,出门就开始下,到了公司,这个世界全白了,看到了这篇文章,贴出来于大家共享!认真有力量,大家认真努力工作哈! 他是个快递小子,20岁出…

Win32 API串口编程

在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信。串口通信方便易行,应用广泛。 一般情况下,工控机和各智能仪表通过RS485总线进行通信。RS485的通信方式是半双工的,只能由…

python安装vtk_python - 安装VTK for Python - SO中文参考 - www.soinside.com

最简单的方法第一个也是最简单的方法是使用Aptitude Package Manager安装软件包:sudo apt-get install libvtk5-dev python-vtk如果你想要最新版本如果你想要最新版本的VTK,你也可以自己构建它:确保安装了CMake:sudo apt-get inst…