生活随笔
收集整理的這篇文章主要介紹了
AC_CHECK_LIB的工作原理
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
AC_CHECK_LIB就是告訴configure我們需要檢查哪些lib,并根據(jù)檢查結(jié)果做什么處理。正是在這里遇到了問題并有所收獲,才促使我寫這篇blog記錄一下。
問題是這樣,我想檢查一下libXv.so這個(gè)庫是否存在,不存在的話就讓configure直接退出。你可能要問人家是so你為啥要在編譯階段檢查一個(gè)動(dòng)態(tài)庫是否存在,答案是因?yàn)榇a里靜態(tài)鏈接了libXv.so里的某些function.
于是乎,我在configure.in里寫了如下代碼:
| 2 | AC_CHECK_LIB(Xv, XvGetVideo , [], [ |
| 3 | ????????echo "Error! You need to have libXv installed!" |
- AC_CHECK_LIB的第一個(gè)參數(shù)是庫名,我們這里依賴libXv,自然是填Xv。
- 第二個(gè)參數(shù)是函數(shù)名,填的要么是你代碼里真正reference到的function;如果你不知道或者懶得去查代碼的話,用nm -D查看這個(gè)so,隨便挑一個(gè)出來填上即可。
- 第三個(gè)參數(shù)是如果check結(jié)果為yes,做什么操作。我想繼續(xù),所以啥也不填。
- 第四個(gè)參數(shù)代表如果check結(jié)果為no,做什么處理。你也看到了——我打印一條報(bào)錯(cuò)信息,然后exit。
看上去沒什么問題,我也由此生成了configure,但是在執(zhí)行configure時(shí)卻有了如下的報(bào)錯(cuò):
| 1 | checking for XvGetVideo in -lXv... no |
沒道理啊!我是用yum install libXv安裝的Xv庫呀,而且XvGetVideo 這個(gè)名字都是通過
| 1 | nm -D /usr/lib64/libXv.so.1 |
得到的啊。
路徑問題?不能啊,我/usr/lib和/usr/lib64下面都有l(wèi)ibXv.so.1啊。雖然我確信我這個(gè)64bit的機(jī)器用的只會(huì)是/usr/lib64.
好在configure執(zhí)行期間會(huì)輸出config.log,這也順便讓我知道了AC_CHECK_LIB的工作原理。
打開config.log,找到下面出錯(cuò)的片段:
| 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 |
| 7 | configure: failed program was: |
| 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.? */ |
| 19 | | return XvGetVideo (); |
| 23 | configure:4449: result: no |
原來AC_CHECK_LIB這個(gè)宏是生成了一個(gè).c程序,在里面調(diào)用我們指定的函數(shù),再讓gcc編譯這個(gè).c程序通過-l去link我們指定的庫,如果link成功,則代表check通過。
而我們之所以沒有通過check,log里也給出了原因:ld returned 1 exit status
ld哪里出錯(cuò)了呢?為了找到原因,我手動(dòng)創(chuàng)建了這個(gè)test.c:
然后執(zhí)行
這下得到了ld失敗的真正原因:
| 1 | /usr/bin/ld: cannot find -lXv |
路徑問題??No,剛才已經(jīng)否定了這個(gè)因素了。
軟連接問題??No. 我ls看了,/usr/lib64/libXv.so.1 -> libXv.so.1.0.0?一點(diǎn)問題都沒有,兩個(gè)文件都好好的。
就連ldconfig -p也顯示libXv被成功load了啊啊!
上下求索了好久,最終在stackoverflow找到了答案:
對(duì)于一個(gè)so來說,在程序執(zhí)行時(shí)被動(dòng)態(tài)link,這時(shí)link對(duì)象的名字叫做SONAME,對(duì)于一個(gè)so來說它的SONAME可以通過objdump看到:
| 1 | $ objdump -p /usr/lib64/libXv.so.1 |?grep?SONAME |
| 2 | ??SONAME????? libXv.so.1 |
這個(gè)SONAME的用途:是程序在執(zhí)行時(shí),在LD_LIBRARY_PATH下查找這個(gè)SONAME,找到對(duì)應(yīng)的so文件,再進(jìn)行動(dòng)態(tài)綁定執(zhí)行。這篇說綠色軟件的文章依照的就是這個(gè)原理。
這也是為何我用yum安裝libXv,/usr/lib和/usr/lib64下面各被安置了一個(gè)libXv.so.1的原因。
所以你也看到了,我一直在說執(zhí)行和動(dòng)態(tài)鏈接。顯然調(diào)用gcc時(shí)并不是在執(zhí)行,也不是在動(dòng)態(tài)鏈接。對(duì)于ld來說,-l{libname} 這個(gè)參數(shù)只會(huì)讓ld去系統(tǒng)庫目錄,也就是/usr/lib或/usr/lib64下以及通過-L指定的目錄下去找lib{libname}.so這個(gè)文件,然后靜態(tài)鏈接。如果找不到就會(huì)報(bào)usr/bin/ld: cannot find -lxxxxxd 的錯(cuò)誤!而我的/usr/lib64/和/usr/lib下面都是沒有l(wèi)ibXv.so這個(gè)文件的。
所以解決辦法很簡單,創(chuàng)建一個(gè)/usr/lib64/libXv.so 的軟連接指向/usr/lib64/libXv.so.1即可。
上面那個(gè)stackoverflow的帖子里同時(shí)也提供了另一個(gè)解決方案,那就是安裝對(duì)應(yīng)庫的devel包。對(duì)于libXv來說,就是安裝libXv-devel。裝好后的效果其實(shí)是一樣:
| 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 |
雖然有點(diǎn)殺雞用牛刀的感覺,但也很好解釋了devel階段的link跟使用時(shí)的link的區(qū)別——說白了就是對(duì)于so來說,靜態(tài)鏈接和動(dòng)態(tài)鏈接時(shí)使用的名字不一樣。靜態(tài)鏈接使用libxxxx.so,動(dòng)態(tài)連接使用SONAME。
總結(jié)
說的東一句西一句貌似沒有什么主題,但這次折騰讓我明白了:
AC_CHECK_LIB的工作原理對(duì)于一個(gè)so來說ld時(shí)使用的名字和執(zhí)行時(shí)被動(dòng)態(tài)綁定時(shí),使用的名字是不一樣的對(duì)于一個(gè)技術(shù)問題,80%中文搜索結(jié)果都是重復(fù)且無用的(況且我用的還是google)對(duì)于技術(shù)問題,更快得到更好答案的方式可能是search in?stackoverflow rather than in google. 當(dāng)然,case by case:)
總結(jié)
以上是生活随笔為你收集整理的AC_CHECK_LIB的工作原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。