Fortran 头文件中公共变量的定义和module 的使用问题 Makefile

本文介绍了一个使用Fortran语言编写的简单数学运算模块及其Makefile构建过程。该模块包含加法和减法子程序,并通过Makefile组织源代码,实现自动化编译。文章详细展示了不同版本Makefile的变化及如何正确指定依赖关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注意事项:
module 文件的编译顺序一定要放在最前面
下一篇将使用变量对Makefile文件进行简化

Makefile 文件

#next step: add variable on 2021.4.16
OBJS= main.o sub_add.o  sub_minus.o
main.out: $(OBJS)
#	mpif90 -o main.out $(OBJS)
	mpif90 -o main.out commonData.f90 main.f90    -I ./sub/   \
	sub/sub_add.f90 sub/sub_minus.f90 


clean:
	rm *.o *.out *.mod


#successfully, all the below are very important, shouldn't be deleted.

main.o: commonData.f90 sub_add.o sub_minus.o 
sub_add.o: sub/sub_add.f90
sub_minus.o: sub/sub_minus.f90	

commonData.f90

MODULE share_data
IMPLICIT NONE
SAVE
INTEGER , PARAMETER :: num_vals = 5 , PI = 3.141592
REAL , DIMENSION(num_vals) :: values
END MODULE share_data

main.f90

program main
use share_data
!INTEGER , PARAMETER :: num_vals = 5 , PI = 3.141592
integer a,b, c
a=1
b=2
write(*, *)"hello world"
write(*, *) "num_vals=", num_vals

call add(a,b,c)
write(*,*) "a+b=3?",c

call minus(a,b,c)
write(*,*) "a-b=-1?",c

end

sub/sub_add.f90

subroutine add(a,b,c)
integer a,b,c
c=a+b

end

sub/sub_minus.f90

subroutine minus(a,b,c)
integer a,b,c
c=a-b

end

Makefile version 2:多个目录下程序的编译,需要注意 -I ./add/ -I ./minus/ 每一个文件夹前面必须对应一个-I,否则报错。

OBJS= main.o sub_add.o  sub_minus.o
main.out: $(OBJS)
#	mpif90 -o main.out $(OBJS)
	mpif90 -o main.out commonData.f90 main.f90    \
		-I ./add/  -I ./minus/ \
			add/sub_add.f90 minus/sub_minus.f90 


clean:
	rm *.o *.out *.mod


#successfully, all the below are very important, shouldn't be deleted.

main.o: commonData.f90 #main.f90 #sub_add.o #sub_minus.o 
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90	

Makefile version 3

main.out: $(OBJS)
	mpif90 -o main.out    \
		commonData.f90 Main/main.f90  \
		-I ./add/  -I ./minus/ \
		add/*.f90 minus/*.f90 

clean:
	rm *.o *.out *.mod

main.o: commonData.f90 Main/main.f90 #sub_add.o #sub_minus.o 
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90    #minus/sub_minus.f90	

OBJS= main.o #sub_add.o  #sub_minus.o

Makefile version 4

main.out: $(OBJS)
	mpif90 -o main.out    \
		CommonData/commonData.f90 Main/main.f90  \
		-I ./add/  -I ./minus/ \
		add/*.f90 minus/*.f90 

clean:
	rm *.o *.out *.mod

main.o: CommonData/commonData.f90 Main/main.f90 #sub_add.o #sub_minus.o 
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90    #minus/sub_minus.f90	


OBJS= main.o #sub_add.o  #sub_minus.o

Makefile version 5

main.out: $(OBJS)
	mpif90 -o main.out    \
		CommonData/commonData.f90 \
		-I ./Main/ Main/*.f90 \
		-I ./add/  add/*.f90 \
		-I ./minus/  minus/*.f90 
clean:
	rm *.o *.out *.mod

main.o: CommonData/commonData.f90 Main/main.f90 #sub_add.o #sub_minus.o 
sub_multiply.o: Main/sub_multiply.f90
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90    #minus/sub_minus.f90	

OBJS= main.o #sub_add.o  #sub_minus.o

Makefile version 6: finally, all files are compiled using the same pattern, -I , it seems to be the most elegant method to write each dependency explicitly.

Nest step: maybe Mo Huang Rui’s implicit method would be more succent?

main.out: $(OBJS)
	mpif90 -o main.out    \
		-I ./CommonData/    CommonData/*.f90 \
		-I ./Main/ Main/*.f90 \
		-I ./add/  add/*.f90 \
		-I ./minus/  minus/*.f90 
clean:
	rm *.o *.out *.mod

main.o: CommonData/*.f90 Main/main.f90 #sub_add.o #sub_minus.o 
sub_multiply.o: Main/sub_multiply.f90
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90    #minus/sub_minus.f90	

OBJS= main.o #sub_add.o  #sub_minus.o

If I comment line 3-6, add all .o file in the OBJS variable, when execute make, it shows the error:

mpif90 -o main.out
/usr/lib/gcc/x86_64-linux-gnu/5/…/…/…/x86_64-linux-gnu/crt1.o: In function _start': (.text+0x20): undefined reference tomain’
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target ‘main.out’ failed
make: *** [main.out] Error 1

main.out: $(OBJS)
	mpif90 -o main.out    \
		-I ./CommonData/    CommonData/*.f90 \
		-I ./Main/ Main/*.f90 \
		-I ./add/  add/*.f90 \
		-I ./minus/  minus/*.f90 
clean:
	rm *.o *.out *.mod

main.o: CommonData/*.f90 Main/main.f90 #sub_add.o #sub_minus.o 
sub_multiply.o: Main/sub_multiply.f90
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90    #minus/sub_minus.f90	

OBJS= main.o sub_add.o  sub_minus.o

The following Makefile works, however, there is no output .o file. Only execution file: main created.

HOME = .
F90=/usr/bin/mpif90
VPATH = ../src
EXE = ../main
opt = -O3 

$(EXE): $(OBJS)
	$(F90) -o $(EXE)   \
		-I $(VPATH)/CommonData/    $(VPATH)/CommonData/*.f90 \
		-I $(VPATH)/Main/ $(VPATH)/Main/*.f90 \
		-I $(VPATH)/add/  $(VPATH)/add/*.f90 \
		-I ./minus/  $(VPATH)/minus/*.f90 
clean:
	rm *.o *.out *.mod

main.o: CommonData/*.f90 Main/main.f90 #sub_add.o #sub_minus.o 
sub_multiply.o: Main/sub_multiply.f90
sub_add.o: add/sub_add.f90   #sub_add.f90 #
sub_minus.o: minus/sub_minus.f90    #minus/sub_minus.f90	

OBJS= main.o sub_add.o  sub_minus.o
Make命令   在make命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些参数指定了需要编译的目标文件。其标准形式为:   target1 [target2 …]:[:][dependent1 …][;commands][#…]   [(tab) commands][#…]   方括号中间的部分表示可选项。Targetsdependents当中可以包含字符、数字、句点"/"符号。除了引用,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模式,输出有关文件检测时间的详细信息。   linux下make标志位的常用选项与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、付费专栏及课程。

余额充值