其实cmake 本质也是生成makefile,我之前编译过muduo库,遇到一个问题,见git的issue

https://github.com/chenshuo/muduo/issues/470

在描述一下当时的问题,当时已经从官网上下载了boost的库

./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 后看描述,有一行重要的描述

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

这样之后却可以很容易解决上面的问题

/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 编译c++项目的候报错 /usr/bin/ld: demo: hidden symbol `__cpu_indicator_init’ in /usr/lib/gcc/x86_64-linux-gnu/5/libgcc.a(cpuinfo.o) is referenced by DSO /usr/bin/ld: final link failed: Bad value collect2: error: ld returned 1 exit status CMakeFiles/demo.dir/build. 如果我们打开维基百科的 链接器 页,我们将会看到如下定义: 在计算机科学中,链接器(英文:Linker),是一个计算机程序,它将一个或多个由编译器生成的目标文件链接为一个单独的可执行文件,库文件或者另外一个目标文件 如果你曾经用 C 写过至少一个程序,那你就已经见过以 *.o 扩展名结尾的文件了。这些文件是目标文件。目标文件是一块块的机器码和数据,其数据包含了引用其他目标文件或库的数据和函 /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libz.a(gzlib.o): relocation R_X86_64_32S against `.rodata' can not be used when making a sh... http://0123.blog.163.com/blog/static/47883120101024104416786/编译出现/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.4.5/../../../libz.so when searching for -lz错误 ============================================ PLATFORM_VERSION_CODENAME=AOSP Linux下编译程序的候,出现/usr/bin/ld: cannot find -lxxx的错误,主要的原因是找不到相应的动态库,库文件没有导入到ld检索目录中。常见的链接不到动态库的错误信息如下:…动态库的名称就是-l后面的名称,如-lpng,就是png动态库。... 1.预处理,生成.i的文件[预处理器cpp] 2.将预处理后的文件不转换成汇编语言,生成文件.s[编译器egcs] 3.有汇编变为目标代码(机器代码)生成.o的文件[汇编器as] 4.连接目标代码,生成可执行程序[链接器ld] [参数详解]