所謂庫文件,讀者可以將其等價為壓縮包文件,該文件內部通常包含不止一個目標文件(也就是二進制文件)。值得一提的是,庫文件中每個目標文件存儲的代碼,並非完整的程序,而是一個個實用的功能模塊。庫文件的產生,極大的提高了程序員的開發效率,因為很多功能根本不需要從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