【问题标题】:Makefile produces for Fortran 90 causes unresolved external symbolMakefile 为 Fortran 90 生成导致无法解析的外部符号
【发布时间】:2016-07-27 15:42:42
【问题描述】:

我的程序是一个使用 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。怎么了?

【问题讨论】:

  • 我不是 makefile 专家,但看起来您的 main 目标对 mymod.mod 没有任何显式依赖,因此无法构建。我也可能完全错了

标签: makefile fortran fortran90


【解决方案1】:

首先,其他人可能会写一个更好/更完整的答案(或指导我们找到一个),我很欢迎,但下面我提供了一个非常简单的例子。

现在我们可以确定错误的(可能的)来源:如果我们只用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 时不会被编译,因此所需的符号不可用(即链接时有未定义为 a.obj 的函数/例程等不可用)。如果我们现在通过调整我们的makefile来证明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 的一部分。请注意,实际上您可能希望确保某些目标在其他目标之前构建(例如,您可能希望在 b.f90 之前编译 a.f90)。您可以使用依赖列表来做到这一点,您可能希望自动生成这些列表(例如参见this question)。

【讨论】:

  • 非常感谢 d_1999。我想出了一个更简单的方法:)
【解决方案2】:

如果我们使用 intel fortran,我想出了一种自动的方法

Intel 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) $<

【讨论】:

  • 仍然给项目引入一个新文件带来了很大的痛苦。这就是为什么我不再将 make 用于 Fortran 的原因。有更好的自动构建工具可用,cmakesconswaf
  • @VladimirF 嗨,VladimirF。多年前,我认为 makefile 只是不必要的。几个月前我开始使用makefile,因为它可以很方便地自定义不同的工作模式:build、clean等。几天前,我厌倦了重新编译,因为我正在密切关注一个bug,我必须编写一个更好的makefile来指定依赖关系。也许在不久的将来,我会像你一样完全厌倦makefile :) 但是顺便问一下,你想在cmake或其他fortran工具上添加一个简单的插图来比较传统方法吗?我在这个网站上搜索并没有找到任何关于问题的好的答案。
  • 在这里放任何东西都是题外话。这里有很多关于 cmake 的问题stackoverflow.com/search?q=cmake%2Bfortran 并且对于 scons 可以在 github github.com/LadaF/PoisFFT/blob/master/src/SConstruct 上找到一些东西(这个是我的)。还有一个 cmake 的文档站点 stackoverflow.com/documentation/cmake/topics
  • @VladimirF 非常感谢,尤其是github页面:)
猜你喜欢
  • 1970-01-01
  • 2022-08-03
  • 2014-05-23
  • 1970-01-01
  • 2018-07-01
  • 2018-01-16
  • 2018-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多