首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何重用Fortran模块而不复制源代码或创建库

如何重用Fortran模块而不复制源代码或创建库
EN

Stack Overflow用户
提问于 2013-05-03 05:39:52
回答 2查看 5.5K关注 0票数 4

在不构建库或复制源代码的情况下,我很难理解是否/如何在几个Fortran项目之间共享代码。

我在linux系统上使用Eclipse/Photran和Intel编译器(ifort),但我相信,与特定的工具相比,我在模块的概念上有更大的问题。

下面是一个简单的示例:在~/工作区/cow中,我有一个源目录(src),其中包含cow.f90 (程序),以及m_graze.f90和m_moo.f90中的两个模块m_graze和m_moo。此项目构建并正确链接,以创建可执行的‘牛’。可执行文件和模块(m_graze.mod和m_moo.mod)存储在~/工作区/cow/Debug中,对象文件存储在~/工作区/cow/Debug/src下。

稍后,我创建了~/workplace/绵羊,并将src/sheep.f90作为程序,src/m_baa.f90作为模块m_baa。我想在m_graze中使用sheep.f90中的“只使用:反刍”来访问反刍()子程序。我只需复制m_graze.f90,但这可能导致代码不同步,并且没有考虑到m_graze可能具有的任何依赖关系。出于这些原因,我宁愿将m_graze留在cow项目中,并根据它编译和链接sheep.f90。

如果我试图编译这个绵羊项目,我会得到一个错误,例如:

代码语言:javascript
复制
error #7002: Error in opening the compiled module file.  Check INCLUDE paths.   [M_GRAZE]

在“属性:绵羊项目参考资料”下,我可以选择奶牛项目。在属性:Fortran构建:设置:Intel:预处理器下,我可以在包含目录的列表中添加~/工作区/ cow /Debug(模块文件的位置),这样编译器就可以找到cow模块并编译sheep.f90。然而,链接器的死方式如下:

代码语言:javascript
复制
Building target: sheep
Invoking: Intel(R) Fortran Linker
ifort -L/home/me/workspace/cow/Debug -o "sheep"  ./src/sheep.o
./src/sheep.o: In function `sheep':
/home/me/workspace/sheep/src/sheep.f90:11: undefined reference to `m_graze_mp_ruminate_'

这通常可以通过向链接器设置添加库和库路径来解决,除非没有适当的库可链接(这是Fortran,而不是C)。

cow项目完全能够将cow.f90、m_graze.f90和m_moo.f90编译并链接到一个可执行文件中。然而,虽然绵羊项目可以编译sheep.f90和m_baa.f90,并且可以找到模块m_graze.mod,但它似乎找不到m_graze的符号,尽管系统中有它这样做所需的所有信息。

这似乎是一个简单的配置问题,以获得ifort的链接部分,以找到缺失的部分,并将它们放在一起,但我不知道需要输入哪些神奇的词,在照片UI中,以实现这一点。

我承认在C和C构建过程中完全缺乏兴趣和能力,我宁愿避免转移创建库(.a或.so),除非这是使此工作的唯一方法。

最终,我在寻找解决这个问题的纯Fortran解决方案,这样我就可以保留源代码的一个副本,而不必手动维护一堆定制Makefile。

那么,这能做到吗?

很抱歉,如果这已经被记录在某个地方;Google只是向我展示了简单的构建示例,如何创建模块,以及如何与现有的库链接。似乎没有任何不涉及重复源代码的模块重用代码的例子。

编辑

正如应答者所指出的,.mod文件是必要的,但还不够;在链接阶段必须指定目标代码(以m_graze.o的形式)或静态共享库。.mod文件描述了对象代码/库的接口,但这两者都是构建最终可执行文件所必需的。

对于这样一个过于简化的玩具问题,这足以回答所提出的问题。

在一个具有更复杂依赖关系的大型项目中(在我的例子中,80+KLOC of F90链接到MKL版本的LAPACK95),IDE或工具链可能缺乏足够的自动或用户界面工具,使共享单个规范的源文件集成为可行的策略。这种选择似乎是在冒着重复源文件失去同步的风险,放弃IDE的许多优点(即避免手工创建make/CMake/SCons文件),或者很可能两者兼而有之。虽然修订控制系统和良好的代码组织可能会有所帮助,但考虑到Eclipse的当前状态,显然在项目之间共享单个规范的源文件集并不容易。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-05-03 21:04:26

我怀疑您已经知道的一些背景:通常(包括ifort)编译Fortran模块的源代码会产生两个输出--一个"mod“文件,该文件包含模块定义的Fortran实体的描述,当它看到模块的USE语句时,编译器需要查找该实体,以及模块定义的实现过程和变量存储等的链接器的对象代码。

您的第一个错误(您解决的那个错误)是因为编译器找不到mod文件。

第二个错误是因为链接器还没有被告知实现源文件中与模块相关的内容的对象代码。无论如何,我不是Eclipse,而是指定对象文件(xxxxx/Debug/m_graze.o)作为附加链接器选项(Fortran > Settings,在Intel > Command Line下)的一种强力方法。(其他工具链在链接阶段具有显式的“附加对象文件”属性--对于Intel链,很可能有更好的方法来实现这一点。)

对于更多涉及的示例,您通常会从共享代码中创建一个库。这并不是真正特定于C的,唯一的Fortran方面是,对象代码的库存档需要与Fortran编译器生成的mod文件一起提供。

票数 4
EN

Stack Overflow用户

发布于 2013-05-04 12:18:26

是的,必须提供目标代码。例如,在Debian (apt-get install libnetcdf-dev)中安装libnetcdf-dev时,包含一个/usr/include/netcdf.mod文件。

现在可以在Fortran代码中使用所有netcdf例程。例如,

代码语言:javascript
复制
program main
use netcdf
...
end 

但是您将有指向netcdf共享(或静态)库的链接,即,

代码语言:javascript
复制
gfortran -I/usr/include/ main.f90 -lnetcdff

但是,正如用户MSB所提到的,mod文件只能由发行版(apt-get install gfortran)附带的gfortran使用。如果您想使用任何其他编译器(甚至是您自己安装的不同版本),那么您必须使用特定的编译器自己构建netcdf。

因此,创建一个库并不是一个糟糕的解决方案。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16352319

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档