在编译程序时,考虑如下场景:
代码中使用到了A库的函数,此外再无其它依赖库。但是,A库中使用了B库的函数,B库依赖C库,C库依赖D库。因此在编译可执行文件时,需要找到ABCD,并指定库的路径,在链接时才不会爆出找不到某个定义的错误。
如果在交叉编译时A库的依赖项高达几十甚至更多个,会让编译变得非常麻烦,需要指定每个库的位置和库名,有些情况可能需要给库添加软链。有没有什么方法在编译时不需要指定依赖?
// libfunA.so
void funA() {printf("libFunA.so\n");funB();}
// libfunB.so
void funB() {printf("libFunB.so\n");funC();}
// libfunC.so
void funC() {printf("libFunC.so\n");}
int main()
{printf("main\n");funA();}
编译动态库
gcc -fPIC -shared xxx.c -o libfunA.so
此时生成的动态库中只含有一个libfunA.so字符串
通过ldd命令查看libfunA.so的依赖,其中没有libfunB.so,即依赖项没有添加入动态库的二进制文件中
Cmake简单使用
cmake 编译时会默认指定一些参数,因此和上面简单的指定参数相比cmake会加入更多选项。
生成动态库时:
#include // link with -ldl
dlopen
dlerror
dlsym
dlclose
// loads the dynamic shared object
void *handle(const char*filename, int flags);
- filename: filename, if is null, the return handle is for the main program.
if contain slash("/"), relative or absolute pathname
filename: filename, if is null, the return handle is for the main program.if contain slash(“/”), relative or absolute pathname
动态库搜索:
flags: 以下二者之一
#include
#include
#include
#include // GNU libc so name macros
int main()
{
void* handle; double(*cosine)(double); char* error;
handle = dlopen(LIBM_SO, RTLD_LAZY);
if (!handle) {exit(1);}
dlerror(); // clear error
cosine = (double(*)(double))dlsym(handle, "cos");
error = dlerror();
if (error != NULL) {printf("%s\n", error); exit(1);}
printf("%f\n", cosine(3.1415926));
dlclose(handle);
}
在编译可执行文件时,需要找到所有已使用符号的定义,如果该符号在动态库中就需要指定动态库; 如果动态库依赖了另外的动态库,也需要指明该库。
通过dl库可在编译时避免指定动态库,方便编译。