如何编译具有接口、模块和子程序的多文件夹 Fortran 项目 [英] how to compile multi-folder Fortran Project having interfaces, modules and subroutines
问题描述
我是 Fortran 的新手.我正在从事一个研究项目,在该项目中我使用了一个开源项目,该项目具有分布在多个文件夹中的多个文件.我找到了每个程序的依赖,但不知道如何编译它们.
I am new to Fortran. I am working on a research project where I am using an open source project that has several files distributed in multiple folders. i found the dependency of each programs but could not figure out how to compile them.
我将源代码分布在三个文件夹中.a) 模块b) 接口c) 子程序
I have source code distributed in three folders. a)modules b)interfaces c)subroutines
我想在 subroutines 文件夹中运行一个名为Main.f90"的程序,该程序依赖于模块和接口文件夹中的源代码.
I would like to run a program named as 'Main.f90' in subroutines folder, this program has dependency of source codes from modules and interfaces folders.
我正在使用 eclipse 进行文件夹结构和 makefile 编译.
I am using eclipse for folder structure and makefile to compile.
对此的任何帮助表示赞赏.
Any help with this is appreciated.
更新:我遵循了@MBR 和@Stefan 发布的答案,由于某种原因,VPATH 无法在源代码中找到程序,所以我在我的 Makefile 中明确给出了这些源文件夹的路径.下面是我的 make 文件脚本.
UPDATE: I followed the answer posted by @MBR and @Stefan, for some reason VPATH did not able to find programs in source code so I explicitly gave path to those source folder in my Makefile. below is my make file script.
.PHONY: Mopac_exe clean
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
SRC = src
#make main program
Mopac_exe: subroutines mopac.o
$(FORTRAN_COMPILER) mopac.o *.o -O2 -g -o bin/Mopac_exe -I Modules/
#compile all the subroutines
subroutines: interfaces
$(FORTRAN_COMPILER) -c $(SRC)/subroutines/*.F90 -J Modules/Subroutines/ -I Modules/
#compiles all the interfaces
interfaces: modules
$(FORTRAN_COMPILER) -c $(SRC)/interfaces/*.f90 -J Modules/
# build all the modules and generate .mod file in Modules directory
modules: build_vast_kind
$(FORTRAN_COMPILER) -c $(SRC)/modules/*.f90 -J Modules/
$(FORTRAN_COMPILER) -c $(SRC)/modules/*.F90 -J Modules/
# compile vastkind.f90 files and generates the .mod file in Modules directory.Every other Modules and interfaces are dependent on this.
build_vast_kind:clean
$(FORTRAN_COMPILER) -c $(SRC)/modules/vastkind.f90 -J Modules/
clean:
rm -f bin/Mopac_exe *.mod
rm -f Modules/*.mod
rm -f *.o
我编译了所有模块并放置在根文件夹的模块目录中.一切编译顺利.构建可执行文件时出现错误.我收到以下错误.
I compiled all the modules and placed in Modules directory of root Folder. All compilation goes well. I get error when I build the executable. I get following error.
gfortran mopac.o *.o -O2 -g -o bin/Mopac_exe -I Modules/
mopac.o: In function `main':
mopac.F90:(.text+0x27c1): multiple definition of `main'
mopac.o:mopac.F90:(.text+0x27c1): first defined here
getdat.o: In function `getdat_':
getdat.F90:(.text+0x22): undefined reference to `iargc_'
getdat.F90:(.text+0xf2): undefined reference to `getarg_'
symr.o: In function `symr_':
symr.F90:(.text+0xd3f): undefined reference to `symp_'
writmo.o: In function `writmo_':
writmo.F90:(.text+0x20c2): undefined reference to `volume_'
collect2: error: ld returned 1 exit status
make: *** [Mopac_exe] Error 1
`iargc_' 正在 'getdat 文件中使用,并且 iargc 已经编译.为什么在使可执行文件说未定义的引用时出错?我错过了什么?
`iargc_' is being used in 'getdat file and iargc is already compiled. why there is error while making the executable saying undefined reference? what am I missing?
推荐答案
你可以做一个像这样的 Makefile
You can do a Makefile which looks like that
F90=gfortran
FFLAGS = -O0
VPATH = modules:interfaces:subroutines:
MODOBJ = module1.o module2.o ...
your_executable: $(MODOBJ) main.o
$(F90) main.o -o your_executable
%.o:%.f90
$(F90) $(FFLAGS) -c $^ -o $@
VPATH
是你的 Makefile 将在其中寻找源文件的目录的路径,所以如果你在 modules/
的根目录中编译你的源代码,接口/
和subroutines/
,你只需要像这样设置VPATH
.
VPATH
is the paths of the directories where your Makefile will look for source files, so if you compile your source in the root directory of modules/
, interfaces/
and subroutines/
, you just have to set up VPATH
like that.
如果您有很多对象并且不想手工编写所有内容,则可以使用以下技巧检索它们
If you have many objects and you don't want to write everything by hand, you can retrieve them using the following trick
F90 = gfortran
FFLAGS = -O0
VPATH = modules:interfaces:subroutines
SRCOBJ = $(wildcard modules/*f90)
MODOBJ = $(SRCOBJ:.f90=.o)
your_executable: $(MODOBJ) main.o
$(F90) main.o -o your_executable
%.o:%.f90
$(F90) $(FFLAGS) -c $^ -o $@
Makefile 中的 wildcard
命令允许您使用小丑 *
;那么你只需要说在你将在 $(SRCOBJ)
中检索的字符串中,你想用 .o
替换 .f90
到获取模块的文件名.
The wildcard
command in a Makefile allows you to use a joker *
; then you just have to say that in the strings you will retrieve in $(SRCOBJ)
, you want to substitute .f90
by .o
to get the filenames of your modules.
这篇关于如何编译具有接口、模块和子程序的多文件夹 Fortran 项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!