我有一个用Fortran编写的程序,它被设计为使用单精度浮点数(REAL
)或双精度浮点数(使用例如GNU Fortran' {{1})定期编译})。我想设计一个makefile来为同一源代码中的每个类似程序构建-fdefault-real-8
和myprog
。这是我到目前为止的抽象概念:
myprog-dbl
- 显示简单的浮点错误传播
mymod.f
MODULE mymod
REAL :: var
CONTAINS
SUBROUTINE forerror(a,j)
REAL :: a
var=0.0
DO i=0,j,1
var=var+a
END DO
WRITE(*,*) "a=",a,"j=",j,"var=",var
END SUBROUTINE
END MODULE
- 计划的主要部分
myprog.f
PROGRAM test
USE mymod
CALL ForError(0.000001,10000000)
END PROGRAM
- GNU Makefile旨在构建两个程序:makefile
和myprog
myprog-dbl
上述几乎可行,但并非完全如此。这是我从shell获得的输出,首先是制作两个程序的默认目标:
# Variables
FC = gfortran
LD = $(FC)
EXECS = myprog myprog-dbl
OBJECTS = myprog.o mymod.o
# Targets
all : $(EXECS)
$(EXECS) : $(OBJECTS)
$(LD) $(LDFLAGS) -o $@ $^
# mymod must be built before prog
myprog.o : mymod.o
# Target-specific variable
myprog-dbl : FFLAGS += -fdefault-real-8
clean :
$(RM) $(OBJECTS) *.mod
.PHONY : all clean
但是,$ make all
gfortran -c -o mymod.o mymod.f
gfortran -c -o myprog.o myprog.f
gfortran -o myprog myprog.o mymod.o
gfortran -o myprog-dbl myprog.o mymod.o
$ ./myprog
a= 9.99999997E-07 j= 10000000 var= 9.59210873
$ ./myprog-dbl
a= 9.99999997E-07 j= 10000000 var= 9.59210873
结果没有使用适当的标志编译依赖对象,它与make myprog-dbl
相同。
在构建第二个程序之前需要清理对象:
myprog
现在它已经使用双精度浮点数构建。如何使用单个$ make clean
rm -f myprog.o mymod.o *.mod
$ make myprog-dbl
gfortran -fdefault-real-8 -c -o mymod.o mymod.f
gfortran -fdefault-real-8 -c -o myprog.o myprog.f
gfortran -o myprog-dbl myprog.o mymod.o
$ ./myprog-dbl
a= 9.9999999999999995E-007 j= 10000000 var= 10.000000999267517
目标构建两个类似的程序?我很乐意重建make all
(或两个),而不是Fortran来源。
答案 0 :(得分:2)
我会将这两个变体编译到不同的目标子目录中。或者至少将.mod
文件放在那里,但我更愿意把它放在那里。
只需确保为模块目录使用正确的标志,该标志从编译器更改为编译器。 Gfortran使用-J
和I
,英特尔Fortran使用-module
代替。
BTW -fdefault-real-8
很难看。在任何新代码中使用kind常量。
答案 1 :(得分:1)
如果先前使用不同的标志编译,则更改标志不会改变mymod.o
已存在的事实。简单地查看时间戳和声明的依赖关系来决定重建的内容。
一种解决方案是为使用不同选项编译的模块使用不同的文件名,然后将它们复制到位以进行最终链接。
另一种方法是让mymod.o
依赖于包含它所构建的标志的文件;当此文件更改时,需要重建mymod.o
。但是,您可能希望避免不必要地重写此文件,以免在没有必要时强制重新编译。也许是这样的:
flagfile.txt:
echo "$(FFLAGS)" >tmp
cmp tmp $@ && rm tmp || mv tmp $@
mymod.o: flagfile.txt
cmp || mv
将创建一个临时文件,并且仅在临时文件的内容与旧内容不同时才更新flagfile.txt
。
答案 2 :(得分:0)
我的建议是重写目标all
以在{2}之间包含clean
,例如
all: myprog clean myprog-dbl
最大的好处是只更改了makefile的一行。
唯一的缺点是你不会使用已经存在的变量EXECS
,但它会完成这项工作。