Linux 6 共享库so的静态链接

1.首先编译.c文件

$gcc -c -fPIC -o sharelib.o sharelib.c
-c表示只编译(compile),而不连接。
-o选项用于说明输出(output)文件名。
gcc将生成一个目标(object)文件sharelib.o。
-fPIC指Position Independent Code。共享库要求有此选项,以便实现动态连接(dynamic linking)。

2.生成共享库

$gcc -shared -o libsharelib.so sharelib.o
库文件以lib开始。共享库文件以.so为后缀。
-shared表示生成一个共享库。

3.共享库的使用

我们所需的.h和.so文件都在当前路径,因此,使用如下命令编译:
$gcc -o test test.c -lsharelib -L.
将生成test可执行文件。

使用
$./test
执行程序

有如下问题:

./test: error while loading shared libraries: libsharelib.so: cannot open shared object file: No such file or directory

这是因为操作系统无法找到库。libsharelib.so位于当前路径,位于库文件的默认路径之外。尽管我们在编译时(compile time)提供了.so文件的位置,但这个信息并没有写入test可执行文件(runtime)。可以使用下面命令测试:
$ldd test
ldd用于显示可执行文件所依赖的库。

为了解决上面的问题,我们可以将.so文件放入默认搜索路径中。但有时,特别是多用户环境下,我们不享有在默认搜索路径写入的权限。
一个解决方案是设置LD_LIBRARY_PATH环境变量。比如:
$export LD_LIBRARY_PATH=.
这样,可执行文件执行时,操作系统将在先在LD_LIBRARY_PATH下搜索库文件,再到默认路径中搜索。环境变量的坏处是,它会影响所有的可执行程序。如果我们在编译其他程序时,如果我们不小心,很可能导致其他可执行文件无法运行。因此,LD_LIBRARY_PATH环境变量多用于测试。
另一个解决方案,即提供-rpath选项,将搜索路径信息写入test文件(rpath代表runtime path)。这样就不需要设置环境变量。这样做的坏处是,如果库文件移动位置,我们需要重新编译test。使用如下命令编译test.c:
$gcc -g -o test test.c -lsharelib -L. -Wl,-rpath=.
-Wl表示,-rpath选项是传递给连接器(linker)。

用例

一个提供±*/函数的共享库。
makefile:

.PHONE : all

all : libcaculate.so testLoad testLink

###生成动态共享库
libcaculate.so : caculate.o
	gcc -Wall -fPIC -shared $^ -o $@
testLoad: testLoad.o
	gcc -Wall -L./ -rdynamic $^ -o $@ -ldl
testLoad.o : testLoad.c
	gcc -c $<
caculate.o : caculate.c
	gcc -c $<
###编译的时候链接库libcalculate.so
testLink : testLink.o
	gcc -L./ -lcaculate -Wl,--rpath=. $< -o $@

testLink.o : testLink.c
	gcc -c $<
	
clean:
	rm -f *.so *.o testLoad testLink

源文件:

/* calculate.c */

#include "stdlib.h"

int add(int a,int b)
{
    return (a + b);
}

int sub(int a, int b)
{
    return (a - b);
}

int mul(int a, int b)
{
    return (a * b);
}

int dive(int a, int b)
{
    return (a / b);
}

一种编译的时候链接使用动态库的方法:

/* testlink.c */
#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("add: %d\n", add(2,7));

    printf("sub: %d\n", sub(9,2));

    printf("mul: %d\n", mul(3,2));

    printf("dive: %d\n", dive(8,2));
    
    exit(0);
}

猜你喜欢

转载自blog.csdn.net/zzj244392657/article/details/92561607