TLDR
.o
目标文件编译期报错
.a
静态库文件
如果只有同名函数,编译期正常,运行时调用先链接的
如果后链接的.c
源码文件有独有函数,不管先链接的有没有独有函数,编译报与链接.o
相同的错
如果先链接的.c
源码文件有独有函数,则正常链接运行先链接的
.so
动态库文件编译期正常,运行时调用先链接的
前期基础
同名函数测试
- 测试准备
// test1.c 和 test2.c (代码相同)
#include <stdio.h>
void test() {
printf("[test same func name] %s: %s\n", __FILE__, __func__);
}
// test4.c 有独有函数lalala
#include <stdio.h>
void test() {
printf("[test same func name] %s: %s\n", __FILE__, __func__);
}
void lalala() {
printf("[test same func name] lalala\n");
}
// test3.c 也有独有函数hehehe
#include <stdio.h>
void test() {
printf("[test same func name] %s: %s\n", __FILE__, __func__);
}
void hehehe() {
printf("[test same func name] hehehe\n");
}
// main.c 只调用同名函数test
extern void test();
int main() {
test();
}
// main_la.c 增加调用test4独有函数
extern void test();
extern void lalala();
int main() {
test();
lalala();
}
// main_he.c 增加调用test3独有函数
extern void test();
extern void lalala();
extern void hehehe();
int main() {
test();
lalala();
hehehe();
}
-
.o
目标文件:将包含同名函数的目标文件进行链接,如果其在同一个命名空间中,编译期会报multiple definition错误
gcc -c ./test1.c
gcc -c ./test2.c
gcc -o main ./test1.o ./test2.o ./main.c
# 编译报错
test2.o:在函数‘test’中:
test2.c:(.text+0x0): `test'被多次定义
test1.o:test1.c:(.text+0x0):第一次在此定义
collect2: error: ld returned 1 exit status
-
.a
静态库文件:将包含同名函数的目标文件分别编译成静态库,按顺序链接,编译正常,运行输出先链接的函数结果。
gcc -c ./test1.c
gcc -c ./test2.c
ar crv libtest1.a test1.o
ar crv libtest2.a test2.o
gcc -L. ./main.c -ltest1 -ltest2 -o main
./main
# 运行正常
[test same fun name] test1.c: test
# 加编译参数-Wl,--verbose重新编译可执行文件查看原因
gcc -L. ./main.c -ltest1 -ltest2 -o main -Wl,--verbose
# 看到只链接了libtest1.a背后的test1.o文件,同时存在动态库和静态库时,优先链接动态库
...
试图打开 ./libtest1.so 失败
试图打开 ./libtest1.a 成功
(./libtest1.a)test1.o
试图打开 ./libtest2.so 失败
试图打开 ./libtest2.a 成功
...
# 如果使用编译参数-Wl,--whole-archive链接libtest1.a和libtest2.a
gcc -L. ./main.c -Wl,--whole-archive -ltest1 -ltest2 -Wl,--no-whole-archive -o main
# 编译报错
./libtest2.a(test2.o):在函数‘test’中:
test2.c:(.text+0x0): `test'被多次定义
./libtest1.a(test1.o):test1.c:(.text+0x0):第一次在此定义
collect2: error: ld returned 1 exit status
4..a
静态库文件后链接的库有独有函数:编译报与链接.o
相同的错。
gcc -c ./test4.c
ar crv libtest4.a test4.o
gcc -L. ./main_la.c -ltest1 -ltest4 -o main_la
# 编译报错
./libtest4.a(test4.o):在函数‘test’中:
test4.c:(.text+0x0): `test'被多次定义
./libtest1.a(test1.o):test1.c:(.text+0x0):第一次在此定义
collect2: error: ld returned 1 exit status
# 两个文件都有独有文件也会报错
gcc -c ./test3.c
ar crv libtest3.a test3.o
gcc -L. ./main_he.c -ltest3 -ltest4 -o main_he
# 编译报错
./libtest4.a(test4.o):在函数‘test’中:
test4.c:(.text+0x0): `test'被多次定义
./libtest3.a(test3.o):test3.c:(.text+0x0):第一次在此定义
collect2: error: ld returned 1 exit status
5..a
静态库文件先链接的库有独有函数:正常编译运行。
gcc -L. ./main_la.c -ltest4 -ltest1 -o main_la
LD_LIBRARY_PATH=./ ./main_la
[test same func name] ./test4.c: test
[test same func name] lalala
-
.so
动态库文件:将包含同名函数的源文件分别编译成动态库,按顺序链接,编译正常,运行输出先链接的函数结果。符号会以第一个查找到的为准(Symbols are resolved on a first match basis)。
gcc -shared -fPIC -o libtest1.so test1.c
gcc -shared -fPIC -o libtest2.so test2.c
gcc -L. ./main.c -ltest1 -ltest2 -o main -Wl,--verbose
# 查看链接过程
试图打开 ./libtest1.so 成功
-ltest1 (./libtest1.so)
试图打开 ./libtest2.so 成功
-ltest2 (./libtest2.so)
LD_LIBRARY_PATH=./ ldd main
# 查看链接结果只链接了test1.so
linux-vdso.so.1 => (0x00007ffcc78c3000)
libtest1.so => ./libtest1.so (0x00007f873a8f7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f873a52d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f873aaf9000)
# 运行结果是test1中函数
LD_LIBRARY_PATH=./ ./main
[test same fun name] test1.c: test
7..so
动态库文件后链接的库有独有函数:同名函数会使用先链接的。
// main.c 增加调用test4独有函数
extern void test();
extern void lalala();
int main() {
test();
lalala();
}
# 编译test4.so和main,ldd查看链接还是只链接了test1
gcc -shared -fPIC -o libtest4.so test4.c
gcc -L. ./main.c -ltest1 -ltest4 -o main
ldd ./main
linux-vdso.so.1 => (0x00007ffe127fd000)
libtest1.so => not found
libtest4.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f345357b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3453945000)
# 运行结果是test1中函数
LD_LIBRARY_PATH=./ ./main
[test same func name] test1.c: test
[test same func name] lalala
8..so
动态库文件都有独有函数:同名函数使用先链接的。
# 编译test3.so和main,ldd查看链接,链接了test3和test4
gcc -shared -fPIC -o libtest3.so test3.c
gcc -L. ./main.c -ltest3 -ltest4 -o main
ldd ./main
linux-vdso.so.1 => (0x00007fff4cfbb000)
libtest3.so => not found
libtest4.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5523437000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5523801000)
# 运行结果是test3中函数
LD_LIBRARY_PATH=./ ./main
[test same func name] test3.c: test
[test same func name] lalala
[test same func name] hehehe