如何编译具有接口,模块和子例程的多文件夹Fortran项目 [英] how to compile multi-folder Fortran Project having interfaces, modules and subroutines

查看:395
本文介绍了如何编译具有接口,模块和子例程的多文件夹Fortran项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Fortran的新手。我正在研究一个研究项目,我正在使用一个开源项目,其中有多个文件分布在多个文件夹中。我发现每个程序的依赖关系,但无法弄清楚如何编译它们。



我的源代码分布在三个文件夹中。
a)modules
b)interfaces
c)subroutines



我想在子例程文件夹中运行一个名为'Main.f90'的程序,这个程序依赖于来自模块和接口文件夹的源代码。

我使用eclipse作为文件夹结构并且使用makefile来编译。



对此有任何帮助表示赞赏。



更新:
我遵循@MBR发布的答案, @Stefan,由于某些原因,VPATH无法在源代码中找到程序,所以我明确指出了我的 Makefile 中的那些源文件夹的路径。下面是我的make文件脚本。

  .PHONY:Mopac_exe clean 

#正在使用不同的Fortran编译器
FORTRAN_COMPILER = gfortran
SRC = src

#make主程序
Mopac_exe:子程序mopac.o
$(FORTRAN_COMPILER) mopac.o * .o -O2 -g -o bin / Mopac_exe -I模块/

#编译所有子程序
子程序:接口
$(FORTRAN_COMPILER)-c $ (SRC)/子程序/ *。F90 -J Modules / Subroutines / -I Modules /

#编译所有接口
interfaces:modules
$(FORTRAN_COMPILER)-c $ (SRC)/ interfaces / *。f90 -J Modules /


#建立所有模块并在Modules目录中生成.mod文件
modules:build_vast_kind
$ (FORTRAN_COMPILER)-c $(SRC)/ modules / *。f90 -J Modules /
$(FORTRAN_COMPILER)-c $(SRC)/ modules / *。F90 -J Modules /

#编译vastkind.f90 f iles并在Modules目录中生成.mod文件。其他所有模块和接口都依赖于此。
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

我编译了所有的模块并放置在根文件夹的Modules目录下。
所有汇编都很顺利。当我构建可执行文件时出现错误。我得到以下错误。

  gfortran mopac.o * .o -O2 -g -o bin / Mopac_exe -I模块/ 
mopac。 o:在main函数中:
mopac.F90 :(。text + 0x27c1):`main'的多重定义
mopac.o:mopac.F90 :( .text + 0x27c1):first defined这里
getdat.o:在函数`getdat_'中:
getdat.F90 :( .text + 0x22):未定义的对'iargc_'的引用
getdat.F90 :( .text + 0xf2) :'getarg_'的未定义引用
symr.o:在函数`symr_'中:
symr.F90 :( .text + 0xd3f):对`symp_'的未定义引用
writmo.o:在函数`writmo_'中:
writmo.F90 :(。text + 0x20c2):对`volume_'的未定义引用
collect2:错误:ld返回1退出状态
make:*** [ Mopac_exe]错误1

'iargc_'正在'getdat文件中使用,并且iargc已经被编译。为什么在将可执行文件称为未定义引用时出现错误?我缺少什么?

解决方案

您可以做一个Makefile,看起来像那样

  F90 = gfortran 
FFLAGS = -O0
VPATH =模块:接口:子程序:
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 / interfaces / 子例程/ ,您只需设置 VPATH 如果你有很多对象,而且你不想手工编写所有东西,你可以使用以下技巧来检索它们:$ b $
$ b

b

  F90 = gfortran 
FFLAGS = -O0
VPATH =模块:接口:子程序
SRCOBJ = $(通配符模块es / * f90)
MODOBJ = $(SRCOBJ:.f90 = .o)

your_executable:$(MODOBJ)main.o
$(F90)main.o - o your_executable
%.o:%。f90
$(F90)$(FFLAGS)-c $ ^ -o $ @

Makefile中的通配符命令允许您使用小丑 * ;那么你只需要说在 $(SRCOBJ)中检索到的字符串中,你希望替换 .f90 通过 .o 来获取模块的文件名。


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.

I have source code distributed in three folders. a)modules b)interfaces c)subroutines

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.

I am using eclipse for folder structure and makefile to compile.

Any help with this is appreciated.

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_' 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?

解决方案

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 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 $@

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