2017-10-04 34 views
0

到現在爲止,我用下面的Makefile拿到2個可執行文件在同一目錄中的所有來源:修改Makefile來得到一個簡單的形式爲2個可執行

GFORTRAN = gfortran -Wall 
CC   = gcc -Wall 
MPI_FORTRAN = mpif90 -Wall 
MPI_CC  = mpicc -Wall 
LD = -lm 

.SUFFIXES : .o .f90 

all: explicitSeq explicitPar 

explicitSeq : explicitSeq.o explUtilSeq.o 
     $(GFORTRAN) -o [email protected] explicitSeq.o explUtilSeq.o 

explicitSeq.o : explicitSeq.f90 
     $(GFORTRAN) -c $(*F).f90 

explUtilSeq.o : explUtilSeq.f90 
     $(GFORTRAN) -c $(*F).f90 

explicitPar : explicitPar.o explUtilPar.o updateBound.o readParam.o 
     $(MPI_FORTRAN) -o [email protected] explicitPar.o explUtilPar.o updateBound.o readParam.o 

.f90.o: 
     $(MPI_FORTRAN) -c $(*F).f90 

clean : 
     /bin/rm -f *.o explicitSeq explicitPar 

一切工作正常。現在,我想使用一個使用%.o%.f90變量並結合「$<」變量的基本表格。

我試圖讓上面的等效Makefile這樣的:

GFORTRAN = gfortran -Wall 
CC   = gcc -Wall 
MPI_FORTRAN = mpif90 -Wall 
MPI_CC  = mpicc -Wall 
LD = -lm 

SRC_SEQ = explicitSeq.f90 explUtilSeq.f90 
OBJ_SEQ = explicitSeq.o explUtilSeq.o 
SRC_PAR = explicitPar.f90 explUtilPar.f90 updateBound.f90 readParam.f90 
OBJ_PAR = explicitPar.o explUtilPar.o updateBound.o readParam.o 

all: explicitSeq explicitPar 

explicitSeq : OBJ_SEQ 
     $(GFORTRAN) -o [email protected] $< 

OBJ_SEQ: SRC_SEQ 
     $(GFORTRAN) -c $< 

explicitPar : OBJ_PAR 
     $(MPI_FORTRAN) -o [email protected] $< 

OBJ_PAR: SRC_PAR 
     $(MPI_FORTRAN) -c $< 

clean : 
     /bin/rm -f *.o explicitSeq explicitPar 

但不幸的是,輸入 「make」 產生:

make: *** No rule to make target `SRC_SEQ', needed by `OBJ_SEQ'. Stop. 

我不知道如何繞過這個錯誤。也許我應該使用依賴.f90.o:但我不知道該把它放在哪裏。對不起,如果這是一個初學者的問題,但任何幫助,歡迎。

更新1:

從Vroomfondel的建議下,我做了以下修改:

GFORTRAN = gfortran-mp-4.9 -Wall 
CC   = gcc -Wall 
MPI_FORTRAN = mpif90 -Wall 
MPI_CC  = mpicc -Wall 
LD = -lm 

SRC_SEQ = explicitSeq.f90 explUtilSeq.f90 
OBJ_SEQ = explicitSeq.o explUtilSeq.o 
SRC_PAR = explicitPar.f90 explUtilPar.f90 updateBound.f90 readParam.f90 
OBJ_PAR = explicitPar.o explUtilPar.o updateBound.o readParam.o 

all: explicitSeq explicitPar 

explicitSeq : $(OBJ_SEQ) 
     $(GFORTRAN) -o [email protected] $< 

$(OBJ_SEQ): $(SRC_SEQ) 
     $(GFORTRAN) -c $< 

explicitPar : $(OBJ_PAR) 
     $(MPI_FORTRAN) -o [email protected] $< 

$(OBJ_PAR): $(SRC_PAR) 
     $(MPI_FORTRAN) -c $< 

clean : 
     /bin/rm -f *.o explicitSeq explicitPar 

和我得到的錯誤:

gfortran-mp-4.9 -Wall -c explicitSeq.f90 
gfortran-mp-4.9 -Wall -c explicitSeq.f90 
gfortran-mp-4.9 -Wall -o explicitSeq explicitSeq.o 
Undefined symbols for architecture x86_64: 
    "_computenext_", referenced from: 
     _MAIN__ in explicitSeq.o 
    "_initvalues_", referenced from: 
     _MAIN__ in explicitSeq.o 
ld: symbol(s) not found for architecture x86_64 
collect2: error: ld returned 1 exit status 
make: *** [explicitSeq] Error 1 

正如你可以看到,文件explicitSeq.f90被編譯2次:它是從修改後的Makefile中預期的行爲嗎?感謝您的幫助

更新2:

我想我可以使用以下規則:

%.o: %.f90 
    $(GFORTRAN) -o [email protected] -c $< 

