今天遇到一個CMake 鏈接問題,這里提出來和大家分享:
問題:
自己用C語言寫了一個動態(tài):libword-counter.so鬓催,公開頭文件word-counter.h, 其中有函數(shù)如:wc_get_word_freq()
自己用C++語言寫了一個測試工程,在main函數(shù)中調(diào)用上述庫函數(shù)wc_get_word_freq蹲嚣。
結(jié)果出現(xiàn)undefined reference to 的錯誤
分析:
1. 根據(jù)Cmake的編譯log徘意,可以看出該錯誤是在linking target的時候出現(xiàn)的,因此build是OK的
2. 如果修改頭文件為其他文件介时,則出現(xiàn)找不到文件的錯誤,因此說明頭文件可以正常找到凌彬。也在次說明1中build是沒問題的
3. 編譯選項我已經(jīng)指明了需要加載的庫 -lword-counter
4. 如果修改3中的庫名沸柔,則出現(xiàn)找不到so的錯誤,說明3中編譯選項是沒問題的铲敛,系統(tǒng)能找到這個庫so
5. 現(xiàn)在出現(xiàn)問題“undefined reference to 的錯誤”褐澎,太詭異了?
6. 本人一直堅信伐蒋,計算機(jī)不會出現(xiàn)靈異事件工三,因此不斷請教度娘
7. 發(fā)現(xiàn)有人建議我用nm命令查看so的符號表迁酸,看看這個函數(shù)是否正常,于是nm -D 庫文件俭正,查看了下奸鬓,結(jié)果函數(shù)正常的。
8. 最后想到C++調(diào)用C存在混編問題掸读,有人建議編譯選項加上 -lstdc++串远,結(jié)果還是不行
9. 最終沿著混編問題走下去,我找到了原因寺枉,需要在庫文件的頭文件中加上下面的語句抑淫,用以指定,在編譯C++的時候被調(diào)用的代碼仍然使用C編譯選項姥闪。
#ifdef __cplusplus
extern "C"
{
#endif
問題解決,希望遇到問題的小伙伴能看到砌烁,少走彎路~~
補(bǔ)充:
今天又遇到一個類似問題筐喳,找不到函數(shù)聲明,extern c沒問題函喉,最終利用步驟7避归,發(fā)現(xiàn)so中沒有符號表。
root cause:函數(shù)沒有export出去
#ifndef EXPORT_API
#define EXPORT_API __attribute__((visibility("default")))
#endif
EXPORT_API
int get_download_info()
{
}
還有一種可能是-lXXX的位置以及庫之間的依賴順序:
原來編譯命令不能這樣:
gcc -lXXXX -o test test.o
要改成:
gcc -o test test.o -lXXXX
這樣就沒錯了管呵。