设计makefile以编译以不同方式配置的程序

时间:2015-07-27 10:14:50

标签: makefile fortran gnu-make

我有一个用Fortran编写的程序,它被设计为使用单精度浮点数(REAL)或双精度浮点数(使用例如GNU Fortran' {{1})定期编译})。我想设计一个makefile来为同一源代码中的每个类似程序构建-fdefault-real-8myprog。这是我到目前为止的抽象概念:

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旨在构建两个程序:makefilemyprog

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来源。

3 个答案:

答案 0 :(得分:2)

我会将这两个变体编译到不同的目标子目录中。或者至少将.mod文件放在那里,但我更愿意把它放在那里。

只需确保为模块目录使用正确的标志,该标志从编译器更改为编译器。 Gfortran使用-JI,英特尔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,但它会完成这项工作。