gcc生成静态库.a和动态库.so
一、用gcc生成静态库和动态库
1、基本概念
Linux下的库有两种:静态库和共享库(动态库)
静态库:静态库的代码在编译过程中已经被载入可执行程序,因此代码体积较大。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
动态库:动态库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积小。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行时才被载入,因此程序运行时还需要动态库的存在。
两者区别:二者的区别在于代码被载入的时刻不同,前者是编译编译连接的,后者是程序连接的。
2、hello实例使用库
(1)准备过程
创建目录
命令说明
#mkdir test /创建新的目录
#cd test /打开目录编辑
#touch hello.h /建立新的文件在该目录下
#vim hello.h /打开编辑文件
#ls /查询该文件目录下的所有文件
.hello代码
hello.h
#ifndef HELLO_H
#define HELLO_H
void hello(const char *name);
#endif
hello.c
#include<stdio.h>
void hello(const char *name)
{
printf("hello %s\n",name);
}
main.c
#include“hello.h”
int main()
{
hello("everyone!");
return 0;
}
gcc编译得到.o文件
键入gcc -c hello.c
第一处出错是由于输漏了"c",“-“一般使用形式是”-x"或者是”-E";第二处出错是由于命令输错,要将.c文件转化为.o文件需要使用的命令是
gcc -c ***.c
而f非 gcc -o ***.c
(2)静态库的使用
由.o文件创建静态库
创建工具:ar
静态库文件命名规范:前缀为lib,加上静态库名,扩展名为.a。格式:lib+静态库名+.a
现要创建静态库文件libmyhello.o
,命令输入ar -crv libmyhello.a hello.o
在程序中使用静态库
在静态库中使用其中的内部的函数:需在使用到这些公用函数的源程序中包含这些公用函数的原型声明,然后再用gcc命令生成目标文件时指明静态库名,gcc将会从静态库中将这些公用函数连接到目标文件中。
在程序中使用静态库有三种命令方法:
①gcc -o hello main.c -L. -lmyhello
注: 在 自定义 的库下使用时,
main.c
还可以放在-L.和lmyhello之间
,但是不能放在他们之后,否则会提醒myhello没有定义。如果是在 系统 的库下使用,如gcc -o main (-L/USR/LIB) -lpthread main.c
就不会报错。
②gcc main.c libmyhello.a -o hello
③先生成main.o 文件 gcc -c main.c
再生成可执行文件 gcc -o hello main.o libmyhello.a
验证静态库的使用特点
在删除静态库的情况下,运行可执行文件,发现程序仍然可以正常运行,表明静态库跟执行程序没有关系。同时,说明了静态库是在程序编译的时候连接上目标代码的。
(3)动态库的使用
由.o文件创建动态库
创建动态库工具:gcc
静态库文件命名规范:前缀为lib,加上动态库名,扩展名为.so。格式:lib+动态库名+.so
现要创建动态库文件libmyhello.so
,命令输入gcc -shared -fPIC -o libmyhello.so hello.o
(-o不可少)。其中,-shared
表示生成指定的动态库链接,-fPIC
表示编译为位置独立的代码。
在程序中使用动态库
终端控制输入gcc -o hello main.c -L. -lmyhello
或gcc main.c libmyhello,so -o hello
再输入./hello
运行可执行文件时,出现了错误
错误纠正:虽然连接时连接的时用的是当前目录,但是由于运行可执行文件时,是在usr/lib
中找库文件的,故将libmyhello.so
复制到目录usr/lib
中即可;
如果显示没有执行权限,可以使用sudo命令授权
(4)静态库和动态库的优先级比较
在控制终端输入以下命令:mv -f hello hello.o /usr/lib/limyhello.so
删除.c和.h以外文件,执行命令之后查询发现还没有全部删除完,继续删除文件直到仅剩下.o和.h文件。
重新创建静态库文件libmyhello.a
和动态库文件libmyhello.so
键入如下命令:gcc -o hello.c
生成 hello.o文件;ar -cr libmyhello.a hello.o
创建静态库; gcc -shared -fPIC -o libmyhello.so hello.o
创建动态库;
使用库生成可执行文件gcc -o hello main.c -L -lmyhello
;运行可执行文件./hello
在运行可执行文件时,会报错。从而可见,当静态库和动态库同名时即两者同时存在是,gcc命令会优先使用动态库。
3、实例一使用库
(1)代码
创建目录
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 *);
#ednif
test.c
#incldue<stdio.h>
#include"A.h"
int main()
{
print1(1);
print2(test);
exit(0);
}
(2)静态库.a文件的生成与使用
终端控制输入以下命令gcc -c A1.o A2.o
生成目标文件;ar crv libafile.a A1.o A2.o
生成静态库.a文件;使用.a文件创建可执行文件gcc -o test test,c libafile.a
;./test
运行可执行程序
(3)共享库.so文件的生成与使用
终端控制输入以下命令:gcc -c -fPIC A1.c A2.c
生成目标文件;gcc -shared *.o -o libsofile.so
生成共享库.so文件;gcc -o test test.c libsofile.so
使用.so文件创建可执行程序;./test
运行可执行程序
运行程序的时候出现错误,运行ldd test
查看链接情况;发现确实找不到对应的.so文件,这是由于Linux自身系统设定的相应的设置的原因,即其只在/lib
和/usr/lib
下搜索对应的.so文件,故需将对应的.so文件复制拷贝到对应的路径。
4、实例二使用库
(1)代码
创建目录
sub1.c
float x2x(int a,int b)
{
float c=0;
c=a+b;
return 0;
}
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>
#incldue"sub.h"
void main()
{
int a,b;
printf("Please input the value of a:");
scanf("%d",&a);
printf("Please input the value of 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
(2)静态库
创建静态库文件ar crv libsub.a sub1.0 sub2.o
生成可执行文件gcc -o mian main.c libsub.a
(3)动态库
gcc shared -fPIC -o libsub.so sub1.o sub2.o
注意: 输入的是
-o
不是-0.否则就会出现像我这种错误
(4)静态库与动态库生成的文件大小比较
静态库
动态库
经过比较发现静态库要比动态库要小很多,生成的可执行文件大小两者之间也存在较小的差别
二、总结
通过三个简单的程序的在静态库和动态库的创建使用以及运行结果的对比,对Linux中静态库和动态库从无到有有了比较的了解,能够比较熟练两者在系统下的操作.在实验过程中,出现了一些错误,在Linux极其需要注意命令格式的正确输入,不能乱用,容易出现错误,也有可能致使电脑奔溃。