嵌入式硬件从小工到专家(一个关于静态库的有趣题目)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        关于编译,大家都比较熟悉了。无非就是把c/c++编译成动态库,或者是编译成可执行程序。还有一种情况呢,其实是编译成静态库。说起来是静态库,其实就是把很多.o文件pack在一起,不做筛选,也不做link,就仅仅是打包在一起而已。这么一看,好像也人畜无害。但有的时候,特别是link的时候,很容易出现依赖关系的时候,今天不妨找个例子看一看。

1、首先有一个add.c

        这个add.c纯粹就是用来做实验的,假设它的内容是这样的,

int add()
{
	return 1;
}

        函数内容比较简单,我们可以通过两行命令,就可以生成对应的静态库文件libadd.a,

gcc -c add.c
ar rc libadd.a add.o

2、再准备一个calculate.c

        这里的calculate.c同样比较简单,实现也不复杂。不过它和add.c有点关系,也就是calculate.c里面函数的实现依赖于add.c。虽然现在还没有进行链接,但是将来肯定要bind在一起的,


extern int add();

int calculate()
{
	return add();
}

        通过代码,不难发现,这里的实现也的确是依赖于add函数。上面的extern,其实也是在告诉编译器,这个函数本文件没有,直接从其他地方找吧。大体就是这个意思。和add.c一样,我们现在也把这个文件编译成静态库libcalcualte.a的形式,整个过程也是两行命令就可以搞定,

gcc -c calculate.c
ar rc libcalculate.a calculate.o

3、准备最后一个main.c

        有了两个静态库,那么就可以开始准备最后一个main.c。既然我们用到了静态库,那么最好的方法,就是在main.c里面直接调用calculate.c里面的函数,再让calculate.c去调用add.c。所以我们的main.c准备写成这个样子,

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern int calculate();

int main(int argc, char* argv[])
{
	return calculate();
}

        很明显,main.c依赖于calculate函数,而calculate函数又依赖于add函数,所以一个比较直观的想法,就是编译的时候,需要把这两个静态库都添加进来。因此,我们继续进行操作。只是操作的时候,出现了戏剧性的一幕。如果我们是这么来敲命令,即

gcc main.c -o main ./libadd.a ./libcalculate.a

        那么很遗憾,编译器告诉我们链接是失败的,

feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/code$ gcc main.c -o main ./libadd.a ./libcalculate.a 
/usr/bin/ld: ./libcalculate.a(calculate.o): in function `calculate':
calculate.c:(.text+0xe): undefined reference to `add'
collect2: error: ld returned 1 exit status

        但是如果反过来呢,也就是libadd.a和libcalculate.a交换一下位置,那么link居然是成功的,

feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/code$ gcc main.c -o main ./libcalculate.a ./libadd.a
feixiaoxing@feixiaoxing-VirtualBox:~/Desktop/code$ 

        这说明什么道理呢?明明libcalculate.a是依赖于libadd.a的,但如果把libcalculate.a放在了最后面,那么它里面的函数其实也就找不到链接了。换句话说,gcc命令当中,越是基础的.a,就越应该出现在命令行的末端;而越复杂的.a,则需要出现在离可执行文件越近的位置。侧面也说明了,哪怕是静态库,编译链接的时候也要注意依赖顺序,不然链接可能过不了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式-老费

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值