gcc生成静态库和动态库
目录
程序例子
1.编辑生成例子程序 hello.h、hello.c 和 main.c。
hello.c
#include <stdio.h>
void hello(const char *name)
{
printf("Hello %s!\n", name);
}
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif //HELLO_H
main.c
#include "hello.h"
int main()
{
hello("everyone");
return 0;
}
2.将 hello.c 编译成.o 文件
gcc -c hello.c
观察编译结果:
3.由.o 文件创建静态库。
静态库文件名的命名规范是以 lib 为前缀,紧接着跟静态库名,扩展名为.a。创建静态库用 ar 命令。在系统提示符下键入以下命令将创建静态库文件 libmyhello.a。
ar -crv libmyhello.a hello.o
输入ls观察结果
4.在程序中使用静态库。
方法一:
gcc -o hello main.c -L. –lmyhello
-L. 表示要连接的库在当前目录中;
-lmyhello编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上 lib,后面 加上.so 或.a 来确定库的名称 libmyhello.so 或 libmyhello.a。
方法二:
gcc main.c libmyhello.a -o hello
(ps:个人推荐第二种方法,但是第一中更能体现出库的链接)
观察结果:
我们删除一下libmyhello.a文件试一下程序是否能进行
可以得出静态库的链接是将整个库和目标文件打包在一起的。
5.由.o 文件创建动态库文件。
动态库文件名命名规范和静态库文件名命名规范类似,也是在动态库名增加前缀 lib,但其 文件扩展名为.so。
输入下面的代码:
gcc -shared -fPIC -o libmyhello.so hello.o
-shared 该选项指定生成动态连接库,不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC作用于编译阶段,告诉编译器产生与位置无关代码(Position-Independent Code),则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。
观察结果:
6.在程序中使用动态库。
建立执行文件与链接静态库相似,输入以下代码:
gcc -o hello main.c -L. -lmyhello
或者
gcc main.c libmyhello.so -o hello
执行结果:
注意:因为虽然连接时用的是当前目录的动态库,但是运行时,是到 /usr/lib 中找库文件的,将文件 libmyhello.so 移动到目录/usr/lib 中就 OK 了,注意先sudo su,不然权限不够。
7.当静态库和动态库同名时,gcc 命令会使用哪个库文件呢?
输入执行文件时,结果与使用动态库的结果相同(出现了同样的错误),可以看出当静态库和动态库同名时,gcc 命令会优先使用动态库文件。
程序实践
1.生成.c文件
main1.c
#include<stdio.h>
#include"sub1.h"
#include"sub2.h"
void main()
{
int a,b,c;
a=10;b=8;
c=x2x(a,b);
printf("x2x=%d\n",c);
printf("x2y=%d\n",x2y(a,b));
}
sub1.c
#include<stdio.h>
int x2x(int a,int b)
{
int c;
c=a*b;
return c;
}
sub1.h
int x2x(int a,int b);
sub2.c
#include<stdio.h>
int x2y(int a,int b)
{
printf("hello world!\n");
return (a+b);
}
sub2.h
int x2y(int a,int b);
2.生成静态库.a和动态库.so
生成.a文件:
通过gcc将sub1.c,sub2.c编译成.o文件后,输入代码:
ar -cr libhehe.a sub1.o sub2.o
生成.so文件:
gcc -shared -fPIC -o libhehe.so sub1.o sub2.o
结果如图:
3.动态库和静态库的运用
1.静态库:
输入:
gcc main1.c libhehe.a -o qwe1
执行结果:
文件大小
2.动态库:
输入:
gcc main1.c libhehe.so -o qwe2
执行结果:
文件大小:
对比文件差异不大,可能是因为生成.o文件很小,导致生成的两个库文件都很小,差异就很小。
要想观察静态库和动态库文件大小的差异怎么办呢?
用ldd观察链接的动态库是,发现还链接了一个动态库
在gcc 里面加入参数static把动态库连接转变成静态库连接
发现调用静态库方式比动态库所需要的空间更大。
总结:
本次的学习,了解了静态库与动态库的区别,静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。在实践中,由于本人代码水平有限,如果有什么出错的地方,希望能交流,互相促进提高