在linux下如何使用Makefile对fortran程序进行编译

在linux下写过不少的fortran程序,但很少写makefile文件,通常情况下我是手动用ifort或pgf90进行编译,虽然也在大型程序中写过一些代码,但因为都有现成的makefile文件,我也只是修改一下配置参数,先make clean,再make,只要生成可执行程序就算搞定了。今天心血来潮,自己写了几个Makefile,供大家参考。


一、不用Makefile的直接编译
比如有2个简单程序,主程序为main.F90,子程序为sub.F90. 如果直接编译的话,键入
ifort main.F90 sub.F90
就可以生成一个a.out文件,即为可执行程序了。
你也可以指定一个可执行程序的名字,如
ifort main.F90 sub.F90 -o bin.exe
则可以生成bin.exe,实际上与a.out是一样的。
当然,如果你不喜欢用子程序,或者子程序和主程序都写在一个F90文件中(如main.F90),上述的编译语句直接省掉sub.F90就行了,但不推荐这样写程序,特别是程序比较大的情况下,一是程序间的关系容易理不清,另外风险也大,万一哪天把程序删掉了或改错了,损失可就大了。


上面的编译也可以分两步进行,
ifort -c main.F90 sub.F90
ifort -o main.exe main.o sub.o
第一行称为编译compile,第二行称为链接link。这个过程最后还是生成main.exe,第一步生成main.o和sub.o两个目标文件,第二步将目标文件链接成可执行文件main.exe。这看起来有点多此一举,如果在程序不大,子程序不多的情况下,这确实是浪费体力,但如果有几十或几百个子程序(如WRF模式),编译一次可能要花几十分钟或几个小时,那么可以单独编译修改的那个程序生成相应的.o文件就行了,然后再执行第二步链接,这样可以节省不少时间。也就是说,第一步的编译可以分开进行:
ifort -c main.F90
ifort -c sub.F90
在有几个子程序的情况下,这样分开编译虽然花点工夫,还是值得的,因为程序很难一蹴而就,总要调试,总要修改,分解成若干子程序逐个编译更容易各个击破。


二、简单的Makefile文件
我们仍以一行编译语句为例,将其写在Makefiel文件中。使用vi建立一个新的Makefile文件,在其中写入:
main.exe: main.F90 sub.F90
ifort main.F90 sub.F90 -o main.exe
就可以了。你把已有的main.exe删掉,键入make,你会发现生成了新的main.exe. 这就是Makefile文件了,简单吧!
如果报错的话,你看看是不是Makefile中的第二行之前没有用tab键空格,必须用tab键,用空格键是不行嘀。


下面我们再来解释一下Makefile的写作格式
简而言之,Makefile的格式就是二行,第一行定义目标文件和依赖文件,:之前的main.exe为目标文件,:之前后的main.F90和sub.F90为依赖文件。第二行为执行语句,与手动编译相同。好像第一行还是多此一举,还不如手动编译只要一行就搞定,我们看完下一个例子再来讨论这一点。


那么对于编译和链接分解的语句如何写呢。重新打开Makefile文件,将原来的两行删去,再写入:
main.exe:main.o sub.o
ifort -o main.exe main.o sub.o
main.o:main.F90
ifort -c main.F90
sub.o:sub.F90
ifort -c sub.F90
这就可以了,是不是还发现一点异样?语句的顺序和前面手动编译时是反的,先是链接语句,后是编译语句,这一点我们稍后解释。还是先运行一下吧,将原来的.exe和.o文件都删掉,执行make后,是不是可以看到新生成了.o和.exe文件。你还可以试试将其中的main.F90进行修改(比如加一行空格,或加一条注释),再执行make,可以发现,仅更新了main.o和main.exe,而sub.o还是原来的生成时间。这就是make的优势。


