日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

AC_CHECK_LIB的工作原理

發布時間:2023/12/10 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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。

總結

說的東一句西一句貌似沒有什么主題,但這次折騰讓我明白了:

  • AC_CHECK_LIB的工作原理
  • 對于一個so來說ld時使用的名字和執行時被動態綁定時,使用的名字是不一樣的
  • 對于一個技術問題,80%中文搜索結果都是重復且無用的(況且我用的還是google)
  • 對于技術問題,更快得到更好答案的方式可能是search in?stackoverflow rather than in google. 當然,case by case:)
  • 總結

    以上是生活随笔為你收集整理的AC_CHECK_LIB的工作原理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。