【问题标题】:Makefile error when compiling with gfortran on Mac OS在 Mac OS 上使用 gfortran 编译时出现 Makefile 错误
【发布时间】:2012-03-07 10:20:03
【问题描述】:

我使用最新的 Xcode (4.3) 运行 Mac OS X lion:

gfortran --version # -> GNU Fortran (GCC) 4.6.1
gcc --version # -> i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658)

我的 makefile 报错:

gfortran temp/modules.o temp/testModules.o temp/mathFunctions.o temp/functionTest.o -o arenatest
ld: duplicate symbol ___rng_MOD_uni in temp/testModules.o and temp/modules.o for architecture x86_64
collect2: ld returned 1 exit status
make: *** [arenatest] Error 1

我不明白原因是什么,所以我尝试编写一个构建脚本来做同样的事情,而且令人惊讶的是它产生了奇迹。我想要一个makefile而不是一个脚本,所以有人能发现其中的区别吗?我完全没有想法。

我知道有一个时髦的循环替换脚本用于在正确的子目录中生成 .o 对象。然而,构建/编译命令似乎完美匹配。如果有更聪明的方法,我愿意提供建议。

脚本:

echo remove old files
rm *.mod
rm *.o
rm -rf temp
rm arenatest

echo create directories and compile:
mkdir -p temp
gfortran -cpp -c ../modules/modules.f90 -o temp/modules.o -J../buildtest -I../buildtest
gfortran -cpp -c ../modules/mathFunctions.f90 -o temp/mathFunctions.o -J../buildtest -I../buildtest
gfortran -cpp -c testModules.f90 -o temp/testModules.o -J../buildtest -I../buildtest
gfortran -cpp -c functionTest.f90 -o temp/functionTest.o -J../buildtest -I../buildtest

echo do linking: gfortran -cpp temp/modules.o temp/testModules.o temp/mathFunctions.o temp/functionTest.o -o arenatest
gfortran temp/modules.o temp/testModules.o temp/mathFunctions.o temp/functionTest.o -o arenatest

echo DONE!

制作文件:

PROGRAM = arenatest
BUILDDIR = temp
FC = gfortran
SRC = ../modules/modules.f90 ../modules/mathFunctions.f90 testModules.f90 functionTest.f90
OBJ = $(SRC:.f90=.o)
OBJECTS = $(foreach var, $(OBJ), $(BUILDDIR)/$(lastword $(subst /, , $(var))) )
FLAGS =-J../buildtest -I../buildtest


all: buildtest

buildtest: $(PROGRAM)

build_message:
    @echo
    @echo sources:
    @echo $(SRC)
    @echo objects:
    @echo $(OBJECTS)

clean:
    rm -rf temp
    rm arenatest
    rm *.mod
    rm *.o


mkdir:
    @echo create directories and compile:
    mkdir -p temp

# 
# gfortran -cpp -c ../modules/modules.f90 -o temp/modules.o -J../buildtest -I../buildtest
# gfortran -cpp -c ../modules/mathFunctions.f90 -o temp/mathFunctions.o -J../buildtest -I../buildtest
# gfortran -cpp -c testModules.f90 -o temp/testModules.o -J../buildtest -I../buildtest
# gfortran -cpp -c functionTest.f90 -o temp/functionTest.o -J../buildtest -I../buildtest
# 
$(OBJECTS) : $(SRC) | mkdir
    $(FC) -c $(FLAGS) $< -o $@
# link: #echo do linking: gfortran -cpp temp/modules.o temp/testModules.o temp/mathFunctions.o temp/functionTest.o -o arenatest
$(PROGRAM): $(OBJECTS) | build_message
    $(FC) $(FLAGS) $(OBJECTS) -o $(PROGRAM)

#echo DONE!

【问题讨论】:

  • Make 应该回显它正在运行的所有命令。只需看看它的输出,并确保所有编译器调用都完全符合您的预期。
  • 它看起来很结实。我无法理解为什么它可以在命令行中输入而不是通过运行 make 来工作。今天下午我会仔细检查所有的调用..

标签: macos linker makefile ld gfortran


【解决方案1】:

编译目标文件的方法是错误的。扩展变量后将如下所示:

temp/modules.o temp/mathFunctions.o temp/testModules.o temp/functionTest.o: ../modules/modules.f90 ../modules/mathFunctions.f90 testModules.f90 functionTest.f90 | mkdir
    $(FC) -c $(FLAGS) $< -o $@

实际上,这意味着每个目标文件都依赖于所有源文件。此外,此配方的每次调用都会将自动变量$&lt; 设置为此源文件列表中的第一个变量。这将导致所有目标文件都是从同一个源文件编译的(因此当然都具有相同符号的定义)。

【讨论】:

  • 这就解释了!那么我该如何解决呢?这似乎不起作用:$(BUILDDIR)/%.o : %.f90 | mkdir $(FC) $(FLAGS) $&lt; -o $@
  • 没关系,我的子目录有问题,我在这里找到解决方案:stackoverflow.com/questions/231229/…
  • 最简单的解决方案?坚持Paul's Third Rule of Makefiles:不要使用temp 目录,而是在当前工作目录中构建目标文件。结合vpath 定位源文件,您可以使用简单的模式规则,如%.o: %.f90,并惊叹于您的Makefile 变得多么简单和容易理解/维护。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
相关资源
最近更新 更多