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. 总结
使用静态库时实际上是直接将其代码嵌入到目标程序中,编译完成后静态库删除不会给目标程序造成影响。而动态库则不一样,是在程序运行的时候才加载的,因此需即使编译完成后也要保证动态库的完整性。
本文详细介绍了如何生成静态库libopt.a和动态库libopt.so,并阐述了它们在不同场景下的使用方法。通过配置Makefile文件,用户能够了解静态库与动态库的区别以及如何在编译和链接时正确地使用它们。

被折叠的 条评论
为什么被折叠?



