修改Makefile:如何指定Fortran *.mod模块文件的生成目录?
Fortran .mod 文件的Makefile规则问题解答
先回答你的第一个问题:当前Makefile里有没有生成*.mod文件的规则?
答案是没有显式的规则,但你不用慌——Fortran编译器(这里你用的是ifort)在编译包含module定义的.f90源文件时,会自动生成对应的.mod文件,这是编译器的默认行为,不需要在Makefile里写专门的规则。你找不到对应规则就是因为它是隐式的,由编译器自动处理。
不过你现在的问题是没法指定.mod文件的生成目录,这是因为当前的编译命令里没有告诉编译器要把.mod文件放到哪里,所以ifort默认会把它们生成在当前工作目录或者源文件所在的./solver目录下。
如何修改Makefile,指定*.mod文件的生成目录?
要让.mod文件生成到你指定的目录(比如和.o文件一样的./obj),只需要给ifort加两个编译选项就行:
-module <目录>:告诉编译器把生成的.mod文件放到指定目录-I <目录>:告诉编译器去哪里找需要引用的.mod文件(因为其他源文件编译时要依赖这些模块)
另外,我注意到你原来的Makefile里有个小问题:OBJ变量被重复赋值了,第二次赋值会覆盖第一次,而且还用到了未定义的_OBJ,这会导致编译错误,我一起帮你修正了。
修改后的完整Makefile代码
# GNU Makefile # Paths SDIR=./solver ODIR=./obj # 如果想单独放mod文件,可以新建MDIR变量,比如 MDIR=./mod _CASE=./WorkCases/problem CASE=$(SDIR)/$(_CASE) TOP = . FC = ifort # 添加 -module $(ODIR) 指定mod输出目录,-I $(ODIR) 指定mod搜索路径 # 如果用单独的MDIR,就改成 -module $(MDIR) -I $(MDIR) FFLAGS = -fpp -O1 -DPTR_INTEGER8 -warn nousage -module $(ODIR) -I $(ODIR) # 确保输出目录存在,避免编译时因为目录不存在报错 $(shell mkdir -p $(ODIR)) # Define rule to make .f90 $(ODIR)/%.o : $(SDIR)/%.f90 $(FC) -c $(FFLAGS) $< -o $@ # set executable name EXEC = $(dir ${CASE})/$(basename $(notdir ${CASE})).out # shared global variables _SHARED_OBJ = shared_modules.o main_vars.o debug_vars.o SHARED_OBJ = $(patsubst %,$(ODIR)/%,$(_SHARED_OBJ)) # 修正重复赋值的OBJ:先定义_OBJ,再映射到ODIR目录下的目标文件 _OBJ = ${_SHARED_OBJ} $(_CASE).PARAMS.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) MAIN_OBJ = $(ODIR)/main.o main : ${SHARED_OBJ} $(OBJ) $(MAIN_OBJ) $(FC) ${FFLAGS} $(OBJ) $(MAIN_OBJ) -o $(EXEC) -lstdc++ -shared-intel
额外说明
- 如果你希望.mod文件和.o文件分开存放,比如放到
./mod目录,只需要:- 添加
MDIR=./mod到路径定义部分 - 修改
FFLAGS里的选项为-module $(MDIR) -I $(MDIR) - 在
mkdir -p命令里加上$(MDIR),变成$(shell mkdir -p $(ODIR) $(MDIR))
- 添加
- 修正后的
OBJ变量先定义了_OBJ列表,再把所有目标文件映射到ODIR目录下,避免了原来的重复赋值问题,确保所有.o文件都生成在./obj里。
内容的提问来源于stack exchange,提问作者Blade
相关产品推荐
相关产品推荐

