其实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
这样之后却可以很容易解决上面的问题