我的程序是一个使用intel MKL的mpi程序。简单来说,我们假设有main.f90 a.f90 b.f90
a.f90
包含其他人需要的模块mymod
通常我会像这样编译它
mpiifort *90 /fast /Qmkl /MD -o main.exe
我只是做了两次,因为这是第一次缺少mymod.mod
现在我想使用makefile,因为我想减少重新编译时间。我这样写的
IFORT = /fast
MKL =/Qmkl
LDFLAGS = /MD
main:main.obj b.obj
mpiifort $(IFORT) $(MKL) $(LDFLAGS) $< -o $@
mymod.mod:a.f90
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<
main.obj:main.f90
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<
b.obj:b.f90
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<
但是,这里肯定有问题。我有一堆unresolved external symbol
。有什么问题?
答案 0 :(得分:0)
首先,其他人可能会写一个更好/更完整的答案(或指示我们一个),我会欢迎这一点,但在下面我提供了一个非常简单的例子。
现在我们可以识别错误的(可能的)来源:如果我们用touch
替换编译命令,我们可以生成一个演示问题的简单示例
main:main.obj b.obj
touch $@
mymod.mod:a.f90
touch $@
main.obj:main.f90
touch $@
b.obj:b.f90
touch $@
如果我们用
构建我们的“源文件”>touch main.f90 b.f90 a.f90
然后我们可以尝试构建我们的main
可执行文件:
>make main
将输出:
touch main.obj
touch b.obj
touch main
请注意,这不会创建mymod.mod
文件。这意味着在您的情况下a.f90
在构建main
时不会被编译,因此所需的symobols不可用(即,当链接时,函数/例程等未定义为{{1} }不可用)。如果我们现在通过将makefile调整为
a.obj
取决于main
mymod.mod
我们现在可以尝试构建main:main.obj b.obj mymod.mod
touch $@
mymod.mod:a.f90
touch $@
main.obj:main.f90
touch $@
b.obj:b.f90
touch $@
(在通过main
首次清理后),我们得到:
rm *.obj mymod.mod main
因此,我们已成功获得>make main
touch main.obj
touch b.obj
touch mymod.mod
touch main
来构建make
目标作为构建mymod.mod
的一部分。请注意,实际上您可能希望确保某些目标在其他目标之前构建(例如,您可能希望在main
之前编译a.f90
)。您可以使用依赖项列表执行此操作,您可能希望自动生成(请参阅例如this question)。
答案 1 :(得分:0)
如果我们使用intel fortran,我会想出一种自动的方法
英特尔fortran提供了一个名为gen-dep
的选项,它会自动分析并输出可用于makefile的依赖信息。所以只需运行以下命令,如果由于缺少mod文件而出现错误消息,则只需运行两次
mpiifort *90 /Qmkl /gen-dep > dependency.txt
我们得到了dependency.txt
。打开它,我们会找到类似这样的东西
mpifc.bat for the Intel(R) MPI Library 5.1.2 for Windows*
Copyright(C) 2007-2015, Intel Corporation. All rights reserved.
mymod.mod : \
a.f90
a.obj : \
a.f90
b.obj : \
b.f90 mymod.mod
main.obj : \
main.f90 \
c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi_base.mod \
c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi_sizeofs.mod \
c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi_constants.mod \
c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\include\mpi.mod \
mymod.mod
Microsoft (R) Incremental Linker Version 14.00.23026.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:a.exe
-subsystem:console
"-libpath:c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mkl\lib\intel64_win"
"/LIBPATH:c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\lib\release_mt"
"/LIBPATH:c:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2016.1.146\windows\mpi\intel64\bin\..\..\intel64\lib"
impi.lib
a.obj
b.obj
main.obj
那些与mpi相关的模块是静态的,所以只需将其删除即可。经过一些简单的文本操作(使用正则表达式将是一个不错的选择),使其更清晰和紧凑,我们可以得到一个像这样的正确的makefile(我在我的问题帖子中修复了一些错误)
IFORT = /fast
MKL =/Qmkl
LDFLAGS = /MD
a: a.obj b.obj main.obj
mpiifort $(IFORT) $(MKL) $(LDFLAGS) $^ -o $@.exe
mymod.mod : a.f90
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<
a.obj : a.f90
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<
b.obj : b.f90 mymod.mod
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<
main.obj : main.f90 mymod.mod
mpiifort /c $(IFORT) $(MKL) $(LDFLAGS) $<