带有预编译和模块的Fortran90 Makefile

带有预编译和模块的Fortran90 Makefile,makefile,fortran,fortran90,precompile,pre-compilation,Makefile,Fortran,Fortran90,Precompile,Pre Compilation,我正在尝试编写一个Makefile来编译一个Fortran90项目,该项目由几个包含子例程和模块的源文件组成。为了使事情变得更复杂,我使用了预编译(从*.F文件创建*.for文件)。我找不到任何答案,但这可能是因为我被Makefile语法的不同风格弄糊涂了 我创建了一个精简版本来重现我的问题(可在上获得)。它包含一个主程序(sayhello.F),两个子程序在单独的源文件中(schleppe.F和schnuppi.F),以及两个模块在单独的源文件中(words\u schleppe.mod.F和

我正在尝试编写一个Makefile来编译一个Fortran90项目,该项目由几个包含子例程和模块的源文件组成。为了使事情变得更复杂,我使用了预编译(从
*.F
文件创建
*.for
文件)。我找不到任何答案,但这可能是因为我被Makefile语法的不同风格弄糊涂了

我创建了一个精简版本来重现我的问题(可在上获得)。它包含一个主程序(
sayhello.F
),两个子程序在单独的源文件中(
schleppe.F
schnuppi.F
),以及两个模块在单独的源文件中(
words\u schleppe.mod.F
words\u schnuppi.mod.F
)。可执行文件是
hello

我能够用一个简单的Makefile构建它,并且避免了预编译。此文件(Makefile_simple)如下所示:

FCOM=gfortran

CPPFLAGS=-E
COMPFLAGS=

EXE=hello

SOURCES=sayhello.F schleppe.F schnuppi.F
MODS=words_schleppe.F words_schnuppi.F

OBJS=$(SOURCES:.F=.o)
MODOBJS=$(MODS:.F=.o)

# this may also be replaced by the ar command (creating archive)
all: $(MODOBJS) $(OBJS)
    $(FCOM) $(OBJS) $(MODOBJS) -o $(EXE)

%.for: %.F
    rm -f $*.for
    $(FCOM) $(CPPFLAGS) $*.F > $*.for

$(MODOBJS): %.o: %.for
    $(FCOM) -c -o $@ $(COMPFLAGS) $*.for

$(OBJS): %.o: %.for
    $(FCOM) -c -o $@ $(COMPFLAGS) $*.for

# clean: remove .for, .o, .do, and .stb files
.PHONY: clean
clean:
    -rm -f *.for *.o *.stb *.mod
FCOM=gfortran
EXE=你好
标准:
$(FCOM)-c单词\u schleppe.mod.F
$(FCOM)-c单词\u schnuppi.mod.F
$(FCOM)-c schleppe.F
$(FCOM)-c schnuppi.F
$(FCOM)words\u schleppe.mod.o words\u schnuppi.mod.o schleppe.o schnuppi.o sayhello.F-o$(EXE)
.假冒:干净
清洁:
rm$(EXE)*.o*.mod
然而,我的项目将比这个大一点,所以我想利用更复杂的Makefile的神秘特性来定义规则。关键是:我想将源文件
*.F
预编译成
.for
。在这里,我还没有定义从模块创建
.mod
文件并构建整个过程的规则。不考虑模块,我会在github存储库中使用以下Makefile(
Makefile\u complex
)运行它:

FCOM=gfortran
CPPFLAGS=-e
COMPFLAGS=
EXE=你好
SOURCES=sayhello.F schleppe.F schnuppi.F
OBJS=$(来源:.F=.o)
全部:$(OBJS)
#这也可以由ar命令(创建存档)代替
$(FCOM)$(OBJS)-o$(EXE)
%。对于:%
rm-f$*。适用于
$(FCOM)$(CPPFLAGS)$*.F>$*。用于
$(OBJS):%o:%用于
$(FCOM)-c-o$@$(COMPFLAGS)$*。用于
#清除:删除.for、.o、.do和.stb文件
.假冒:干净
清洁:
-rm-f*.for*.o*.stb*.mod

为了在构建中包含模块,我必须添加什么?依赖项如下:
子例程schleppe
我找到了解决方案!简单地说,
all:
的规则必须包括模块源文件,并且这些必须在其他源文件之前。另外,必须添加从模块源文件创建对象文件的规则。工作生成文件如下所示:

FCOM=gfortran

CPPFLAGS=-E
COMPFLAGS=

EXE=hello

SOURCES=sayhello.F schleppe.F schnuppi.F
MODS=words_schleppe.F words_schnuppi.F

OBJS=$(SOURCES:.F=.o)
MODOBJS=$(MODS:.F=.o)

# this may also be replaced by the ar command (creating archive)
all: $(MODOBJS) $(OBJS)
    $(FCOM) $(OBJS) $(MODOBJS) -o $(EXE)

%.for: %.F
    rm -f $*.for
    $(FCOM) $(CPPFLAGS) $*.F > $*.for

$(MODOBJS): %.o: %.for
    $(FCOM) -c -o $@ $(COMPFLAGS) $*.for

$(OBJS): %.o: %.for
    $(FCOM) -c -o $@ $(COMPFLAGS) $*.for

# clean: remove .for, .o, .do, and .stb files
.PHONY: clean
clean:
    -rm -f *.for *.o *.stb *.mod

如何从模块中生成
.mod
文件(这些是
.mod.F
文件)?这些
.mod
文件如何在构建过程的其余部分使用?@EtanReisner编译包含模块的源文件时,
.mod
文件由编译器自动创建。当同一编译器遇到任何
use
语句时,都会隐式使用它们。您的意思是编译
schleppe.F
将生成
schleppe.for
,编译
words\u schleppe.mod.F
将使用相同的编译命令自动生成
words\u schleppe.mod
,是的,就是这样。然后我想你只需要用
MODS
复制
OBJS
的部分,并添加
%.mod:%.F
配方和匹配
$(MODS):%.o:%.mod
配方(如果这也是必要的)。