静态库和动态库介绍以及Makefile

1、库文件介绍

(1)库文件的提供方式:静态库/动态库 + 头文件说明。其中头文件是说明静态库/动态库里都实现了哪些函数,就好像是库的说明书一样,使用库的开发者需要根据头文件来使用库;
(2)库文件的实质:就是将很多.o文件打包在一起。其中涉及到程序的预编译、编译、汇编、链接等过程,.o文件就是只编译不链接的文件;

2、库文件的作用

1.加快项目开发:库文件可以将大工程划分为一个一个的模块,每个模块的代码以库的形式提供,库与库之间只需要提前商定好交互头文件,然后每个库的开发人员就按照头文件进行同步开发,最后再联调。
2.保密的作用:比如你去买一个模组,生产商一般会提供给你一个demo程序、静态库/动态库、头文件,头文件和demo程序是说明怎么操作模组,但是具体操作模组的函数实体你是看不到的,已经封装成库文件提供给你,真正底层的东西你是接触不到的。
3.便于维护代码:整个项目是由一个一个的库组成,原则上只要库的交互头文件不改动,库内部的修改别人是不关心的,这样每个库都可以作为单独的模块去维护。

3、静态库

1.命名:libxxx.a;
2.特点:
(1)静态库的函数链接是在编译阶段完成的;
(2)可执行程序在运行时不再依赖静态库,因为在链接的时候已经将静态库嵌套到可执行程序中,所以你在设备的lib目录里看到的基本都是动态库,因为用不上静态库;
(3)优点:因为可执行程序不再依赖静态库,移植更方便,直接将可执行程序移植过去就可以运行;
(4)缺点:因为在编译可执行程序时就把静态库编译进可执行程序,所以编译出来的可执行程序比较大;更新可执行程序比较麻烦,因为修改静态库就必须要把可执行程序重新编译一遍;

4、动态库

1.命名:libxxx.so;
2.特点
(1)动态库是在程序运行时才将函数链接进去:在编译的时候相当于做了个标记,在运行时去链接函数;
(2)可执行程序依赖动态库,在可执行程序运行的环境里必须存在对应的动态库;
(3)优点:升级程序简单,更新动态库不需要重新编译可执行程序;可执行程序比较小,因为在编译的时候并没有将动态库链接进去;可以实现代码的共享,对于可重入函数,只需要在内存中加载一份,使用该函数的地方可以共享;
(4)缺点:移植麻烦一点,可执行程序运行时必须依赖动态库,移植可执行程序必须把动态库一起移植过去;

5、生成静态库/动态库的指令:AR

生成静态库ar [编译选项] libxxx.a 依赖的.o文件
生成动态库ar -shared [编译选项] libxxx.so 依赖的.o文件(.o文件编译时必须加上-fPIC)
补充:编译动态库要加上-fPIC是因为动态库必须是位置无关码,因为动态库的链接地址是不定的,由链接时决定;

6、静态库/动态库的使用

(1)静态库:在使用静态库的源码里包含静态库对应的头文件;在编译可执行程序时指定静态库和静态库所在的路径(通过-l指令静态库,-L指定静态库所在路径,比如libtest.a,就是-ltest);
(2)动态库:在静态库的基础上,还需要将动态库拷贝到可执行程序所在的环境中,并在环境变量LD_LIBRARY_PATH中加上动态库的所在路径(export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/tmp/share/);
补充:LD_LIBRARY_PATH是Linux的环境变量,里面包含Linux默认的动态库搜索路径;

7、GCC常见编译选项

-E 预处理指定的源文件,不进行编译,生成.i文件 gcc -E circle.c -o circle.i
-S 编译指定的源文件,但是不进行汇编,生成.s文件
-c 编译、汇编但是不连接,生成.o文件
-o 指定输出文件的名字
-I 指定头文件的搜索路径
-fPIC 编译器生成位置无关码,生成动态库时必须选上(PIC:position-independent code)
-O0:关闭所有优化选项
-O1:第一级别优化,使用此选项可使可执行文件更小、运行更快,并不会增加太多编译时间,可以简写为-O
-O2:第二级别优化,采用了几乎所有的优化技术,使用此选项会延长编译时间
-O3:第三级别优化,在-O2的基础上增加了产生inline函数、使用寄存器等优化技术
-Os:此选项类似于-O2,作用是优化所占用的空间,但不会进行性能优化,常用于生成最终版本
-werror 把警告当错误处理,遇到警告就终止编译

8、生成静态库/动态库的步骤

(1)指定编译器的选项:头文件搜索路径、优化等级······
(2)将源文件编译成.o文件;
(3)用ar指令生成静态库/动态库;

9、生成静态/动态链接库的Makefile示例

#指定交叉编译工具链
plat ?= hi3516dv300

ifeq ($(plat),hi3516dv300)
	CROSS = arm-himix200v002-linux-
else ifeq ($(plat),x86)
	CROSS = 
else
	CROSS = arm-himix200v002-linux-
endif

# 定义变量表示具体的交叉编译工具链
CC	= $(CROSS)gcc
LD	= $(CROSS)ld
AR  = $(CROSS)ar
RM	= rm -rf
STRIP = $(CROSS)strip

#指定源文件的路径
BASE_PATH = $(PWD)/..
SRC_PATH = $(BASE_PATH)/src

#指定编译选项
AFLAGS += -r
CFLAGS += -I $(BASE_PATH)/include
CFLAGS += -O2 -werror  -fPIC

#用find命令查找所有的.c源文件的路径
C_FILES=$(shell find $(SRC_PATH) -name "*.c" -print)

#将源文件的后缀.c替换成.o,将来把每个.c文件都编译成.o文件
OBJS=$(C_FILES:%.c=%.o)

#指令静态库/动态库的名字
LIB_STATIC=libcard.a
LIB_DYNAMIC=libcard.so

#Makefile的总目标
all: $(LIB_STATIC) $(LIB_DYNAMIC) 

#生成静态库
$(LIB_STATIC): $(OBJS)
	$(AR) $(AFLAGS)  $@ $^

#生成动态库
LIB_STATIC:
	$(CC) -shared -o libcard.so $^
	
#自动匹配规则,将每个.c文件都编译成对应的.o文件
%.o : %.c
	$(CC) -o $@ $< -c  $(CFLAGS)

#清除中间产物
clean:
	-$(RM) $(OBJS)

你可能感兴趣的:(Linux编程,C语言,ubuntu,linux,运维)