【发布时间】:2011-05-03 15:21:01
【问题描述】:
我有一个由许多不同的 .F 和 .h 文件组成的 FORTRAN 源代码。我需要从中构建一个可执行文件,但我遇到了一些问题。到目前为止我制作的makefile(可能有错误,因为我是新手)是:
# 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) $@ $<
%.o: %.F
$(FC) $(FLFLAGS) -o $@ $<
%.mod: %.h
$(FC) $(FLFLAGS) -o $@ $<
clean:
rm -f *.o *.mod
但是,当我尝试编写程序时,我遇到了许多未定义的引用错误。我的意思是,第一个编译的 .F 文件中的每个函数和子例程调用都会返回一个未定义的引用错误。我认为这是因为 gfortran 试图链接文件而不是仅编译它们然后在最后链接,但我认为“-c”选项应该可以防止这种情况发生。
更新:
正如评论者所指出的,我混淆了编译和链接标志。此外,您不应该编译 *.h 文件。这是最新的、更正后的 makefile:
# 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 $@ $<
%.o: %.F
$(FC) $(FCFLAGS) -o $@ $<
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 日
Sverre 指出了我的 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 $@ $^
%.o: %.F
$(FC) $(FCFLAGS) -o $@ $<
# %.mod: %.h
# $(FC) $(FCFLAGS) -o $@ $<
clean:
rm -f *.o *.mod
【问题讨论】:
-
Make 只是一种自动化您可以手动完成的任务的方法。你能在命令行上编译这段代码,而不用 Make 吗?如果没有,那么摆弄 makefile 将无济于事。
-
您正在将链接标志应用于编译,反之亦然。
-
源文件和头文件太多,依赖项太多,我无法手动完成。无人问津,你是对的。我愚蠢地切换了这两个变量。将它们切换回来允许我构建 .f 文件。 gfortran 给了我 .h 文件的错误。似乎认为它们是C文件。但这是另一个问题。感谢您的帮助。
-
您似乎正在尝试构建您的
*.h文件,您不应该这样做。如果我没记错的话,%.mod: *.h下的$<会挑选出第一个*.h文件。也许您想以包含模块的*.F文件为首? (尽管我必须承认我从不担心我的 makefile 中的*.mods) -
另外,我想补充一点,这个问题的最终解决方案可能不适用于 F90、F2003 和 F2008 源文件,因为使用模块会施加依赖关系,然后对象“*.o”文件具有他们自己的依赖关系,他们需要以一种特殊的方式重新排序。在这种一般情况下,解决方案发布在stackoverflow.com/questions/25705273/…。