设计makefile以编译不同配置的程序
我有一个用Fortran编写的程序,该程序设计为使用单精度浮点(设计makefile以编译不同配置的程序,makefile,fortran,gnu-make,Makefile,Fortran,Gnu Make,我有一个用Fortran编写的程序,该程序设计为使用单精度浮点(REAL)或双精度浮点(例如使用GNU Fortran的-fdefault-REAL-8)定期编译。我想设计一个makefile,为来自相同源代码的每个类似程序构建myprog和myprog dbl。以下是我到目前为止的一个抽象概念: mymod.f-显示简单的浮点错误传播 MODULE mymod REAL :: var CONTAINS SUBROUTINE forerror(a
REAL
)或双精度浮点(例如使用GNU Fortran的-fdefault-REAL-8
)定期编译。我想设计一个makefile,为来自相同源代码的每个类似程序构建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
makefile
-GNU makefile设计用于构建两个程序:myprog
和myprog dbl
# 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
上述方法几乎有效,但并不完全有效。下面是我从shell获得的输出,首先是默认目标,即生成两个程序:
$ 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
目标构建两个类似的程序?我很乐意重建makefile
(或两个),但不重建Fortran源代码。更改标志不会改变这样一个事实,即如果以前使用不同的标志编译了mymod.o
,则它已经存在。Make只需查看时间戳和声明的依赖项就可以决定重建什么
一种解决方案是对使用不同选项编译的模块使用不同的文件名,然后只需将它们复制到适当的位置以进行最终链接
另一种方法是让mymod.o
依赖于一个包含构建时使用的标志的文件;当此文件更改时,需要重新生成mymod.o。但是,您可能希望避免不必要地重写此文件,以免在不必要时强制重新编译。也许是这样的:
flagfile.txt:
echo "$(FFLAGS)" >tmp
cmp tmp $@ && rm tmp || mv tmp $@
mymod.o: flagfile.txt
cmp | | mv
将创建一个临时文件,当临时文件的内容与旧内容不同时,仅更新flagfile.txt
。我将把这两个变体编译到不同的目标子目录中。或者至少把.mod
文件放在那里,但我更愿意把所有东西都放在那里
只需确保为模块目录使用正确的标志,它会随着编译器的不同而变化。Gfortran使用-J
和I
,英特尔Fortran使用-module
顺便说一句,fdefault-real-8不好看。在任何新代码中使用种类常量。我的建议是重写目标
all
,在两个可执行名称之间包括clean
,如
all: myprog clean myprog-dbl
最大的优点是只更改makefile的一行。
唯一的缺点是您不会使用已经存在的变量EXECS
,但它可以完成任务