[轉]在linux下如何使用Makefile對fortran程序進行編譯


-

在linux下寫過不少的fortran程序,但很少寫makefile文件,通常情況下我是手動用ifort或pgf90進行編譯,雖然也在大型程序中寫過一些代碼,但因為都有現成的makefile文件,我也只是修改一下配置參數,先make clean,再make,只要生成可執行程序就算搞定了。今天心血來潮,自己寫了幾個Makefile,供大家參考。


一、不用Makefile的直接編譯
比如有2個簡單程序,主程序為main.F90,子程序為sub.F90. 如果直接編譯的話,鍵入
ifort main.F90 sub.F90
就可以生成一個a.out文件,即為可執行程序了。
你也可以指定一個可執行程序的名字,如
ifort main.F90 sub.F90 -o bin.exe
則可以生成bin.exe,實際上與a.out是一樣的。
當然,如果你不喜歡用子程序,或者子程序和主程序都寫在一個F90文件中(如main.F90),上述的編譯語句直接省掉sub.F90就行了,但不推薦這樣寫程序,特別是程序比較大的情況下,一是程序間的關系容易理不清,另外風險也大,萬一哪天把程序刪掉了或改錯了,損失可就大了。


上面的編譯也可以分兩步進行,
ifort -c main.F90 sub.F90
ifort -o main.exe main.o sub.o
第一行稱為編譯compile,第二行稱為鏈接link。這個過程最后還是生成main.exe,第一步生成main.o和sub.o兩個目標文件,第二步將目標文件鏈接成可執行文件main.exe。這看起來有點多此一舉,如果在程序不大,子程序不多的情況下,這確實是浪費體力,但如果有幾十或幾百個子程序(如WRF模式),編譯一次可能要花幾十分鍾或幾個小時,那么可以單獨編譯修改的那個程序生成相應的.o文件就行了,然后再執行第二步鏈接,這樣可以節省不少時間。也就是說,第一步的編譯可以分開進行:
ifort -c main.F90
ifort -c sub.F90
在有幾個子程序的情況下,這樣分開編譯雖然花點工夫,還是值得的,因為程序很難一蹴而就,總要調試,總要修改,分解成若干子程序逐個編譯更容易各個擊破。


二、簡單的Makefile文件
我們仍以一行編譯語句為例,將其寫在Makefiel文件中。使用vi建立一個新的Makefile文件,在其中寫入:
main.exe: main.F90 sub.F90
ifort main.F90 sub.F90 -o main.exe
就可以了。你把已有的main.exe刪掉,鍵入make,你會發現生成了新的main.exe. 這就是Makefile文件了,簡單吧!
如果報錯的話,你看看是不是Makefile中的第二行之前沒有用tab鍵空格,必須用tab鍵,用空格鍵是不行嘀。


下面我們再來解釋一下Makefile的寫作格式
簡而言之,Makefile的格式就是二行,第一行定義目標文件和依賴文件,:之前的main.exe為目標文件,:之前后的main.F90和sub.F90為依賴文件。第二行為執行語句,與手動編譯相同。好像第一行還是多此一舉,還不如手動編譯只要一行就搞定,我們看完下一個例子再來討論這一點。


那么對於編譯和鏈接分解的語句如何寫呢。重新打開Makefile文件,將原來的兩行刪去,再寫入:
main.exe:main.o sub.o
ifort -o main.exe main.o sub.o
main.o:main.F90
ifort -c main.F90
sub.o:sub.F90
ifort -c sub.F90
這就可以了,是不是還發現一點異樣?語句的順序和前面手動編譯時是反的,先是鏈接語句,后是編譯語句,這一點我們稍后解釋。還是先運行一下吧,將原來的.exe和.o文件都刪掉,執行make后,是不是可以看到新生成了.o和.exe文件。你還可以試試將其中的main.F90進行修改(比如加一行空格,或加一條注釋),再執行make,可以發現,僅更新了main.o和main.exe,而sub.o還是原來的生成時間。這就是make的優勢。


我們先來解釋一下目標文件和依賴文件的關系,如果任意一個依賴文件發生了改變,則要運行下一行的執行語句,即生成新的目標文件,否則跳過執行文件。在make執行的過程中,實際上並不是順序執行的,而是先把所有的目標文件和依賴文件檢查一遍,從最頂層的目標文件開始,再分解檢查各個子目標,將發生變化的依賴文件標記下來,然后再從下向上執行標記語句,最后更新頂層的目標文件。所以寫makefile文件的順序必須是先寫頂層的目標文件,也就是連接生成的.exe文件,然后再分別寫編譯要生成的.o文件,這與手動編譯時是不同的。make的工作方式就象警察辦案一樣,先偵察推演,收集證據;再順藤摸瓜,收網抓賊。


三、復雜一點的Makefile文件
下面這個例子中用到了變量定義和靜態模式
SOURS = main.F90 sub.F90
OBJS = main.o sub.o
BIN = main.exe
F90 = ifort


${BIN}:${OBJS}
${F90} -o ${BIN} ${OBJS}
${OBJS}: %.o :%.F90
${F90} -c $<
先來說說變量定義,這個地球人都知道,只要會寫shell腳本的人都能看的懂,如果子程序不多的話也沒必要定義來定義去的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM