折腾了一天编译、动态库的问题,整理一下(参考:https://blog.csdn.net/flyztek/article/details/73612469):
现有4个文件:
app.cc--应用程序
head.h--库头文件
source1.cc--库源文件1
source2.cc--库源文件2
其中,app.cc里包含了库的头文件,并用到了库里的方法:
// app.cc
#include "stdio.h"
#include "stdlib.h"
#include "head.h"
int main()
{
source1();
source2();
return 0;
}
库头文件head.h里是库源文件1 source1.cc、库源文件2 source2.cc里方法的声明:
// head.h
void source1();
void source2();
库源文件1 source1.cc里定义了source1()函数:
// source1.cc
#include "stdio.h"
#include "stdlib.h"
#include "head.h"
void source1()
{
printf("source1\n");
}
库源文件1 source1.cc里定义了source1()函数:
// source2.cc
#include "stdio.h"
#include "stdlib.h"
#include "head.h"
void source2()
{
printf("source2\n");
}
然后,重点来了!
想要应用程序正确执行,有三种方法:
一、直接编译3个源文件app.cc、source1.cc、source2.cc生成一个目标程序文件app
gcc app.cc source1.cc source2.cc -o app
然后执行app,可以正确执行
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2
二、编译库的2个源文件source1.cc、source2.cc为两个目标文件source1.o,source2.o:
zhan@virtualBox:~/home/test_lib$ gcc source1.cc -c
zhan@virtualBox:~/home/test_lib$ ls
app.cc head.h source1.cc source1.o source2.cc
zhan@virtualBox:~/home/test_lib$ gcc source2.cc -c
zhan@virtualBox:~/home/test_lib$ ls
app.cc head.h source1.cc source1.o source2.cc source2.o
然后用ar命令将source1.o、source2.o创建成静态库文件,这里有两种方案:
1、第一种是分别创建两个静态库文件 libsource1.a、libsource2.a,
zhan@virtualBox:~/home/test_lib$ ar -cr libsource1.a source1.o
zhan@virtualBox:~/home/test_lib$ ar -cr libsource2.a source2.o
zhan@virtualBox:~/home/test_lib$ ls
app.cc libsource1.a source1.cc source2.cc
head.h libsource2.a source1.o source2.o
然后链接两个静态库编译成应用app:
zhan@virtualBox:~/home/test_lib$ gcc app.cc -L. -lsource1 -lsource2 -o app
zhan@virtualBox:~/home/test_lib$ ls
app head.h libsource2.a source1.o source2.o
app.cc libsource1.a source1.cc source2.cc
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2
2、第二种是将两个目标文件source1.o,source2.o合并创建成一个静态库文件 libsource.a:
zhan@virtualBox:~/home/test_lib$ ar -cr libsource.a source1.o source2.o
zhan@virtualBox:~/home/test_lib$ ls
app.cc head.h libsource.a source1.cc source1.o source2.cc source2.o
zhan@virtualBox:~/home/test_lib$ gcc app.cc -L. -lsource -o app
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2
三、编译库的2个源文件source1.cc、source2.cc为一个动态库文件source.so:
zhan@virtualBox:~/home/test_lib$ gcc source1.cc source2.cc -fPIC -shared -o libsource.so
zhan@virtualBox:~/home/test_lib$ ls
app.cc head.h libsource.so source1.cc source2.cc
然后生成app,生成时链接库文件:
zhan@virtualBox:~/home/test_lib$ gcc app.cc -L. -lsource -o app
zhan@virtualBox:~/home/test_lib$ ls
app app.cc head.h libsource.so source1.cc source2.cc
执行生成的应用app:
zhan@virtualBox:~/home/test_lib$ ./app
./app: error while loading shared libraries: libsource.so: cannot open shared object file: No such file or directory
此时却报错了,ldd命令查看app应用的库链接情况:
zhan@virtualBox:~/home/test_lib$ ldd app
linux-vdso.so.1 => (0x00007ffd54b8a000)
libsource.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbe0a005000)
/lib64/ld-linux-x86-64.so.2 (0x0000557f1caba000)
发现找不到库文件,此时有多种解决方案:
1、将刚刚生成的libsource.so库复制到/usr/lib目录里,然后执行ldconfig命令,再运行程序app就可以了:
zhan@virtualBox:~/home/test_lib$ sudo cp libsource.so /usr/lib
zhan@virtualBox:~/home/test_lib$ ldd app
linux-vdso.so.1 => (0x00007ffc7c100000)
libsource.so => /usr/lib/libsource.so (0x00007fc1f5106000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc1f4d3d000)
/lib64/ld-linux-x86-64.so.2 (0x000055e2451c0000)
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2
2、将libsource.so库文件所在目录添加到/etc/ld.so.conf文件中:
zhan@virtualBox:~/home/test_lib$ sudo vim /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
/home/test_lib
zhan@virtualBox:~/home/test_lib$ sudo ldconfig
zhan@virtualBox:~/home/test_lib$ ldd app
linux-vdso.so.1 => (0x00007fffa93dc000)
libsource.so => /home/test_lib/libsource.so (0x00007fada87ab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fada83c9000)
/lib64/ld-linux-x86-64.so.2 (0x00005643a0cbf000)
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2
3、用export命令export一个指向libsource.so库文件所在目录的全局变量LD_LIBRARY_PATH, 然后运行程序的时候就会去这个目录中找共享库. (建议该方法只用于临时调试)
zhan@virtualBox:~/home/test_lib$ export LD_LIBRARY_PATH=/home/test_lib:$LD_LIBRARY_PATH
zhan@virtualBox:~/home/test_lib$ ldd app
linux-vdso.so.1 => (0x00007fffa93dc000)
libsource.so => /home/test_lib/libsource.so (0x00007fada87ab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fada83c9000)
/lib64/ld-linux-x86-64.so.2 (0x00005643a0cbf000)
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2
PS:
也可以将二中的两个目标文件source1.o,source2.o合成为动态库文件libsource.so
zhan@virtualBox:~/home/test_lib$ ar -rc -o libsource.so source1.o source2.o
zhan@virtualBox:~/home/test_lib$ ls
app.cc head.h libsource.so source1.cc source1.o source2.cc source2.o
zhan@virtualBox:~/home/test_lib$ gcc app.cc -L. -lsource -o app
zhan@virtualBox:~/home/test_lib$ ldd app
linux-vdso.so.1 => (0x00007ffcc5c9a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f926e42b000)
/lib64/ld-linux-x86-64.so.2 (0x0000560f56a62000)
zhan@virtualBox:~/home/test_lib$ ./app
source1
source2