2016-07-27 210 views
0

我的程序是使用英特爾MKL的mpi程序。簡單,讓我們假設有main.f90 a.f90 b.f90其中a.f90包含模塊調用mymod被別人需要Makefile爲Fortran 90生成導致無法解析的外部符號

通常我會編譯它像這樣

mpiifort *90 /fast /Qmkl /MD -o main.exe 

我只是做兩次,因爲是第一次,有將缺少mymod.mod

現在我想使用makefile,因爲我想減少重新編譯時間。我是這樣寫的

IFORT = /fast 
MKL =/Qmkl 
LDFLAGS = /MD 
main:main.obj b.obj 
    mpiifort $(IFORT) $(MKL) $(LDFLAGS) $< -o [email protected] 
mymod.mod:a.f90 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 
main.obj:main.f90 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 
b.obj:b.f90 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 

但是,這裏肯定有問題。我得到了一堆unresolved external symbol。哪裏不對?

+2

我不是makefile專家,但它看起來像你的'main'目標沒有明確依賴'mymod.mod',所以這不會被構建。我也可能完全錯了 –

回答

0

首先,其他人可能會寫一個更好/更完整的答案(或指示我們一個),我會歡迎,但下面我提供了一個非常簡單的例子。

現在,我們可以找出錯誤的(可能)來源:如果我們只是touch更換編譯命令,我們可以製作一個簡單的例子,演示了這個問題

main:main.obj b.obj 
     touch [email protected] 
mymod.mod:a.f90 
     touch [email protected] 
main.obj:main.f90 
     touch [email protected] 
b.obj:b.f90 
     touch [email protected] 

然後如果我們構建我們的「源文件」與

>touch main.f90 b.f90 a.f90 

那麼我們可以嘗試建立我們main可執行:

>make main 

將輸出:

touch main.obj 
touch b.obj 
touch main 

注意這如何不創建mymod.mod文件。這意味着在你的情況下a.f90在編譯main時沒有被編譯,因此所需的symobols不可用(即當鏈接有未定義的函數/例程等,因爲a.obj不可用)。如果我們現在表明,main取決於mymod.mod通過調整我們的makefile是

main:main.obj b.obj mymod.mod 
     touch [email protected] 
mymod.mod:a.f90 
     touch [email protected] 
main.obj:main.f90 
     touch [email protected] 
b.obj:b.f90 
     touch [email protected] 

我們現在可以嘗試建立main(後首先做rm *.obj mymod.mod main清理),我們得到:

>make main 
touch main.obj 
touch b.obj 
touch mymod.mod 
touch main 

所以我們已成功獲得make以構建mymod.mod目標作爲建築main的一部分。請注意,實際上,您可能希望確保某些目標先於其他目標(例如,您可能想在b.f90之前編譯a.f90)。您可以使用依賴項列表來執行此操作,您可能希望自動生成這些列表(請參閱this question)。

+0

非常感謝d_1999。我找出了一種更簡單的方法:) – user15964

0

我想出一個辦法,那就是一種自動的,如果我們使用英特爾Fortran

英特爾Fortran提供了一個名爲gen-dep一個選項,它會自動將可用於生成文件分析,輸出相關信息。因此,只要運行下面的命令,如果由於缺少MOD文件的錯誤消息,只要運行它兩次

mpiifort *90 /Qmkl /gen-dep > dependency.txt 

我們得到dependency.txt。打開它,我們會發現像這樣的東西

mpifc.bat for the Intel(R) MPI Library 5.1.2 for Windows* 
Copyright(C) 2007-2015, Intel Corporation. All rights reserved. 

mymod.mod : \ 
    a.f90 

a.obj : \ 
    a.f90 

b.obj : \ 
    b.f90 mymod.mod 

main.obj : \ 
    main.f90 \ 
    c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi_base.mod \ 
    c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi_sizeofs.mod \ 
    c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi_constants.mod \ 
    c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi.mod \ 
    mymod.mod 

Microsoft (R) Incremental Linker Version 14.00.23026.0 
Copyright (C) Microsoft Corporation. All rights reserved. 

-out:a.exe 
-subsystem:console 
"-libpath:c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mkl\lib\intel64_win" 
"/LIBPATH:c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\lib\release_mt" 
"/LIBPATH:c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\lib" 
impi.lib 
a.obj 
b.obj 
main.obj 

那些與mpi相關的模塊是靜態的,所以只需將其刪除即可。一些簡單的文字處理後(使用正則表達式將是一個不錯的選擇),使之更加清晰和緊湊,我們可以得到一個正確的Makefile這樣的(我有固定在我的問題後的一些錯誤)

IFORT = /fast 
MKL =/Qmkl 
LDFLAGS = /MD 
a: a.obj b.obj main.obj 
    mpiifort $(IFORT) $(MKL) $(LDFLAGS) $^ -o [email protected] 
mymod.mod : a.f90 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 
a.obj : a.f90 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 
b.obj : b.f90 mymod.mod 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 
main.obj : main.f90 mymod.mod 
    mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $< 
+0

儘管如此,它仍然會給項目引入一個新文件帶來很大的痛苦。這就是爲什麼我不再使用'make'作爲Fortran的原因。有更好的自動構建工具可用,'cmake','scons'和'waf'。 –

+0

@VladimirF您好,VladimirF。幾年前,我認爲makefile是不必要的。幾個月前我開始使用makefile,因爲它可以方便地定製不同的工作模式:構建,清理等。幾天前,我厭倦了重新編譯,因爲我正在密切追蹤一個bug,我必須編寫一個更好的makefile來指定依賴關係。也許在不久的將來,我會像你一樣完全厭倦makefile:)但順便說一句,你想在cmake或其他Fortran工具上添加一個簡單的例子來比較傳統方法嗎?我在這個網站上搜索,沒有找到任何問題的好答案。 – user15964

+0

把任何東西放在這裏都是無關緊要的。有很多關於cmake的問題http://stackoverflow.com/search?q=cmake%2Bfortran和scons在github上找到一些東西https://github.com/LadaF/PoisFFT/blob/master/src/SConstruct(this一個是我的)。還有一個cmake文檔站點http://stackoverflow.com/documentation/cmake/topics –

相關問題