静态库Archive

静态库是共享代码的一种实现方式。其名字出自于编译时静态加载,编译出的对象文件完全包含了静态库中的所有代码。

生成静态库只需要两步:
第一步将源文件*.c编译成*.o文件:cc -c *.c
第二步再简单地将*.o文件打包成*.a即可:ar crv libtarget.a *.o

静态库的使用:
由于静态加载,需要在link时就指定静态库,用来将静态库中的全部代码link到最终的目标文件中。

对于*.a文件可以使用nm这个命令来list symbols from object files:nm libtarget.a
还可以通过ar命令的x选项将*.a反向解压:ar xv libtarget.a,将libtarget.a解包成之前的一系列*.o文件。

静态库的应用场景是:
代码使用商要购买某个算法,或者产品套件中有配套的代码。
但是代码提供商出售代码时不希望公开源码,可以将编译的中间结果卖给代码使用商。
代码使用商就可以以*.a形式文件作为原料,制作动态库,或者制作成应用程序。
但是需要注意的是,*.o文件原则上不应该被代码版本管理工具(如git,svn)所收容,因为工程编译自己也会产生*.o文件,这对于代码管理会有干扰。
比如我修改了3个源文件,编译验证通过,本来要上库的,结果不仅提示3个源文件被更新,如果代码版本库中有*.o文件也会提示要更新。
所以一般代码提供商会将要发布的*.o文件打包成*.a文件,即静态库文件。

以如下实验代码为例:
源代码文件func.c,其中定义了func0,func1,func2,func3这四个函数

#include <stdio.h>
#define FUNC(TAG) \
    int func##TAG(void) \
    { \
        printf("%s.%d:%s\n", __FILE__, __LINE__, __func__); \
        return 0; \
    }

FUNC(0);    /* func0 */
FUNC(1);    /* func1 */
FUNC(2);    /* func2 */
FUNC(3);    /* func3 */

再有文件stub.c,其中定义了stub0,stub1,stub2,stub3这四个函数

#include <stdio.h>
#define FUNC(TAG) \
    int stub##TAG(void) \
    { \
        printf("%s.%d:%s\n", __FILE__, __LINE__, __func__); \
        return 0; \
    }

FUNC(0);    /* stub0 */
FUNC(1);    /* stub1 */
FUNC(2);    /* stub2 */
FUNC(3);    /* stub3 */

再有文件call.c,其中定义了call()函数,其引用了func0和stub0函数

int call()
{
    func0();
    stub0();
    return 0;
}

最后在文件main.c中定义main函数,且依次调用func.c,stub.c和call.c中的函数

#include <stdio.h>
int main()
{
    printf("%s begin\n", __func__);

#if 1
    func1();
    func2();
    func3();
#endif

#if 1
    stub1();
    stub2();
    stub3();
#endif

#if 1
    call();
#endif

    printf("%s return\n", __func__);
    return 0;
}

如果直接编译main.c肯定会报错,因为link时找不到对应符号实际的定义:

test@test:~$ gcc main.c 
/tmp/ccDTot2x.o: In function `main':
main.c:(.text+0x21): undefined reference to `func1'
main.c:(.text+0x2b): undefined reference to `func2'
main.c:(.text+0x35): undefined reference to `func3'
main.c:(.text+0x3f): undefined reference to `stub1'
main.c:(.text+0x49): undefined reference to `stub2'
main.c:(.text+0x53): undefined reference to `stub3'
main.c:(.text+0x5d): undefined reference to `call'
collect2: ld returned 1 exit status

这里我们将func.c和stub.c对应的代码制作成libcsdn.a

gcc -c func.c stub.c
ar crv libcsdn.a func.o stub.o

这样静态库文件就制作好了。
然后就可以将静态库文件当作普通的*.o来使用:

gcc main.c libcsdn.a call.c

这样生成的a.out应用程序就完整了包含了所有源代码文件的内容,在运行时全部加载入内存。

使用静态库:link时指定用到的静态库文件,且要注意顺序
例如:

gcc main.c libt3.a -o a.out
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yilonglucky

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

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

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

打赏作者

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

抵扣说明:

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

余额充值