如何使用模块为 Fortran 程序创建联编文件
How to create a makefile for a Fortran program using modules
挑战在于创建一个包含模块列表的 makefile,并且不需要我整理优先级。例如,模块是
mod allocations.f08 mod precision definitions.f08 mod unit values.f08
mod blocks.f08 mod shared.f08 mod parameters.f08
mod timers.f08
主程序是characterize.f08
。错误信息是
Fatal Error: Can't open module file ‘mprecisiondefinitions.mod’ for reading at (1): No such file or directory
主程序中的第一条语句是use mPrecisionDefinitions
,mod precision definitions.f08
中定义的模块。
以下基于 Creating a FORTRAN makefile 的 makefile 是:
# compiler
FC := /usr/local/bin/gfortran
# compile flags
FCFLAGS = -g -c -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.f08, %.o, $(wildcard *.f08))
# program name
PROGRAM = a.out
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $@ $^
%.mod: %.f08
$(FC) $(FCFLAGS) -o $@ $<
%.o: %.f08
$(FC) $(FCFLAGS) -o $@ $<
clean:
rm -f *.o *.mod
对于初学者,我建议用下划线或类似的东西替换文件名中的所有空格。
空格几乎普遍用作分隔符,任何以类似
开头的程序
gfortran -c -o mod precision definitions.o mod precision definitions.f08
会将此行解释为“从源文件 precision
、definitions.o
、mod
、precision
和definitions.f08
。虽然有很多方法可以做到,但随着自动化程度的提高,您必须跳得越来越多。
相比之下,这个效果很好:
gfortran -c -o mod_precision_definitions.o mod_precision_definitions.f08
我将使用此命令将所有空格更改为下划线:
rename 's/ /_/g' *.f08
如果这不起作用,请使用此命令:
for f in *.f08; do mv "$f" ${f// /_}; done
接下来,我不会担心 .mod
个文件。当您编译模块时,它们会与目标文件一起生成。因此,虽然从技术上讲,某些使用模块的例程需要该模块的 .mod
文件,但您也可以在 Makefile
中声明它取决于目标文件本身。
话虽如此,这是我要使用的 Makefile(添加了一些假设的模块间依赖项):
# Find all source files, create a list of corresponding object files
SRCS=$(wildcard *.f08)
OBJS=$(patsubst %.f08,%.o,$(SRCS))
# Ditto for mods (They will be in both lists)
MODS=$(wildcard mod*.f08)
MOD_OBJS=$(patsubst %.f08,%.o,$(MODS))
# Compiler/Linker settings
FC = gfortran
FLFLAGS = -g
FCFLAGS = -g -c -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
PROGRAM = characterize
PRG_OBJ = $(PROGRAM).o
# make without parameters will make first target found.
default : $(PROGRAM)
# Compiler steps for all objects
$(OBJS) : %.o : %.f08
$(FC) $(FCFLAGS) -o $@ $<
# Linker
$(PROGRAM) : $(OBJS)
$(FC) $(FLFLAGS) -o $@ $^
# If something doesn't work right, have a 'make debug' to
# show what each variable contains.
debug:
@echo "SRCS = $(SRCS)"
@echo "OBJS = $(OBJS)"
@echo "MODS = $(MODS)"
@echo "MOD_OBJS = $(MOD_OBJS)"
@echo "PROGRAM = $(PROGRAM)"
@echo "PRG_OBJ = $(PRG_OBJ)"
clean:
rm -rf $(OBJS) $(PROGRAM) $(patsubst %.o,%.mod,$(MOD_OBJS))
.PHONY: debug default clean
# Dependencies
# Main program depends on all modules
$(PRG_OBJ) : $(MOD_OBJS)
# Blocks and allocations depends on shared
mod_blocks.o mod_allocations.o : mod_shared.o
挑战在于创建一个包含模块列表的 makefile,并且不需要我整理优先级。例如,模块是
mod allocations.f08 mod precision definitions.f08 mod unit values.f08
mod blocks.f08 mod shared.f08 mod parameters.f08
mod timers.f08
主程序是characterize.f08
。错误信息是
Fatal Error: Can't open module file ‘mprecisiondefinitions.mod’ for reading at (1): No such file or directory
主程序中的第一条语句是use mPrecisionDefinitions
,mod precision definitions.f08
中定义的模块。
以下基于 Creating a FORTRAN makefile 的 makefile 是:
# compiler
FC := /usr/local/bin/gfortran
# compile flags
FCFLAGS = -g -c -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
# link flags
FLFLAGS =
# source files and objects
SRCS = $(patsubst %.f08, %.o, $(wildcard *.f08))
# program name
PROGRAM = a.out
all: $(PROGRAM)
$(PROGRAM): $(SRCS)
$(FC) $(FLFLAGS) -o $@ $^
%.mod: %.f08
$(FC) $(FCFLAGS) -o $@ $<
%.o: %.f08
$(FC) $(FCFLAGS) -o $@ $<
clean:
rm -f *.o *.mod
对于初学者,我建议用下划线或类似的东西替换文件名中的所有空格。
空格几乎普遍用作分隔符,任何以类似
开头的程序gfortran -c -o mod precision definitions.o mod precision definitions.f08
会将此行解释为“从源文件 precision
、definitions.o
、mod
、precision
和definitions.f08
。虽然有很多方法可以做到,但随着自动化程度的提高,您必须跳得越来越多。
相比之下,这个效果很好:
gfortran -c -o mod_precision_definitions.o mod_precision_definitions.f08
我将使用此命令将所有空格更改为下划线:
rename 's/ /_/g' *.f08
如果这不起作用,请使用此命令:
for f in *.f08; do mv "$f" ${f// /_}; done
接下来,我不会担心 .mod
个文件。当您编译模块时,它们会与目标文件一起生成。因此,虽然从技术上讲,某些使用模块的例程需要该模块的 .mod
文件,但您也可以在 Makefile
中声明它取决于目标文件本身。
话虽如此,这是我要使用的 Makefile(添加了一些假设的模块间依赖项):
# Find all source files, create a list of corresponding object files
SRCS=$(wildcard *.f08)
OBJS=$(patsubst %.f08,%.o,$(SRCS))
# Ditto for mods (They will be in both lists)
MODS=$(wildcard mod*.f08)
MOD_OBJS=$(patsubst %.f08,%.o,$(MODS))
# Compiler/Linker settings
FC = gfortran
FLFLAGS = -g
FCFLAGS = -g -c -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5
PROGRAM = characterize
PRG_OBJ = $(PROGRAM).o
# make without parameters will make first target found.
default : $(PROGRAM)
# Compiler steps for all objects
$(OBJS) : %.o : %.f08
$(FC) $(FCFLAGS) -o $@ $<
# Linker
$(PROGRAM) : $(OBJS)
$(FC) $(FLFLAGS) -o $@ $^
# If something doesn't work right, have a 'make debug' to
# show what each variable contains.
debug:
@echo "SRCS = $(SRCS)"
@echo "OBJS = $(OBJS)"
@echo "MODS = $(MODS)"
@echo "MOD_OBJS = $(MOD_OBJS)"
@echo "PROGRAM = $(PROGRAM)"
@echo "PRG_OBJ = $(PRG_OBJ)"
clean:
rm -rf $(OBJS) $(PROGRAM) $(patsubst %.o,%.mod,$(MOD_OBJS))
.PHONY: debug default clean
# Dependencies
# Main program depends on all modules
$(PRG_OBJ) : $(MOD_OBJS)
# Blocks and allocations depends on shared
mod_blocks.o mod_allocations.o : mod_shared.o