其實cmake 本質也是生成makefile,我之前編譯過muduo庫,遇到一個問題,見git的issue
https://github.com/chenshuo/muduo/issues/470
在描述一下當時的問題,當時已經從官網上下載了boost的庫
./b2
./b2 install
但是依然出現了
/tmp/ccLjGYKC.o:在函數‘__static_initialization_and_destruction_0(int, int)’中:
main.cc:(.text+0x30):對‘boost::unit_test::unit_test_log_t::instance()’未定義的引用
collect2: error: ld returned 1 exit status
其實這時候我們可以用一些方法來很容易和輕鬆的解決這個問題,一般出現連接庫文件失敗,或者沒有找到庫,我認爲都可以這麼做,這麼做會讓我們很容易排查到錯誤
1.一個關鍵點善用 --verbose
就是在cc gcc g++的時候我們可以看到連接器的查找路徑,我們可以使用這些方法
gcc -print-search-dirs
gcc Wl,--verbose
ld -lpthread --verbose
你使用這些方式都可以很輕鬆的幫助你在編譯的時候排查問題,它可以打印出這個連接器的查找路徑,我就是用這種方法找到了編譯失敗的原因,是因爲有兩個相同名字的.so庫,之前的問題是因爲查找到另一個庫裏了,但是這個方式真的很好用,它可以打印出庫的查找路徑。
因爲gcc 在編譯的時候進行連接的連接器正是/usr/bin/ld,在思考一下我們如何以最簡單的方式來確認是否在編譯的時候能找到庫進行準確的鏈接操作呢?
hanglei@zhanglei-virtual-machine:~$ gcc -lpthread
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
或者
ld -lpthread
2.使用ldconfig可以解決編譯時缺少庫的問題嗎?
我認爲是很遺憾的說不能,爲什麼呢因爲我試了很多次,我認爲就是不能的,因爲gcc --verbose的運行結果告訴我不能
描述一下我的實驗現象:
vim /etc/ld.so.conf.d/xxx.conf
也添加了我自定義的查找路徑
/home/zhanglei/ourc/xxx/bin.lnx/x64
sudo ldconfig,然後發現庫已經確實加載了(當然我們之前沒有把庫放到系統級目錄下面,而是放到了自己指定的任意目錄下),我使用ldconfig -p 確實生效了
zhanglei@zhanglei-virtual-machine:~$ sudo ldconfig -p|grep iter
libsciter-gtk.so (libc6,x86-64) => /home/zhanglei/ourc/xxx/bin.lnx/x64/libxxxx.so
zhanglei@zhanglei-virtual-machine:~$
但是在編譯的時候路徑查找真的是不盡人意
==================================================
/usr/bin/ld:模式 elf_x86_64
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o 成功
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o 成功
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o 成功
/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libpthread.so 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libpthread.a 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpthread.so 成功
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libpthread.so
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a 成功
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so 成功
打開腳本文件 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
打開腳本文件 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
試圖打開 libgcc_s.so.1 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so.1 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1 成功
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a 成功
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libc.so 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libc.a 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so 成功
打開腳本文件 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
打開腳本文件 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
試圖打開 /lib/x86_64-linux-gnu/libc.so.6 成功
/lib/x86_64-linux-gnu/libc.so.6
試圖打開 /usr/lib/x86_64-linux-gnu/libc_nonshared.a 成功
/usr/lib/x86_64-linux-gnu/libc_nonshared.a
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
試圖打開 /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 成功
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/usr/lib/x86_64-linux-gnu/libc_nonshared.a
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a 成功
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so 成功
打開腳本文件 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
打開腳本文件 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
試圖打開 libgcc_s.so.1 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so.1 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1 成功
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so 失敗
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a 成功
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o 成功
/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
試圖打開 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o 成功
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
ld-linux-x86-64.so.2 needed by /lib/x86_64-linux-gnu/libc.so.6
found ld-linux-x86-64.so.2 at /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
/usr/bin/ld: 找到鏈結錯誤,刪除可運行文件 a.out
collect2: error: ld returned 1 exit status
zhanglei@zhanglei-virtual-machine:~$
我們發現在編譯的時候根本沒有去查找我們的路徑,當然我們可以在gcc -L 的時候去定義庫的路徑,這個路徑會被優先查找
我們man ldconfig 後看描述,有一行重要的描述
NAME
ldconfig - configure dynamic linker run-time bindings
就是說ldconfig 是 解析的 動態運行庫的鏈接,是運行時庫,參考地址:
https://www.cnblogs.com/qinfengxiaoyue/archive/2012/05/27/2519703.html
linux:
dlopen
windows:
windows下調用動態庫的方法:
1 隱式加載:即在程序中包含lib文件和.h文件,隱式鏈接有時稱爲靜態加載或加載時動態鏈接。例如:
#include "somedll.h"
#pragma comment( lib, "somedll.lib")
然後就可以直接調用此dll中的函數,注意運行時仍然需要somedll.dll。
2 顯示加載:使用loadlibrary,GetProcAddress,FreeLibrary,不需要.h文件和.lib文件,但是要知道函數的原型。顯式鏈接有時稱爲動態加載或運行時動態鏈接。
但是如果我們使用
ln -s xxxx /usr/lib/libxxx.so
這樣之後卻可以很容易解決上面的問題