介绍GCC生成静态库.a和动态库.so及其实例使用
一、用gcc生成.a静态库和.so动态库
1、例子1 hello程序讲解
① 创建目录并编辑生成例子程序 hello.h、hello.c 和main.c
(1)例子程序hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif
(2)例子程序 hello.c
#include<stdio.h>
void hello(const char *name)
{
printf("Hello %s\n",name);
}
(3)例子程序 main.c
#include"hello.h"
int main()
{
hello("everyone");
return 0;
}
(4)将hello.c编译成.o文件
gcc -c hello.c
提示:文件编辑可用 vim、nano、gedit等
②gcc生成静态库并使用
(1) 创建静态库
静态库文件名规范格式:lib为前缀,紧跟静态库名,扩展名为.a。 创建静态库用ar命令。
ar -crv libmyhello.a hello.o
如图所示:
(2)使用静态库
方法一:gcc -o hello main .c -L -lmyhello
提示:main.c还可以放在-L.和-lmyhello之间,但是不能放在它俩之后,否则myhello没有定义。
-L:表示连接的库在当前目录
如图所示:
方法二:gcc main.c libmyhello.a -o hello
如图所示:
方法三:先生成 main.c:gcc -c main.c
再生成可执行文件:gcc -o hello main.o libmyhello.a
如图所示:
(3)查看公用函数是否真的连接到目标文件hello中
如图所示:
发现在删除静态库后,可执行文件依然执行,表明静态库中的公用函数已经连接到目标文件中了。
③gcc生成动态库并使用
(1)由.o文件创建动态库文件
动态库文件名规范格式:lib前缀,紧跟动态库库文件名,文件扩展名为.so。创建动态库为gcc命令。
gcc -shared -fPIC -o libmyhello.so hello.o
如图所示:
提示:-shared 该选项指定生成动态连接库(让连接器生成 T 类型的导出符号表,有时候也生成弱连接 W 类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
(2)使用动态库
gcc -o hello main.c -L. 或gcc main.c libmyhello.so -o hello
执行./hello出错,因连接时用的是当前目录的动态库文件,运行时是去/usr/lib中找动态库文件,所以将文件libmyhello.so 复制到目录/usr/lib中。
如图所示:
发现在程序运行时是需要动态库的。
④当静态库和动态库同名时,gcc的选择
(1)删除所有生成文件,恢复到3个子程序创建完成状态。
(2)创建静态库文件 libmyhello.a 和动态库文件 libmyhello.so。
gcc -c hello.c
ar -ccr libmyhello.a hello.o
gcc -shared -fPIC -o libmyhello.so hello.o
如图所示:
结果:当静态库和动态库同名时,gcc 命令将优先使用动态库,默认去连/usr/lib 和/lib 等目录中的动态库。
⑤静态库和动态库的总结
静态库:静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库:动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。
2、实例2
①创建程序:
A1.c:
#include <stdio.h>
void print1(int arg){
printf("A1 print arg:%d\n",arg);
}
A2.c:
#include <stdio.h>
void print2(char *arg){
printf("A2 printf arg:%s\n", arg);
}
A.h:
#ifndef A_H
#define A_H
void print1(int);
void print2(char *);
#endif
test.c:
#include <stdlib.h>
#include "A.h"
int main(){
print1(1);
print2("test");
return 0;
}
②静态库.a 文件的生成与使用。
③共享库.so 文件的生成与使用
3、 实例3
①创建程序:
sub1.c:
float x2x(int a,int b)
{
float c=0;
c=a-b;
return c;
}
sub2.c:
float x2y(int a,int b)
{
float c=0;
c=a*b;
return c;
}
sub.h
#ifndef SUB_H
#define SUB_H
float x2x(int a,int b);
float x2y(int a,int b);
#endif
main.c:
#include<stdio.h>
#include"sub.h"
void main()
{
int a,b;
printf("请输入a:");
scanf("%d",&a);
printf("请输入b:");
scanf("%d",&b);
printf("a-b=%.2f\n",x2x(a,b));
printf("a*b=%.2f\n",x2y(a,b));
}
如图所示:
②生成三个.o文件
gcc -c sub1.c sub2.c main.c
③将x2x、x2y目标文件生成静态库并使用
ar crv libsub.a sub1.o sub2.o
gcc -o main main.c libsub.a
④将x2x、x2y目标文件生成动态库并使用
gcc -shared -fPIC -o libsosub.so sub1.o sub2.o
gcc -o main main.c libsosub.so
⑤将静态库和动态库生成文件大小比较
静态库大小:
动态库大小:
结论:比较发现静态库文件小于动态库文件,生成的可执行文件差别较小。
二、 实验总结
本实验为第二次使用gcc,相比第一次对于ubuntu的操作熟悉了很多。本次实验主要为验证过程,所以操作较为简单,熟悉静态库和动态库的用法及区别。
三、参考资料
[1]Linux下静态库.a与.so库文件的生成与使用。
[2]用gcc生成静态库和动态库。