1. 目的
最近工作中需要用到静态库和动态库,以前这些都学习过的,但很久没用,就忘记了,这次学习决定要记下来。
2. 说明
本文要生成的静态库名称是libopt.a,动态库名称是libopt.so。首先先介绍下本文中的创建库的文件路径:
$ /testlib/tree
.
├── include ==>这个是库的头文件,到时候安装库的时候需要拷贝到用户指定的头文件路径中,方便引用。本文是/usr/local/include/opt/
│ ├── add.h
│ └── mul.h
├── Makefile ==》makefile,这个makefile用于创建动态库的。
├── Makefile_lib_a ==》 这个makefile用于创建静态库,这里我是分别测试学习的,所以被重命名了。
├── objs ==》这个目录用于存放编译生成的.o文件和临时存放库文件.
└── src ==》生成库文件的源码
├── add.c
└── mul.c
源码和头文件中内容都很简单,add.c提供两个整数相加的函数,add.h提供函数申明,供外部使用。mul.c和mul.h类似,代码就不贴了。
3. 静态库生成与使用
3.1 Makefile文件
CC= gcc
AR= ar
CFLAG=-Wall -Wpointer-arith -Wno-unused-parameter -Werror -g
INC_DIR=include/
SRC_DIR=src/
OBJS_DIR=objs/
TARGET_LIB=$(OBJS_DIR)libopt.a ==》静态库名称
MY_LIB_DIR=/usr/local/lib/
MY_INC_DIR=/usr/local/include/
OUTPUT_FILES= $(OBJS_DIR)add.o $(OBJS_DIR)mul.o
$(TARGET_LIB):$(OUTPUT_FILES)
$(AR) -r $(TARGET_LIB) $(OUTPUT_FILES) ==》最关键的命令,生成静态库
$(OBJS_DIR)add.o: $(INC_DIR)add.h $(SRC_DIR)add.c
$(CC) -c $(CFLAGS) -o $(OBJS_DIR)add.o $(SRC_DIR)add.c
$(OBJS_DIR)mul.o: $(INC_DIR)mul.h $(SRC_DIR)mul.c
$(CC) -c $(CFLAGS) -o $(OBJS_DIR)mul.o $(SRC_DIR)mul.c
install:
test -f $(TARGET_LIB) || make
cp -rf $(INC_DIR) $(MY_INC_DIR)opt/ ==》 将库和头文件拷贝到指定的目录
cp $(TARGET_LIB) $(MY_LIB_DIR)
clean:
rm -f objs/*
3.2 使用方法
编译一个简单的程序main.c,里面包含库里面的头文件(make install时已经拷贝到/usr/local/include/目录了),该程序内部调用静态库中提供的接口,编译时,应该带上库的选项,如下:
gcc -o main main.c -lopt ==>我们生产的库名称是libopt.a,那么此处我们应该用-lopt,-l 其实是一个gcc的选项,用于指定静态库。接着运行main可以成功得到预期的结果。
4. 动态库生成与使用
4.1 Makefile文件
CC= gcc
CFLAG=-fPIC -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g # -fPIC for share lib
==》这里编译选项中增加了 -fPIC,也是生成动态库的必须项。
INC_DIR=include/
SRC_DIR=src/
OBJS_DIR=objs/
TARGET_LIB=$(OBJS_DIR)libopt.so
MY_LIB_DIR=/usr/local/lib/
MY_INC_DIR=/usr/local/include/
OUTPUT_FILES= $(OBJS_DIR)add.o $(OBJS_DIR)mul.o
$(TARGET_LIB):$(OUTPUT_FILES)
$(CC) -shared -o $(TARGET_LIB) $(OUTPUT_FILES) ==》 与生成静态库不一样,生成动态库使用该语句。
$(OBJS_DIR)add.o:$(INC_DIR)add.h $(SRC_DIR)add.c
$(CC) -c $(CFLAG) -o $(OBJS_DIR)add.o $(SRC_DIR)add.c
$(OBJS_DIR)mul.o:$(INC_DIR)mul.h $(SRC_DIR)mul.c
$(CC) -c $(CFLAG) -o $(OBJS_DIR)mul.o $(SRC_DIR)mul.c
install:
test -f $(TARGET_LIB) || make
cp -rf $(INC_DIR) $(MY_INC_DIR)opt/
cp $(TARGET_LIB) $(MY_LIB_DIR)
clean:
rm -f objs/*
4.2 使用方法
同样,还是用刚刚的测试程序main.c,重新编译该文件,只不过这次使用动态库,而不使用静态库,编译方法如下:
gcc -o main main.c /usr/local/lib/libopt.so ==>我们生成的库名称是libopt.so,且make install时拷贝到/usr/local/lib/目录了,注意这里使用动态库一定要加路径,否则会出现找不到库的提示,除非环境变量中有这个路径,比如,我这里将/usr/local/lib/这个路径加到环境变量中去就可以省略。
5. 总结
使用静态库时实际上是直接将其代码嵌入到目标程序中,编译完成后静态库删除不会给目标程序造成影响。而动态库则不一样,是在程序运行的时候才加载的,因此需即使编译完成后也要保证动态库的完整性。