但問題是,我還編譯$(MPI_FORTRAN)一些*.f90文件。我不知道如何區分2例obj的文件(*的.o)(與gfortan編譯器和編譯器mpif90)

更新3:

我有差不多的解決方案。我做了:

GFORTRAN = gfortran -Wall 
CC   = gcc -Wall 
MPI_FORTRAN = mpif90 -Wall 
MPI_CC  = mpicc -Wall 
LD = -lm 

DIR_SEQ = tmpSeqDir 
DIR_PAR = tmpParDir 
SRC_SEQ = explicitSeq.f90 explUtilSeq.f90 
OBJ_SEQ = $(addprefix $(DIR_SEQ)/,$(SRC_SEQ:.f90=.o)) 
SRC_PAR = explicitPar.f90 explUtilPar.f90 updateBound.f90 readParam.f90 
OBJ_PAR = $(addprefix $(DIR_PAR)/,$(SRC_PAR:.f90=.o)) 

all: explicitSeq explicitPar 

explicitSeq: $(OBJ_SEQ) 
     $(GFORTRAN) -o [email protected] $^ 

$(DIR_SEQ)/%.o: $(DIR_SEQ)/%.f90 
     $(GFORTRAN) -c $< -o [email protected] 

explicitPar: $(OBJ_PAR) 
     $(MPI_FORTRAN) -o [email protected] $^ 

$(DIR_PAR)/%.o: $(DIR_PAR)/%.f90 
     $(MPI_FORTRAN) -c $< -o [email protected] 

$(OBJ_SEQ): | $(DIR_SEQ) 
$(OBJ_PAR): | $(DIR_PAR) 

$(DIR_SEQ): 
     mkdir [email protected] 
     cp -pf $(SRC_SEQ) [email protected] 

$(DIR_PAR): 
     mkdir [email protected] 
     cp -pf $(SRC_PAR) [email protected] 

