makefile - 使用 make 将目标文件存储在单独的目录中

标签 makefile fortran mingw gfortran

我正在 Windows 上使用 mingw 运行 makefile。我看过很多关于这个主题的 SO 链接,但它们似乎都是针对 C 或 c++ 的。我不确定是否适用相同的规则,而且由于我使用的是 Windows,语法似乎也有点不同。以下是一些其他引用资料:

How to place object files in separate subdirectory (我认为最有前途)

Using a make file to compile files in separate directories

Flat object file directory structure output with GNU Make

我目前拥有的是(逐字记录)

VPATH =\
    user \
    static \
    computations \
    solvers\\steadyState \
    solvers\\transient \
    solvers\\transient\\momentum \
    solvers\\transient\\induction

FC      = gfortran
TOP_DIR = .
MOD_DIR = $(TOP_DIR)\\mod
OBJ_DIR = $(TOP_DIR)\\obj

FCFLAGS = -g
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized

TARGET = parametricStudy

SRCS_F =\
    user\\constants.f90 \
    static\\myExceptions.f90 \
    static\\myDebug.f90 \
    static\\scalarField.f90 \
    static\\vectorField.f90 \
    static\\myIO.f90 \
    user\\simParams.f90 \
    static\\solverSettings.f90 \
    static\\myTime.f90 \
    computations\\myError.f90 \
    static\\coordinates.f90 \
    user\\griddata.f90 \
    static\\myAllocate.f90 \
    static\\BCs.f90 \
    user\\rundata.f90 \
    computations\\myDel.f90 \
    computations\\vectorOps.f90 \
    static\\myExport.f90 \
    computations\\applyBCs.f90 \
    solvers\\steadyState\\mySOR.f90 \
    solvers\\steadyState\\myPoisson.f90 \
    solvers\\transient\\induction\\initializeBBCs.f90 \
    solvers\\transient\\induction\\initializeBfield.f90 \
    solvers\\transient\\induction\\initializeSigmaMu.f90 \
    solvers\\transient\\momentum\\initializeUBCs.f90 \
    solvers\\transient\\momentum\\initializeUfield.f90 \
    solvers\\transient\\inductionSolver.f90 \
    solvers\\transient\\momentumSolver.f90 \
    solvers\\transient\\MHDSolver.f90 \
    user\\MOONS.f90 \
    parametricStudy.f90

OBJS_F = $(patsubst %.f90,$(OBJ_DIR)\\%.o,$(notdir $(SRCS_F)))

all: $(TARGET)

$(TARGET): $(OBJS_F)
    $(FC) -o $@ $(FCFLAGS) $(OBJS_F)

$(OBJ_DIR)\\%.o: %.f90
    $(FC) $(FCFLAGS) -c -o $@ $<
clean:
    del $(OBJ_DIR)\\*.o $(MOD_DIR)\\*.mod parametricStudy.exe
list:;  @echo " "
    @echo " "
    @echo "Source files:"
    @echo $(SRCS_F)
    @echo " "
    @echo "Object files:"
    @echo $(OBJS_F)
    @echo " "
    @echo "Compiler          : $(FC)"
    @echo "Include directory : $(INC_DIR)"
    @echo "Root directory    : $(ROOT_DIR)"
    @echo "Bin directory     : $(BIN_DIR)"
    @echo "Modules directory : $(MOD_DIR)"
    @echo "Modules directory : $(MOD_DIR)"
    @echo "Object directory  : $(OBJ_DIR)"
    @echo " "

使用它,我可以执行以下命令(再次,逐字)

C:\Users\Charlie\Desktop\development\FORTRAN_LIB>gmake
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\const
ants.o user/constants.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myExc
eptions.o static/myExceptions.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myDeb
ug.o static/myDebug.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\scala
rField.o static/scalarField.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\vecto
rField.o static/vectorField.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myIO.
o static/myIO.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\simPa
rams.o user/simParams.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\solve
rSettings.o static/solverSettings.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myTim
e.o static/myTime.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myErr
or.o computations/myError.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\coord
inates.o static/coordinates.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\gridd
ata.o user/griddata.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myAll
ocate.o static/myAllocate.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\BCs.o
 static/BCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\runda
ta.o user/rundata.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myDel
.o computations/myDel.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\vecto
rOps.o computations/vectorOps.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myExp
ort.o static/myExport.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\apply
BCs.o computations/applyBCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\mySOR
.o solvers\\steadyState/mySOR.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\myPoi
sson.o solvers\\steadyState/myPoisson.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeBBCs.o solvers\\transient\\induction/initializeBBCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeBfield.o solvers\\transient\\induction/initializeBfield.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeSigmaMu.o solvers\\transient\\induction/initializeSigmaMu.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeUBCs.o solvers\\transient\\momentum/initializeUBCs.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\initi
alizeUfield.o solvers\\transient\\momentum/initializeUfield.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\induc
tionSolver.o solvers\\transient\\induction/inductionSolver.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\momen
tumSolver.o solvers\\transient\\momentum/momentumSolver.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\MHDSo
lver.o solvers\\transient/MHDSolver.f90
gfortran -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized -c -o .\\obj\MOONS
.o user/MOONS.f90
gmake: *** No rule to make target `.\\obj\parametricStudy.o', needed by `paramet
ricStudy'.  Stop.

C:\Users\Charlie\Desktop\development\FORTRAN_LIB>gfortran -g -J.\\mod -fopenmp -
c -o .\\obj\parametricStudy.o parametricStudy.f90

