所谓库文件,读者可以将其等价为压缩包文件,该文件内部通常包含不止一个目标文件(也就是二进制文件)。值得一提的是,库文件中每个目标文件存储的代码,并非完整的程序,而是一个个实用的功能模块。库文件的产生,极大的提高了程序员的开发效率,因为很多功能根本不需要从0开发,直接调取包含该功能的库文件即可。在windows平台和linux平台下都大量存在着库。本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。
虽然库文件用于程序的链接阶段,但编译器提供有2种实现链接的方式,分别称为静态链接方式和动态链接方式,其中采用静态链接方式实现链接操作的库文件,称为静态链接库;采用动态链接方式实现链接操作的库文件,称为动态链接库。
windows和linux的二进制文件是不兼容的:
Windows下:.dll后缀为动态库,.lib后缀为静态库;
Linux下:.so后缀为动态库,.a后缀为静态库。
静态库可以简单的看成一组目标文件的集合,即很多目标文件经过压缩打包后形成的文件。比如在我们日常编程中,如果需要使用printf函数,就需要包含stdio.h的库文件,使用strlen时,又需要包含string.h的库文件,可是如果直接把对应函数源码编译后形成的.o文件直接提供给我们,将会对我们的管理和使用上造成极大不便,于是可以使用“ar”压缩程序将这些目标文件压缩在一起,形成libx.a静态库文件。
注:静态库命名格式:lib + "库名称”+ .a(后缀) 例:libadd.a就是一个叫add的静态库
对于静态库,程序在编译链接时,将库的代码链接到可执行文件中,程序运行时不再需要静态库。在使用过程中只需要将库和我们的程序编译后的文件链接在一起就可形成一个可执行文件。
使用静态库文件实现程序的链接操作,既有优势也有劣势:
- 优势是,生成的可执行文件不再需要任何静态库文件的支持就可以独立运行(可移植性强);
- 劣势是,如果程序文件中多次调用库中的同一功能模块,则该模块代码势必就会被复制多次,生成的可执行文件中会包含多段完全相同的代码,造成代码的冗余。
和使用动态链接库生成的可执行文件相比,静态链接库生成的可执行文件的体积更大。
使用oneAPI IVF(ifort)为Fortran编译静态库(gfortran同理),步骤如下:
1. 使用ifort将待编译的源代码文件(.f90)编译成二进制文件(.o)文件;
2. 使用oneAPI提供的“xiar”命令将二进制文件打包成目标库(gfortran直接使用ar),命令:
xiar rc -o libtarget.a a.o b.o c.o
3. 得到最终的静态库文件libtarget.a,同时,如果源代码文件中有模块(module),编译过程中会生成Fortran头文件(.mod),在调取静态库时也必须包含。因此最终文件包即为“.a + .mod”。
使用oneAPI IVF(ifort)在编译其他源代码文件时如果需要调用静态库内的文件,步骤如下:
此处假设源代码文件在./src/中,而静态库和头文件在./include/中,使用makefile或手动编译均可,分编译和链接两步走。
1. 编译
$(IVF) $(FFLAGS) -I./include/ -o src.o -c src.f90
2. 链接
$(LD) $(LDFLAGS) -o target src.o ./include/libtarget.a
即可完成编译。
连接过程中还可以使用另一种方式,即
$(LD) $(LDFLAGS) -o target src.o -L./include/ -ltarget