clean: 
     rm -f *.o explicitSeq explicitPar 
     rm -f $(DIR_SEQ)/* 
     rmdir $(DIR_SEQ) 
     rm -f $(DIR_PAR)/* 
     rmdir $(DIR_PAR) 

不幸的是,我必須連續輸入3次「make」才能獲得2個可執行文件。下面是這3個 「品牌」 輸出:

第一 「讓」:

$ make 
mkdir tmpSeqDir 
cp -pf explicitSeq.f90 explUtilSeq.f90 tmpSeqDir 
gfortran -Wall -o explicitSeq tmpSeqDir/explicitSeq.o tmpSeqDir/explUtilSeq.o 
gfortran: error: tmpSeqDir/explicitSeq.o: No such file or directory 
gfortran: error: tmpSeqDir/explUtilSeq.o: No such file or directory 
Makefile:17: recipe for target 'explicitSeq' failed 
make: *** [explicitSeq] Error 1 

二 「作」:

$ make 
gfortran -Wall -c tmpSeqDir/explicitSeq.f90 -o tmpSeqDir/explicitSeq.o 
gfortran -Wall -c tmpSeqDir/explUtilSeq.f90 -o tmpSeqDir/explUtilSeq.o 
gfortran -Wall -o explicitSeq tmpSeqDir/explicitSeq.o tmpSeqDir/explUtilSeq.o 
mkdir tmpParDir 
cp -pf explicitPar.f90 explUtilPar.f90 updateBound.f90 readParam.f90 tmpParDir 
mpif90 -Wall -o explicitPar tmpParDir/explicitPar.o tmpParDir/explUtilPar.o tmpParDir/updateBound.o tmpParDir/readParam.o 
gfortran: error: tmpParDir/explicitPar.o: No such file or directory 
gfortran: error: tmpParDir/explUtilPar.o: No such file or directory 
gfortran: error: tmpParDir/updateBound.o: No such file or directory 
gfortran: error: tmpParDir/readParam.o: No such file or directory 
Makefile:23: recipe for target 'explicitPar' failed 
make: *** [explicitPar] Error 1 

三 「作」:

$ make 
mpif90 -Wall -c tmpParDir/explicitPar.f90 -o tmpParDir/explicitPar.o 
mpif90 -Wall -c tmpParDir/explUtilPar.f90 -o tmpParDir/explUtilPar.o 
mpif90 -Wall -c tmpParDir/updateBound.f90 -o tmpParDir/updateBound.o 
mpif90 -Wall -c tmpParDir/readParam.f90 -o tmpParDir/readParam.o 
mpif90 -Wall -o explicitPar tmpParDir/explicitPar.o tmpParDir/explUtilPar.o tmpParDir/updateBound.o tmpParDir/readParam.o 

是否可以只做一個簡單的「make」來編譯所有,而不必輸入3次「make」?

我懷疑行cp -pf $(SRC_SEQ) [email protected]cp -pf $(SRC_PAR) [email protected]導致相對於$(DIR_SEQ)/%.f90$(DIR_PAR)/%.f90相關性的問題。

謝謝,也許我會開始賞金。

+0

您需要在訪問(讀取)它們時在'$()'中寫入變量名稱。沒有'$()'的表單只用於賦值。 – Vroomfondel

+0

@Vroomfondel你可以看看我的**更新1 **和**更新2 **嗎? – youpilat13

+0

規則'explicitSeq:$(DIR_SEQ)/ $(OBJ_SEQ)'將計算爲'explicitSeq:tmpSeqDir/explicitSeq.f90 explUtilSeq.f90'(注意第二個文件的丟失路徑),這不是我們想要的。然而,爲什麼它聲稱不知道如何做到這一點,我不知道。稍後再研究它。順便說一句,你正在使用? – Vroomfondel

回答

0

雙編譯的問題來自於規則:

$(OBJ_SEQ): $(SRC_SEQ) 
     $(GFORTRAN) -c $< 

$<名稱僅第一先決條件,其在所有情況下是explicitSeq.f90 - 你的其他目標文件不被更新,因爲在所有他們的食譜不要創建目標!

對於第二個問題:這是一個棘手的問題。 A 非常棘手的一個恕我直言。實際上,您正在尋求一種多架構構建,其中增加了複雜性,您希望這兩個體系結構都構建在一個makefile中。我沒有足夠的精力去佈置多拱橋解決方案,更不用說在一個stackoverflow答案中,但是現在我想出了一個解決方案,它違反了Paul's third rule然而它的簡單。 如需進一步閱讀,請參閱Paul's Multiarchitecture Builds,其中有很多很好的信息。

現在解決方案:您需要一種方法來指定應由「其他」編譯器編譯的文件。由於文件名結尾顯然沒有選項我不知道是否有必要編譯同一個文件以及其他編譯器,我建議使用不同的目錄文件。由於我沒有Fortran源代碼和編譯器,我使用C和C++來接管順序和並行代碼的角色。我認爲你可以很容易地適應您的系統:

.PHONY: all  
all: objectoriented procedural 

PROC_DIR = proc 
OBJ_DIR = oo 

OBJ_SRC = cppbaz.c 
PROC_SRC = bar.c 
SHARED_SRC = foo.c 

# deduce the object files from the sources 
OBJECT = $(addprefix $(OBJ_DIR)/,$(OBJ_SRC:.c=.o) $(SHARED_SRC:.c=.o)) 
PROCED = $(addprefix $(PROC_DIR)/,$(PROC_SRC:.c=.o) $(SHARED_SRC:.c=.o)) 

# pattern rules for the compilation - as we violate Paul's 3rd rule, we 
# need to give these, otherwise make executes empty recipes: 
$(OBJ_DIR)/%.o: %.c 
    g++ -c -o [email protected] $< 

$(PROC_DIR)/%.o: %.c 
    gcc -c -o [email protected] $< 

# targets for the binaries 
objectoriented: $(OBJECT) 
    @echo linking $^ 
    -gcc -o [email protected] $^ 

procedural: $(PROCED) 
    @echo linking $^ 
    -gcc -o [email protected] $^ 

# create destination directories, if not present 
$(OBJECT): | $(OBJ_DIR) 
$(PROCED): | $(PROC_DIR)  
$(OBJ_DIR): 
    mkdir [email protected] 
$(PROC_DIR): 
    mkdir [email protected] 

一兩件事:我使用的VPATH找到源文件:

make VPATH=srcdir_a:srcdir_b:othersrcdir這告訴make在哪裏可以找到所需要的源文件彙編。

+0

- @ Vroomfondel感謝您的幫助。我不明白'$(OBJECT):|行$(OBJ_DIR)'和'$(PROCED):| $(PROC_DIR)':他們做什麼?我理解'$(OBJ_DIR)'這一行: mkdir $ @':它創建了具有$(OBJ_DIR)名稱的目錄,但我在文檔中沒有看到上述註釋中的兩行。 Regards – youpilat13

+0

'target:| order-only-prerequisite'這使得目標依賴於_existence_而不是先決條件的_timestamp_。只有訂單應改名爲只存在恕我直言。對於目錄,這正是我們想要的:如果它在那裏,不管最後一次修改如何,都可以,創建它。 – Vroomfondel

+0

- @ Vroomfondel我明白了:正如你可以在** UPDATE 3 **和你的解決方案中看到的那樣,我的錯誤是我沒有意識到規則'$(OBJ_DIR)/%。o:%.c'確定自動根據定義的$(OBJ_DIR)/%。o'目標文件自動將正確的源代碼* .c作爲函數:我認爲'%.c'對應於所有'* .c'sources(Seq和Par來源)我的目錄。非常感謝 ! – youpilat13

相關問題