在Linux环境下,使用ifortran编译 带有结构的和.inc头文件 的fortran项目生成.so文件
- 1 致谢
- 2 参考文章和手册
- 3 需求描述
- 3.1 文件结构
- 3.2 文件调用关系
- 4 主程序改造为函数
- 5 项目编译方法
- 5.1 方案一 直接对所有.f90源文件进行编译
- 5.1.1 具体实现
- 5.1.2 注意事项
- 5.2 方案二 编译时使用 -I 参数指定头文件路径进行编译
- 5.2.1 具体实现
- 5.2.2 注意事项
- 6 生成.so文件后的注意事项
1 致谢
Godzilla_BB
DOSKEY_jason
2 参考文章和手册
在linux下安装fortran编译器详细教程
linux下gfortran 生成so文件
Intel® Fortran Compiler User and Reference Guides.pdf
3 需求描述
将 一个复杂的fortran项目 编译成一个对外暴露函数 接口的 .so文件 供外部调用。
3.1 文件结构
该项目共15个文件,包含13个.f90源文件和2个定义常量声明的.inc文件。
3.2 文件调用关系
其中13个源文件中1个是主程序(带有program关键字),其他12个为模块化调用的函数function和子程序subroutine。
并且主程序和子模块或函数间有一定的调用关系,且这13个.f90源文件中某些引用了.inc文件,以加载常量声明(即:出现了include 'xxx.inc’的加载外部文件的语句)
示例调用关系如下:
4 主程序改造为函数
由于主程序是program关键字编写的,进行部分改造,使主程序源文件 变成一个函数function的f90源文件。
源主程序代码示例
program TPKx1! ...end program
改造成函数后代码示例
integer function TPKx1()!program TPKx1! ...!end programTPKx1 = 9999return end function
5 项目编译方法
5.1 方案一 直接对所有.f90源文件进行编译
借助 ifortran编译器 编译时 将当前路径作为默认搜索路径的特点
5.1.1 具体实现
文件路径结构
将所有.f90文件和所有.inc文件放置于同一个文件夹下。
在Linux环境下,在该文件夹中打开shell终端,
输入命令(此时终端的路径为放置所有文件的文件夹路径)
ifort -fPIC -shared -o 目标文件名.so ./*.f90
释义
ifort 使用ifort编译器进行编译
-fPIC 编译器产生与位置无关代码(Position-Independent Code)
-shared -o 生成共享文件(shared object)
目标文件名.so 指定需要生成的.so文件的名称
./*.f90 指定需要参与编译的源文件为: 当前路径下所有以.f90后缀结尾的文件
5.1.2 注意事项
① 带有include ‘xxx.inc’ 代码的 f90源文件,在编译时,虽然没有指定参与编译的’xxx.inc’文件,但是由于编译器默认会在当前目录下寻找所需的 'xxx.inc’文件,然在f90源文件中相应的地方展开,所以最终可以成功编译出需要的.so文件。
② 虽然将所有的f90文件和inc文件置于同一文件夹下,但是编译时,选择 参与编译的文件只能是所有的.f90文件,因为.inc文件 ifortran编译器无法辨识。即:发生 file format not recognized for xxx .inc警告,导致编译.so文件失败。
若使用如下命令,
ifort -fPIC -shared -o 目标文件名.so ./*
警告示例
5.2 方案二 编译时使用 -I 参数指定头文件路径进行编译
5.2.1 具体实现
文件路径结构
将所有.f90文件放入 A 文件夹下, 在A文件夹下新建include文件夹,将所有.inc文件放入A文件夹下的include文件夹
输入命令(此时终端的路径显示为A文件夹路径)
ifort -I ./include -fPIC -shared -o 目标文件名.so ./*.f90
释义
-I ./include 指定编译所需头文件的路径为 ./include 文件夹,即当前文件夹下的include文件夹
5.2.2 注意事项
输入编译命令时,打开的终端的路径为A文件夹时(此时A文件夹下有include文件夹), 告诉编译器
所需参与编译的文件应该为 ./*.f90 而不能是 ./* (./* 表示当前文件夹下所有内容)
这样会导致编译器将 include文件夹这一对象也作为需要参与编译的文件,而导致无法识别文件夹发生错误。
警告示例
6 生成.so文件后的注意事项
将原主程序program, 改造成function函数后。在外部调用,
最终输出的.so文件中的TPKx1()函数, 函数名会发生改变,变成小写并添加下划线_ ,即:tpkx1_
具体检测方法
输入命令
nm 目标文件名.so
查看该.so文件对外暴露的函数接口 为 tpkx1_ , 在使用JNA进行调用时需要注意这一点,否则无法调用该函数成功。