链接、装载和库看完这个系列就够了(二)(静态库链接顺序问题续)

测试代码

单个.o链接生成静态库

让我们来继续深入的了解一下静态库的链接问题,我们把函数在每个静态库中再添加一个函数,同时修改一下Makefile:

//lib_a1.c 
#include "lib_a1.h"
int a1_fun()
{
        return 0;
}

int a1_fun2()
{
        return 0;
}
//lib_a2.c 
#include "lib_a2.h"
#include "lib_a1.h"
int a2_fun()
{
        a1_fun();
        return 0;
}

int a2_fun2()
{
        a1_fun2();
        return 0;
}
//main.c 
#include "lib_a1.h"
#include "lib_a2.h"

int main()
{
        a1_fun();
        a2_fun2();
        return 0;
}
#Makefile 
all:main

lib_a1.a: lib_a1.o
        ar rcs $@ $<
lib_a2.a: lib_a2.o
        ar rcs $@ $<

main: main.o lib_a1.a lib_a2.a
        gcc -o $@ main.o -l_a1 -l_a2 -L.

clean:
        rm -rf *.o *.a *.so main

此时我们此行make,程序不会报错:

# make clean;make
rm -rf *.o *.a *.so main
cc    -c -o main.o main.c
cc    -c -o lib_a1.o lib_a1.c
ar rcs lib_a1.a lib_a1.o
cc    -c -o lib_a2.o lib_a2.c
ar rcs lib_a2.a lib_a2.o
gcc -o main main.o -l_a1 -l_a2 -L.

我们分析一下,链接器首先读入main.o,发现a1_fun()和a2_fun2()都没有定义,所以加入未定义符号表,然后读入lib_a1.a,发现a1_fun()没有定义,就把a1_fun()链接进来,并且在未定义符号表中删除a1_fun(),最后读入lib_a2.a,发现a2_fun2(),所以把a2_fun2()链接进来,但是a2_fun2()中又调用了一个a1_fun2(),这个符号之前并没有链接进来,此时链接器应该报找不到a1_fun2()才对,为什么这里没有报错?
这是因为链接器在加载静态库的时候,一次性加载的内容是以.o为单位的,而不是以每个符号。这样,在读入lib_a1.a时,因为要链接a1_fun()和a1_fun2()是在同一个文件中,所以会一起链接进来,所以编译不会报错。

多个.o生成链接库

好了,让我们测试一下刚才的链接问题,我们把库函数的定义分别放入两个.o文件,验证一下之前的结论:

//lib_a1.c 
#include "lib_a1.h"
int a1_fun()
{
        return 0;
}
//lib_a1_2.c 
#include "lib_a1.h"
int a1_fun2()
{
        return 0;
}
//lib_a2.c 
#include "lib_a2.h"
#include "lib_a1.h"
int a2_fun()
{
        a1_fun();
        return 0;
}
//lib_a2_2.c 
#include "lib_a2.h"
#include "lib_a1.h"
int a2_fun2()
{
        a1_fun2();
        return 0;
}
//main.c 
#include "lib_a1.h"
#include "lib_a2.h"

int main()
{
        a1_fun();
        a2_fun2();
        return 0;
}
#Makefile 
all:main

lib_a1.a: lib_a1.o lib_a1_2.o
        ar rcs $@ $^
lib_a2.a: lib_a2.o lib_a2_2.o
        ar rcs $@ $^

main: main.o lib_a1.a lib_a2.a
        gcc -o $@ main.o -l_a1 -l_a2 -L.

clean:
        rm -rf *.o *.a *.so main

此时我们make:

# make clean;make
rm -rf *.o *.a *.so main
cc    -c -o main.o main.c
cc    -c -o lib_a1.o lib_a1.c
cc    -c -o lib_a1_2.o lib_a1_2.c
ar rcs lib_a1.a lib_a1.o lib_a1_2.o
cc    -c -o lib_a2.o lib_a2.c
cc    -c -o lib_a2_2.o lib_a2_2.c
ar rcs lib_a2.a lib_a2.o lib_a2_2.o
gcc -o main main.o -l_a1 -l_a2 -L.
./lib_a2.a(lib_a2_2.o): In function `a2_fun2':
lib_a2_2.c:(.text+0xa): undefined reference to `a1_fun2'
collect2: error: ld returned 1 exit status
Makefile:9: recipe for target 'main' failed
make: *** [main] Error 1

发现链接器报a2_fun2未定义,和我们上面的分析一致。
好了,静态库的链接就将到这里。

发布了8 篇原创文章 · 获赞 0 · 访问量 231

猜你喜欢

转载自blog.csdn.net/zhensansan/article/details/104586745