C:\Users\Charlie\Desktop\development\FORTRAN_LIB>gmake
gfortran -o parametricStudy -g -J.\\mod -fopenmp -fimplicit-none -Wuninitialized
 .\\obj\constants.o .\\obj\myExceptions.o .\\obj\myDebug.o .\\obj\scalarField.o
.\\obj\vectorField.o .\\obj\myIO.o .\\obj\simParams.o .\\obj\solverSettings.o .\
\obj\myTime.o .\\obj\myError.o .\\obj\coordinates.o .\\obj\griddata.o .\\obj\myA
llocate.o .\\obj\BCs.o .\\obj\rundata.o .\\obj\myDel.o .\\obj\vectorOps.o .\\obj
\myExport.o .\\obj\applyBCs.o .\\obj\mySOR.o .\\obj\myPoisson.o .\\obj\initializ
eBBCs.o .\\obj\initializeBfield.o .\\obj\initializeSigmaMu.o .\\obj\initializeUB
Cs.o .\\obj\initializeUfield.o .\\obj\inductionSolver.o .\\obj\momentumSolver.o
.\\obj\MHDSolver.o .\\obj\MOONS.o .\\obj\parametricStudy.o

请注意,收到错误后,我可以在错误发生后显式编译 parametricStudy.f90:

 gfortran -g -J.\\mod -fopenmp -c -o .\\obj\parametricStudy.o parametricStudy.f90

然后输入

 gmake

同样,这不会导致任何错误。我很困惑。

这是屏幕截图enter image description here我的目录:

也许这和TARGET有关系?看起来最后一个文件的路径有些错误。非常感谢任何帮助!

最佳答案

我认为下面的 makefile 风格可以解决这个问题。我用样本C测试了它 项目,不是 fortran,但这对于 make 问题和解决方案并不重要。

# VPATH: Tell `make` to look for in `user` for prerequisites it can't find here
VPATH = user
# If e.g. you also want `make` to look for for prerequisites in `../include`, then:
# VPATH = user:../include
FC      = gfortran
TOP_DIR = .
MOD_DIR = $(TOP_DIR)\\mod
OBJ_DIR = $(TOP_DIR)\\obj

FCFLAGS = -g
FCFLAGS += -J$(MOD_DIR) -fopenmp -fimplicit-none -Wuninitialized

TARGET = parametricStudy

SRCS_F =\
    user\\constants.f90 \
    ...
    parametricStudy.f90

OBJS_T1 = $(patsubst %.f90,%.o,$(SRCS_F))
OBJS_T2 = $(notdir $(OBJS_T1))
# The object files are all to be obj\<name>.o
OBJS_F = $(patsubst %.o,$(OBJ_DIR)\\%.o,$(OBJS_T2))

all: $(TARGET)

$(TARGET): $(OBJS_F)
    $(FC) -o $@ $(FCFLAGS) $(OBJS_F)

# How to make an obj\*.o from the matching *.f90. `make` considers the VPATH
$(OBJ_DIR)\\%.o: %.f90
    $(FC) $(FCFLAGS) -c -o $@ $<
clean:
    del $(OBJ_DIR)\\*.o $(MOD_DIR)\\*.mod parametricStudy.exe

使用相对路径TOP_DIR = .而不是绝对ROOT_DIR是已经提供的好建议 作者:@Wintermute。

启用所需的模式规则:

$(OBJ_DIR)\\%.o: %.f90

要启动,您必须让 make 觉得任何先决条件 *.f90 都在这里,按照模式, 不在其他目录中,例如user\constants.f90 这就是VPATH 实现。

继续后续开发

还没有看到 makefile 所在目录的列表我 只能大胆假设,但我所看到的假设是:

该目录实际上并不包含名为 parametricStudy.f90 的文件, 但是一个名为 parametricStudy.F90 的文件,如果将其重命名为 parametricStudy.f90, 然后 makefile 将找到并编译它。

是吗?

这如何解释事实:模式规则:

$(OBJ_DIR)\\%.o: %.f90

无法匹配任何parametricStudy.f90,因此不存在此类文件。然而你说:

gfortran -g -J.\\mod -fopenmp -c -o .\\obj\parametricStudy.o parametricStudy.f90

编译成功。

您正在 Windows 上进行构建,因此工具链订阅 Windows 的文件处理协议(protocol)。 文件名不区分大小写:parametricStudy.f90 将识别 parametricStudy.F90(如果存在), 和 .F90 将被 gfortran(在 Windows 或其他任何地方)解释为表示 Fortran 90 源文件。这样命令行编译就成功了。

但是模式规则与文件处理协议(protocol)无关。这只是一个模式 匹配规则,不变的.f90.F90不匹配。

关于makefile - 使用 make 将目标文件存储在单独的目录中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28121161/

相关文章:

c - 将静态库链接到可执行文件

c - 有没有 Fortran 编译器之类的东西?

debugging - Fortran 是否通过子程序多次调用修改输入参数?

c++ - 如何在没有依赖的情况下构建 harfbuzz

c++ - 在 Windows 的 MinGW 中打印堆栈跟踪

c - gcc 编译器和 makefile : error: expected identifier or ‘(’ before ‘&’ token

C++ 从源生成器生成文件 - 有这样的吗?

makefile - 条件生成文件中的变量?

fortran - 在模块中使用外部函数

c++ - 链接器在同一目录中找不到静态库