1、引言
1、Linux下的库
静态库和共享库(动态库),二者的不同点在于代码被载入的时刻不同。 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。 共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。
2、库存在的意义 库是别人写好的现有的,成熟的,可以复用的代码,你可以使用但要记得遵守许可协议。 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常。 共享库的好处是,不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例。
2、静态库 静态库的后缀是.a,它的产生分两步 Step 1.由源文件编译生成一堆.o,每个.o里都包含这个编译单元的符号表 Step 2.ar命令将很多.o转换成.a,成为静态库 动态库的后缀是.so,它由gcc加特定参数编译产生。具体方法参见后文实例。 在 GNU/linux 系统中静态链接文件实际上就是多个 .o 文件的压缩包。假设我们有 cool.h cool.c 和 some.c 文件,要得到静态链接库 libcool.a。首先使用如下指令得到相应的 object 文件 cool.o 和 some.o:
gcc -c cool.c
gcc -c some.c
用这种方法生成的 object 文件称为 PDC 即位置相关代码(position-dependence code)。再使用如下指令可以得到静态链接文件 libcool.a:
ar -r libcool.a cool.o some.o
静态链接库 libcool.a 遵从 GNU/Linux 规定的静态链接库命名规范,必须是”libyour_library_name.a”
3、动态库
在 GNU/Linux 中动态链接文件,必需通过链接器 ld 生成。假设我们有 hot.c other.c 等文件要生成动态链接库 libhot.so 。首先使用如下指令得到相应的 object 文件 hot.o 和 some.o
gcc -fPIC -c hot.c
gcc -fPIC -c other.c
参数 -fPIC 指定生成的 object 文件为位置无关代码(position-independence code),只有 PIC 可以被用作生成动态链接库。然后使用如下指令得到动态库:
ld -Bshared -o libhot.so hot.o other.o
或者可以使用编译器的ld wrapper:
gcc -shared -o libhot.so hot.o other.o
也可以使用编译器直接生成动态库:
gcc -fPIC -shared -o libhot.so hot.c other.c
这里选项 -shared 指示目标文件的类型是动态链接库,动态库的命名规范是”libyour_library_name.so”
ldd 命令可以查看一个可执行程序依赖的共享库, 例如# ldd /bin/lnlibc.so.6 => /lib/libc.so.6 (0×40021000)/lib/ld-linux.so.2 => /lib/ld- linux.so.2 (0×40000000) 可以看到ln命令依赖于libc库和ld-linux库
1、创建动态库
目录/test/ include
lib1.h
#ifndef LIB1_H #define LIB1_H void lib1function(void); void lib1_1function(void); #endiflib2.h #ifndef LIB2_H #define LIB2_H void lib2function(void); #endif 目录/test/srclib1.c
#include<stdio.h> #include "lib1.h" void lib1function(void) { printf("lib1function\n"); } void lib1_1function(void) { printf("lib1_1function\n"); }lib2.c #include<stdio.h> #include "lib2.h" void lib2function(void) { printf("lib2function\n"); }makefile CC=gcc CXX=g++ AR=ar TARGET=libmylib.a DIR=./ INCLUDE=-I../include SRC_C=$(wildcard *.c) SRC_CPP=$(wildcard *.cpp) DIR_C=$(notdir $(SRC_C)) DIR_CPP=$(notdir $(SRC_CPP)) OBJ_C=$(patsubst %.c,%.o,$(DIR_C) ) OBJ_CPP=$(patsubst %.cpp,%.o,$(DIR_CPP) ) all:$(TARGET) mv $(TARGET) ../lib $(TARGET):$(OBJ_C) $(AR) -rs $(TARGET) $(OBJ_C) $(OBJ_CPP) .cpp.o: $(CXX) -c $^ $(INCLUDE) .c.o: $(CC) -c $^ $(INCLUDE) clean: rm -rf *.o *.a
创建目录lib
执行命令 $src#./make
在目录lib下生成libmylib.a
目录/test
main.c
#include<stdio.h> #include "lib1.h" #include "lib2.h" int main(void) { lib1function(); lib1_1function(); lib2function(); return 0; }makefile CC=gcc CXX=g++ AR=ar TARGET=main DIR=. LIB=-L./lib -lmylib INCLUDE=-I./include SRC_C=$(wildcard *.c) SRC_CPP=$(wildcard *.cpp) DIR_C=$(notdir $(SRC_C)) DIR_CPP=$(notdir $(SRC_CPP)) OBJ_C=$(patsubst %.c,%.o,$(DIR_C) ) OBJ_CPP=$(patsubst %.cpp,%.o,$(DIR_CPP) ) SRC =main.c all:$(TARGET) $(TARGET): $(OBJ_C) $(OBJ_CPP) $(CC) $(OBJ_C) $(LIB) -o $(TARGET) .cpp.o: $(CXX) -c $^ $(INCLUDE) .c.o: $(CC) -c $^ $(INCLUDE) clean: rm -rf *.o $(TARGET) 执行命令 test# ./makefile
结果在test目录下生成main
运行 #./main
# ./main lib1function lib1_1function lib2function
2、创建动态库
修改两个Makefile
目录/test/src
CC=gcc CXX=g++ AR=ar TARGET=libmylib.so DIR=./ INCLUDE=-I../include SRC_C=$(wildcard *.c) SRC_CPP=$(wildcard *.cpp) DIR_C=$(notdir $(SRC_C)) DIR_CPP=$(notdir $(SRC_CPP)) OBJ_C=$(patsubst %.c,%.o,$(DIR_C) ) OBJ_CPP=$(patsubst %.cpp,%.o,$(DIR_CPP) ) all:$(TARGET) mv $(TARGET) ../lib $(TARGET):$(OBJ_C) $(CC) -shared $(OBJ_C) $(OBJ_CPP) -o $(TARGET) .cpp.o: $(CXX) -c -fpic $^ $(INCLUDE) .c.o: $(CC) -c -fpic $^ $(INCLUDE) clean: rm -rf *.o *.a test目录Makefile
CC=gcc CXX=g++ AR=ar TARGET=main DIR=. LIB=./lib/libmylib.so INCLUDE=-I./include SRC_C=$(wildcard *.c) SRC_CPP=$(wildcard *.cpp) DIR_C=$(notdir $(SRC_C)) DIR_CPP=$(notdir $(SRC_CPP)) OBJ_C=$(patsubst %.c,%.o,$(DIR_C) ) OBJ_CPP=$(patsubst %.cpp,%.o,$(DIR_CPP) ) SRC =main.c all:$(TARGET) $(TARGET): $(OBJ_C) $(OBJ_CPP) $(CC) $(OBJ_C) $(LIB) -o $(TARGET) .cpp.o: $(CXX) -c $^ $(INCLUDE) .c.o: $(CC) -c $^ $(INCLUDE) clean: rm -rf *.o $(TARGET)