我们先来解释一下目标文件和依赖文件的关系,如果任意一个依赖文件发生了改变,则要运行下一行的执行语句,即生成新的目标文件,否则跳过执行文件。在make执行的过程中,实际上并不是顺序执行的,而是先把所有的目标文件和依赖文件检查一遍,从最顶层的目标文件开始,再分解检查各个子目标,将发生变化的依赖文件标记下来,然后再从下向上执行标记语句,最后更新顶层的目标文件。所以写makefile文件的顺序必须是先写顶层的目标文件,也就是连接生成的.exe文件,然后再分别写编译要生成的.o文件,这与手动编译时是不同的。make的工作方式就象警察办案一样,先侦察推演,收集证据;再顺藤摸瓜,收网抓贼。


三、复杂一点的Makefile文件
下面这个例子中用到了变量定义和静态模式
SOURS = main.F90 sub.F90
OBJS = main.o sub.o
BIN = main.exe
F90 = ifort


${BIN}:${OBJS}
${F90} -o ${BIN} ${OBJS}
${OBJS}: %.o :%.F90
${F90} -c $<
先来说说变量定义,这个地球人都知道,只要会写shell脚本的人都能看的懂,如果子程序不多的话也没必要定义来定义去的。


http://www.zhixing123.cn/ubuntu/30488.html

  • 8
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Make命令   在make命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些参数指定了需要编译的目标文件。其标准形式为:   target1 [target2 …]:[:][dependent1 …][;commands][#…]   [(tab) commands][#…]   方括号中间的部分表示可选项。Targets和dependents当中可以包含字符、数字、句点和"/"符号。除了引用,commands中不能含有"#",也不允许换行。   在通常的情况下命令行参数中只含有一个冒号":",此时command序列通常和makefile文件中某些定义文件间依赖关系的描述行有关。如果与目标相关连的那些描述行指定了相关的command序列,那么就执行这些相关的command命令,即使在分号和(tab)后面的aommand字段甚至有可能是NULL。如果那些与目标相关连的行没有指定command,那么将调用系统默认的目标文件生成规则。   如果命令行参数中含有两个冒号"::",则此时的command序列也许会和makefile中所有描述文件依赖关系的行有关。此时将执行那些与目标相关连的描述行所指向的相关命令。同时还将执行build-in规则。   如果在执行command命令时返回了一个非"0"的出错信号,例如makefile文件中出现了错误的目标文件名或者出现了以连字符打头的命令字符串,make操作一般会就此终止,但如果make后带有"-i"参数,则make将忽略此类出错信号。   Make命本身可带有四种参数:标志、宏定义、描述文件名和目标文件名。其标准形式为:   Make [flags] [macro definitions] [targets]   Unix系统下标志位flags选项及其含义为:   -f file  指定file文件为描述文件,如果file参数为"-"符,那么描述文件指向标准输入。如果没有"-f"参数,则系统将默认当前目录下名为makefile或者名为Makefile的文件为描述文件。在linux中, GNU make 工具在当前工作目录中按照GNUmakefilemakefileMakefile的顺序搜索 makefile文件。   -i   忽略命令执行返回的出错信息。   -s   沉默模式,在执行之前不输出相应的命令行信息。   -r   禁止使用build-in规则。   -n   非执行模式,输出所有执行命令,但并不执行。   -t   更新目标文件。   -q   make操作将根据目标文件是否已经更新返回"0"或非"0"的状态信息。   -p   输出所有宏定义和目标文件描述。   -d   Debug模式,输出有关文件和检测时间的详细信息。   linuxmake标志位的常用选项与Unix系统中稍有不同,下面我们只列出了不同部分:   -c dir   在读取 makefile 之前改变到指定的目录dir。   -I dir   当包含其他 makefile文件时,利用该选项指定搜索目录。   -h   help文挡,显示所有的make选项。   -w   在处理 makefile 之前和之后,都显示工作目录。   通过命令行参数中的target ,可指定make编译的目标,并且允许同时定义编译多个目标,操作时按照从左向右的顺序依次编译target选项中指定的目标文件。如果命令行中没有指定目标,则系统默认target指向描述文件中第一个目标文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值