2011-05-03 106 views
12

我有一个FORTRAN源代码包含许多不同的.F和.h文件。我需要从它构建一个可执行文件,但是我遇到了一些问题。我生产至今(其中可能有错误,因为我是新来的这个)的生成文件是:创建一个FORTRAN生成文件

# compiler 
FC = /usr/bin/gfortran-4.5 

# compile flags 
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons 
# link flags 
FLFLAGS = -g -fbacktrace 

# source files and objects 
SRCS = $(patsubst %.F, %.o, $(wildcard *.F)) \ 
     $(patsubst %.h, %.mod, $(wildcard *.h)) 

# program name 
PROGRAM = blah 

all: $(PROGRAM) 

$(PROGRAM): $(SRCS) 
    $(FC) $(FCFLAGS) [email protected] $< 

%.o: %.F 
    $(FC) $(FLFLAGS) -o [email protected] $< 

%.mod: %.h 
    $(FC) $(FLFLAGS) -o [email protected] $< 

clean: 
    rm -f *.o *.mod 

当我试图使程序,但是,我得到未定义引用错误的转换。我的意思是,在第一个编译的.F文件中的每个函数和子程序调用都会返回一个未定义的引用错误。我认为这是因为gfortran试图链接文件,而不是仅仅编译它们,然后在最后连接,但我认为'-c'选项应该阻止这种情况。

UPDATE:

正如评论者所指出的那样,我是混合了编译和链接标志。而且,你不应该编译* .h文件。下面是最新的,纠正生成文件:

# compiler 
FC = /usr/bin/gfortran-4.4 

# compile flags 
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons -fbounds-check -std=legacy 
# link flags 
FLFLAGS = 

# source files and objects 
SRCS = $(patsubst %.F, %.o, $(wildcard *.F)) 

# program name 
PROGRAM = blah 

all: $(PROGRAM) 

$(PROGRAM): $(SRCS) 
    $(FC) $(FLFLAGS) -o [email protected] $< 

%.o: %.F 
    $(FC) $(FCFLAGS) -o [email protected] $< 

clean: 
    rm -f *.o *.mod 

现在,当我运行make,它将编译代码中的每个* .F文件,但它在链接阶段失败。我在第一个* .F文件中遇到了一堆未定义的引用错误。编译器似乎在连接阶段单独检查每个* .F文件,我不确定是否正确。然后,我得到一个错误:

/usr/lib/gcc/x86_64-linux-gnu/4.4.5/libgfortranbegin.a(fmain.o): In function `main': 
(.text+0x26): undefined reference to `MAIN__' 
collect2: ld returned 1 exit status 

但是,如果我键入命令:

gfortran -o blah *.o 

的可执行文件将被建成,所以好像我做错了什么事中的makefile链接阶段。

更新:2011年5月9日

斯维尔指出,最终的问题与我的makefile。在我构建该程序的第一个目标中,我仅对第一个依赖项($ <)使用快捷命令,但我需要使用($ ^)快捷方式包含所有依赖项(即所有* .o文件)。最终的工作makefile如下:

# compiler 
FC  := /usr/bin/gfortran-4.5 

# compile flags 
FCFLAGS = -g -c -fdefault-real-8 -fbacktrace -fno-align-commons -fbounds-check 
# link flags 
FLFLAGS = 

# source files and objects 
SRCS = $(patsubst %.F, %.o, $(wildcard *.F)) 
#  $(patsubst %.h, %.mod, $(wildcard *.h)) 

# program name 
PROGRAM = vipre 

all: $(PROGRAM) 

$(PROGRAM): $(SRCS) 
    $(FC) $(FLFLAGS) -o [email protected] $^ 

%.o: %.F 
    $(FC) $(FCFLAGS) -o [email protected] $< 

# %.mod: %.h 
# $(FC) $(FCFLAGS) -o [email protected] $< 

clean: 
    rm -f *.o *.mod 
+0

Make只是一种自动完成手动任务的方法。你可以在命令行上编译这些代码吗?如果没有,那么摆弄makefile将无济于事。 – Beta 2011-05-03 15:24:13

+5

您正在将链接标志应用于编译,反之亦然。 – 2011-05-03 15:26:33

+0

对于我来说,有太多的源文件和头文件需要手动完成。 unapersson,你是对的。我愚蠢地改变了这两个变量。将它们切换回来允许我构建.f文件。虽然gfortran给了我.h文件的错误。它似乎认为他们是C文件。但那是另一个问题。谢谢您的帮助。 – Bob 2011-05-03 15:49:43

回答

11

您使用的是GNU make吗?如果是这样,

$(FC) $(FLFLAGS) -o [email protected] $< 

可能是罪魁祸首。 $<第一个的先决条件,但您希望所有*.o文件的名称。请尝试使用$^代替。

+2

是的,这是完美的。我做了改变,它工作。最后的工作makefile发布在我原来的问题中。有趣的是,我有一天在我的办公室实际追踪了这个代码的makefile。但是,它比我的长20倍,因为它们列出了每个个体的依赖关系。非常高兴我学会了正确的方式来做到这一点。 – Bob 2011-05-09 14:28:37

+1

如果一个答案解决了你的问题,你应该标记它 – steabert 2012-01-22 10:17:49

+0

通常人们使用'$(FFLAGS)'而不是'$(FLFLAGS)' – 2016-06-26 10:19:20