Я немного пытался понять, как работает компоновщик gcc и чем отличаются вещи при связывании общей библиотеки с другой общей библиотекой и при связывании двоичного файла с общей библиотекой. Я использую Ubuntu 16.04.1 LTS, gcc 5.4.0 и ld 2.26.1.
Ниже приведены два набора последовательностей команд, выполняемых с некоторыми исходными файлами C.
Последовательность 1:-
ammal@ubuntu:~/linktest6$ cat a.c
#include <stdio.h>
int a_func() {
printf("Running a_func()\n");
return 0;
}
ammal@ubuntu:~/linktest6$ cat b.c
#include <stdio.h>
int a_func();
int b_func() {
printf("Running b_func()\n");
a_func();
return 0;
}
ammal@ubuntu:~/linktest6$ cat d.c
#include <stdio.h>
int b_func();
int d_func() {
printf("Running d_func()\n");
b_func();
return 0;
}
ammal@ubuntu:~/linktest6$ cat myprog.c
#include <stdio.h>
int d_func();
int main() {
printf("Running myprog_func()\n");
d_func();
return 0;
}
ammal@ubuntu:~/linktest6$ gcc -shared -fPIC -o liba.so a.c
ammal@ubuntu:~/linktest6$ ldd -r liba.so
linux-vdso.so.1 => (0x00007ffc6fded000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1898da3000)
/lib64/ld-linux-x86-64.so.2 (0x0000555e2853c000)
ammal@ubuntu:~/linktest6$ gcc -shared -fPIC -o libb.so b.c
ammal@ubuntu:~/linktest6$ ldd -r libb.so
linux-vdso.so.1 => (0x00007ffd82127000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0cc6253000)
/lib64/ld-linux-x86-64.so.2 (0x00005586e6a36000)
undefined symbol: a_func (./libb.so)
ammal@ubuntu:~/linktest6$ gcc -shared -fPIC -o libd.so d.c
ammal@ubuntu:~/linktest6$ ldd -r libd.so
linux-vdso.so.1 => (0x00007ffc3addb000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f408db59000)
/lib64/ld-linux-x86-64.so.2 (0x0000558720efc000)
undefined symbol: b_func (./libd.so)
ammal@ubuntu:~/linktest6$ gcc -fPIC -o myprog myprog.c -L. -ld -lb -la
ammal@ubuntu:~/linktest6$ ldd -r myprog
linux-vdso.so.1 => (0x00007ffe807aa000)
libd.so => not found
libb.so => not found
liba.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f344acce000)
/lib64/ld-linux-x86-64.so.2 (0x0000563a89eb4000)
undefined symbol: d_func (./myprog)
Последовательность 2:-
ammal@ubuntu:~/linktest6$ cat a.c
#include <stdio.h>
int a_func() {
printf("Running a_func()\n");
return 0;
}
ammal@ubuntu:~/linktest6$ cat b.c
#include <stdio.h>
int a_func();
int b_func() {
printf("Running b_func()\n");
a_func();
return 0;
}
ammal@ubuntu:~/linktest6$ cat d.c
#include <stdio.h>
int b_func();
int d_func() {
printf("Running d_func()\n");
b_func();
return 0;
}
ammal@ubuntu:~/linktest6$ cat myprog.c
#include <stdio.h>
int d_func();
int main() {
printf("Running myprog_func()\n");
d_func();
return 0;
}
ammal@ubuntu:~/linktest6$ gcc -shared -fPIC -o liba.so a.c
ammal@ubuntu:~/linktest6$ ldd -r liba.so
linux-vdso.so.1 => (0x00007ffe8c9ee000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f88b91c2000)
/lib64/ld-linux-x86-64.so.2 (0x0000555cf72ef000)
ammal@ubuntu:~/linktest6$ gcc -shared -fPIC -o libb.so b.c
ammal@ubuntu:~/linktest6$ ldd -r libb.so
linux-vdso.so.1 => (0x00007fffbffc4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f69ea310000)
/lib64/ld-linux-x86-64.so.2 (0x000055996b3e5000)
undefined symbol: a_func (./libb.so)
ammal@ubuntu:~/linktest6$ gcc -shared -fPIC -o libd.so d.c -L. -lb -Wl,-rpath=/home/ammal/linktest6
ammal@ubuntu:~/linktest6$ ldd -r libd.so
linux-vdso.so.1 => (0x00007ffe21bb6000)
libb.so => /home/ammal/linktest6/libb.so (0x00007fca1cdb6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fca1c9d5000)
/lib64/ld-linux-x86-64.so.2 (0x000055f517b11000)
undefined symbol: a_func (/home/ammal/linktest6/libb.so)
ammal@ubuntu:~/linktest6$ gcc -fPIC -o myprog myprog.c -L. -ld -lb -la
./libb.so: undefined reference to `a_func'
collect2: error: ld returned 1 exit status
Мой вопрос в том, почему я могу успешно скомпилировать двоичный файл в первом случае, а не во втором.