目标

我们的目的是:链接这个动态链接库,并放在可执行文件目录下,使可执行文件执行时能找到这个库。

当然。我们最终应该可以将动态链接库放在任何位置,同时保证我们的可执行文件可以找到这些动态链接库。

这对我们组织、打包整个项目相当有帮助。你可以使用命令: ldd <可执行文件名> 看看可执行文件所链接的动态库,及其路径。

创建动态链接库

gcc -shared -fpic x1.o x2.o x3.o -o libqazwsx.so

上面这条命令将 x1.o、x2.0、 x3.o 三个文件打包成一个动态链接库文件 libqazwsx.so

指定位置

下面是我们的核心编译命令

gcc test.o -o test -Wl,-rpath,./ -L./ -lqazwsx

这条命令会告诉可执行文件,他需要的动态链接的位置,这个是我们创建的实验文件目录。

.--test
|-------test.c
|-------x1.c
|-------x2.c
|-------x3.c
|-------test.o
|-------x1.o
|-------x2.o
|-------x3.o
|-------libqazwsx.so

命令解释

现在我们已经有了一个指定了链接位置的动态链接库,来详细解释一下这条命令。

test.o -o testtest.o 与动态库链接并输出可执行文件 test

-Wl,-rpath,./ 告诉链接器,test 在执行时应当在 ./ 下找动态库

-L./ -lqazwsx 告诉链接器,链接时在 ./ 下找动态库

测试代码

// x1.c
#include <stdio.h>
void print_x1 (void) {
    printf("I am x1.o\n");
}
// x2.c
#include <stdio.h>
void print_x2 (void) {
    printf("I am x2.o\n");
}
// x3.c
#include <stdio.h>
void print_x3 (void) {
    printf("I am x3.o\n");
}
//test.c
#include <stdio.h>
extern void print_x1 (void);
extern void print_x2 (void);
extern void print_x3 (void);
int main (void) {
    print_x1();
    print_x2();
    print_x3();
    printf("I am main function\n");
    return 0;
}

这里是完整的编译指令

gcc -c x1.c
gcc -c x2.c
gcc -c x3.c
gcc -c test.c
gcc -shared -fpic x1.o x2.o x3.o -o libqazwsx.so
gcc test.o -o test -Wl,-rpath,./ -L./ -lqazwsx

执行测试

# ??? @ ??? in ~/workspace/cpp [19:18:35]
$ ./test
I am x1.o
I am x2.o
I am x3.o
I am main function

# ??? @ ??? in ~/workspace/cpp [19:18:39]
$ ldd test
linux-vdso.so.1 (0x00007fff755fd000)
libqazwsx.so => ./libqazwsx.so (0x00007f9708264000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9707ea2000)
/lib64/ld-linux-x86-64.so.2 (0x0000564acd3d3000)

# ??? @ ??? in ~/workspace/cpp [19:22:57]
$ rm libqazwsx.so
rm:是否删除普通文件 'libqazwsx.so'?y

# ??? @ ??? in ~/workspace/cpp [19:23:04]
$ ./test
./test: error while loading shared libraries: libqazwsx.so: cannot open shared object file: No such file or directory

# ??? @ ??? in ~/workspace/cpp [19:23:07] C:127
$ ldd test
linux-vdso.so.1 (0x00007ffda6fdb000)
libqazwsx.so => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f702f741000)
/lib64/ld-linux-x86-64.so.2 (0x000055c80d664000)

可以看到,我们创建的动态链接库放在了可执行文件的同级目录下,这时可执行文件可以找到这个动态链接库。当我们删除了这个库时,可执行文件就因为找不到链接库而无法运行了。

总结

现在,我们知道了指定动态链接库到可执行文件的同级目录下,换言之,我们也可以将库放到其他位置。这样我们可以做到系统的模块化。不同功能的代码封装到不同的动态链接库中,这样可以做到系统的热更新。