Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
设计makefile以编译不同配置的程序_Makefile_Fortran_Gnu Make - Fatal编程技术网

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

设计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

我有一个用Fortran编写的程序,该程序设计为使用单精度浮点(
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
,但它可以完成任务