【问题标题】:how to compile multi-folder Fortran Project having interfaces, modules and subroutines如何编译具有接口、模块和子例程的多文件夹 Fortran 项目
【发布时间】:2021-11-28 22:15:58
【问题描述】:

我是 Fortran 新手。我正在做一个研究项目,我正在使用一个开源项目,该项目有多个文件分布在多个文件夹中。我找到了每个程序的依赖关系,但不知道如何编译它们。

我的源代码分布在三个文件夹中。 a) 模块 b) 接口 c) 子程序

我想在 subroutines 文件夹中运行一个名为“Main.f90”的程序,该程序依赖于模块和接口文件夹中的源代码。

我正在使用eclipse进行文件夹结构和makefile进行编译。

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

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

    .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

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

    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 已经编译。为什么在使可执行文件说未定义引用时出现错误?我错过了什么?

【问题讨论】:

    标签: module fortran gfortran subroutine


    【解决方案1】:

    你可以做一个看起来像这样的 Makefile

    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/interfaces/subroutines/ 的根目录下编译你的源代码,你只需要设置VPATH 那样。

    如果您有很多对象并且不想手动编写所有内容,则可以使用以下技巧检索它们

    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来获取你的模块的文件名。

    【讨论】:

    • 谢谢 MBR 您的 makefile 对我来说很有意义。我试图写,但无法通过运行程序。问题是我为几个子例程创建了所有接口,这些接口使用“USE”关键字列在 Main.f90 程序中。类似的模块也使用“USE”关键字在 Main.f90 中使用。由于有大文件,我如何动态包含和链接它们,而不是像您在答案中提到的那样列出每个文件,例如 MODOBJ = module1.o module2.o ...
    【解决方案2】:

    您可以像往常一样创建您的 Makefile。最大的问题应该是.mod 文件。解决此问题的最简单方法是创建一个单独的文件夹,用于存储和搜索这些文件。

    这可以通过-J-module 标志分别用于gfortranifort 来实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 2015-04-08
      • 2012-09-29
      相关资源
      最近更新 更多