【问题标题】:FORTRAN Makefile for a large project大型项目的 FORTRAN Makefile
【发布时间】:2016-07-08 22:23:52
【问题描述】:

我在 Fortran95 中开始了一个新项目,该项目应该很快就会变大(很多模块)。目前我只有

  • 输出.f90
  • moldyn.f90

output.f90 包含一个带有几个公共变量、两个公共子例程和两个私有子例程的模块。 Moldyn.f90 包含调用 output.f90 中包含的两个公共子例程的主程序。

这是我第一次处理大型项目,因此我想通过创建一个通用且易于调整的 Makefile 来尽可能地自动化编译和链接。我之前创建的 Makefile 只是“硬编码”的编译和链接语句,对于一个大型项目,我想自动化这个过程(但不使用其他工具作为 CMake)。

这是我的尝试,不幸的是它不起作用:

# ========
# Makefile
# ========

# Makefile name
MF = Makefile

# ==========
# Executable
# ==========

# Executable name
EXE = $(BINDIR)/moldyn.x

# ========
# Compiler
# ========

# Fortran compiler
FC = gfortran

# Fortran flags
FFLAGS = -O2 -Wall -Warray-bounds -fbounds-check

# ===========
# Directories
# ===========
SRCDIR = src
BINDIR = bin
OBJDIR = obj
MODDIR = mod

# ========
# Suffixes
# ========

.SUFFIXES:
.SUFFIXES: .f90 .o .mod

# ===================
# Sources and objects
# ===================

SRC = \
    $(SRCDIR)/moldyn.f90\
    $(SRCDIR)/output.f90

OBJ = $(SRC:$(SRCDIR)%.f90=$(OBJDIR)%.o)

# =====
# Rules
# =====

all:
    @echo $(SRC)
    @echo $(OBJ)

moldyn: $(OBJDIR)/.o $(EXE)

$(EXE): $(OBJ)
    $(FC) $(FFLAGS) -o $(SRCDIR)/$@ $(OBJ)

$(OBJDIR)/.o:
    $(FC) $(FFLAGS) -c $(SRC)

$(OBJ): $(MF)

# =======
# Folders
# =======

$(BINDIR):
    mkdir -p $(BINDIR)

$(OBJDIR):
    mkdir -p $(OBJDIR)

$(MODDIR):
    mkdir -p $(MODDIR)

# =====
# Clean
# =====

clean:
    rm -f src/*~
    rm -fr $(BINDIR) $(OBJDIR) $(MODDIR)

我认为混乱来自这样一个事实,即我在 src/ 文件夹中有源代码,我想在 obj/ 文件夹中创建 .o 并在 bin/ 文件夹中创建可执行文件。 .mod 文件也起作用,因为它们是在 dase 文件夹中创建的(那里有 makefile),但我真的不知道如何处理它们(这是我的第一个 Fortran 项目)。

谁能帮助我了解编译问题的来源?我得到的错误如下:

gfortran -O2 -Wall -Warray-bounds -fbounds-check -c src/moldyn.f90 

src/output.f90
src/moldyn.f90:20.6:

  use output, only: title, gpl
      1
Fatal Error: Can't open module file 'output.mod' for reading at (1): No such file or directory
make: *** [obj/.o] Error 1

并且似乎与 .mod 文件有关。

【问题讨论】:

  • 查看您的目录并查看文件的放置位置。编译步骤如何将 *.o 文件放入 $(OBJDIR) 中。可能是 *.o 文件位于 $(SRC) 目录中,而不是 $(OBJDIR)。
  • @KeithSmith 使用make all 我测试了路径,命令OBJ = $(SRC:$(SRCDIR)%.f90=$(OBJDIR)%.o) 按预期工作,即OBJ 中的值都以$(OBJDIR)/ 开头。但是 *.o 和 *.mod 是在当前目录中创建的。
  • 手工制作的 Makefile 是一场噩梦。 CMake 是大型项目的不错选择。我改用 SCons,因为我不想再学习另一种语言,而 SCons 只是 Python。

标签: makefile compiler-errors fortran gnu-make linker-errors


【解决方案1】:

我认为您的 makefile 问题在这篇 Stack Overflow 帖子中得到了很好的回答: Automatic Ordering of Obejct Files "*.o" in a Fortran Makefile

就您的具体错误而言,您需要在 gfortran 调用中包含 -I $(OBJDIR) 以告诉它您的 *.mod 文件在哪里。

gfortran -O2 -Wall -Warray-bounds -fbounds-check -I obj/ -c src/moldyn.f90

不过,请重新考虑 CMake。我们有一个非常大的 Fortran/C/C++ 代码库(约 800,000 行 Fortran/约 900,000 行 C/C++)并且对 CMake 非常满意。对我们来说,我们需要在 Windows/Mac/Linux 上构建/测试/部署,而 CMake 为我们完成了这些工作。我们还使用 GNU 和 Intel 编译器,它可以处理这些问题。我们还有调试和发布版本以及覆盖测试和内存泄漏版本。它还提供了一个带有 CTest 的测试工具和一个带有 CDash 的持续集成仪表板。一旦您的项目变得更大,您就可以迁移到它。因此,当您的项目很小时,请使用 Makefile 方法。如果你开始感觉到限制,那么不要把很多时间花在一些精心制作的 Makefile 生成方案上——我一直在走这条路。只需切换到 CMake——这里有一个指向 example of CMake for Fortran 的奖励链接。当我提供不请自来的建议时,不要进行“源代码”构建。原因在this blog post by Jussi Pakkanen上总结得很好。

【讨论】:

    【解决方案2】:

    您可以使用VPATH = <path> 告诉make 在哪里可以找到源文件。您将需要一个编译器标志来更改 .mod 文件的构建位置。对于gfortran,标志是-J<path>

    要指定.o 文件的构建位置,您可以执行以下操作:

    # Current directory
    BASEPATH = $(shell pwd)
    
    # Absolute paths to the directories
    SRCDIR = $(BASEPATH)/src
    BINDIR = $(BASEPATH)/bin
    OBJDIR = $(BASEPATH)/obj
    MODDIR = $(BASEPATH)/mod
    
    # Put module files in their own directory
    FFLAGS += -J$(MODDIR)
    
    # Search path for source code
    VPATH = $(SRCDIR)
    
    ...
    
    # Using VPATH, so no need to give full path to source
    SRC = \
        moldyn.f90\
        output.f90
    
    # Replace .f90 with .o
    OBJ_O = $(patsubst %.f90,%.o,$(SRC)
    # Prepend object path
    OBJ = $(addprefix $(OBJPATH)/,$(OBJ_O))
    
    ...
    
    $(OBJDIR)/%.o: %.f90
        # Check object and binary directories exist, make them if necessary
        # We can use the $(@D) magic variable to get the directory
        @mkdir -p $(@D)
        # $@ means the left-hand side of the recipe
        # $< means all of the right hand side
        $(FC) $(FFLAGS) -c -o $@ $<
    

    按照 redwizard792 的建议,您可以使用 this answer 自动生成 .o 文件的依赖项。如果这样做,您还需要从该答案中包含添加到您的 makefile 中。

    【讨论】:

      猜你喜欢
      • 2014-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-22
      • 2016-08-14
      • 1970-01-01
      • 2017-12-21
      • 2014-10-31
      相关资源
      最近更新 更多