2009-02-20 78 views
1

我有4 '的.cpp' 文件和1个文件:简单的makefile问题(用一个简单的依赖性)

Tools.cpp 
Code1.cpp 
Code2.cpp 
Code3.cpp 

and Tools.hh 

现在所有Code1.cpp, Code2.cpp, Code3.cpp 使用存储在Tools.cpp功能。

目前,我做什么来编译所有的人都用这个 简单的shell脚本:

#!/bin/bash 
echo "compiling Code1.cpp"; 
g++ Code1.cpp Tools.cpp -o Code1 

echo "compiling Code2.cpp"; 
g++ Code2.cpp Tools.cpp -o Code2 

echo "compiling Code3.cpp"; 
g++ Code3.cpp Tools.cpp -o Code3 

这一切工作正常。

现在我想用标准的makefile来做这件事。 但是,为什么这并不”工作:

CXX = g++ 

TOOLSRC = Tools.cpp Code1.cpp Code2.cpp \ 
Code3.cpp  

TOOLSINC = Tools.hh  

all: Code1 Code2 Code3 

Code1: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

Code2: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

Code3: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

我得到的错误是这样的:

ld: warning in makefile, file is not of required architecture 
ld: duplicate symbol neighbors(std::vector<int, std::allocator<int> >&, int, int)in /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccQCrGHe.o and /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccreq9YU.o 

collect2: ld returned 1 exit status 
make: *** [FindNeighbours] Error 1 

我怎样才能纠正错误?

回答

4

在这些目标:

Code1: $(TOOLSRC) $(TOOLSINC) makefile 
    $(CXX) $^ -o [email protected] 

得到的命令是:

g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1 

这显然不是你想要的。g++正在尝试编译头文件和生成文件,并不知道如何处理生成文件。你还要声明每个单元的所有三个主单元的相关性。所以如果Code3.cpp发生变化Code​​1将需要重新编译。 这也是不可取的。

尝试这样代替:

CXX = g++ 

all: Code1 Code2 Code3 

%.o: %.cpp 
    $(CXX) $(CXXFLAGS) -c -o [email protected] $^ 

Code1: Code1.o Tools.o 
    $(CXX) -o [email protected] $^ 

Code2: Code1.o Tools.o 
    $(CXX) -o [email protected] $^ 

Code3: Code1.o Tools.o 
    $(CXX) -o [email protected] $^ 
2

嗯。通常你会用“.o”扩展名指定对象文件的依赖关系。 Make可能会让人感到困惑,因为它内置了各种类型文件的规则。

错误是因为您想通过将$ ^传递给编译器来将makefile链接到程序中。

+0

嗨,有什么替代$ ^呢? – neversaint 2009-02-20 07:38:18

+0

你不应该需要任何东西,make应该能够推导出自己的构建命令。或者按照greyfade的建议做,不依赖于makefile。 – unwind 2009-02-20 07:56:39

1

在规则的右侧,你应该把只有这些文件是有用的。

Code1: Code1.cpp Tools.cpp 
    $(CXX) $^ -o [email protected] 
Code1: Code2.cpp Tools.cpp 
    $(CXX) $^ -o [email protected] 
Code3: Code3.cpp Tools.cpp 
    $(CXX) $^ -o [email protected] 

虽然这解决了您的问题,但您应该阅读Grayfade关于如何做“正确方法”的答案。

+0

这将使编译器不止一次地处理tools.cpp - 这是不必要的。请参阅下面的Greyfade以获取更好的解释,Rberteig更短的makefile。 – nimrodm 2009-02-20 08:21:06

4

总之,$^不是你想要的。它评估为“所有先决条件的名称,它们之间有空格”。在问题生成文件,导致所有三个目标使用几乎相同的命令线,使得每个像

g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1 

从援引该错误消息,克++已决定,生成文件应该被传递到链接器就好像它是一个目的。事实并非如此。如果没有makefile,你仍然会编译和链接所有四个源文件,而且很可能让链接器决定使用四个main()函数中的哪一个。

您可能希望利用make对常见情况具有大量内置规则的事实。编译两个源文件并将结果链接到这些常见情况。它的未经测试,但以下应该做你想做的一切(假设最近编译GNU make,至少),并且具有仅编译每个对象一次的优点。

all: Code1 Code2 Code3 
Code1: Code1.o Tools.o 
Code2: Code2.o Tools.o 
Code3: Code3.o Tools.o 

Code1.o Code2.o Code3.o Tools.o: Tools.hh 

如果您需要设置一些编译器选项,您可以为传统上靠近文件顶部的CXXFLAGS添加一个定义。

0

我在makefile文件不是专家,但是这是多么我通常做,效果很好。

COMPILER = g++ 
CXXFLAGS = 
EXECUTABLE = code 

all: code 

code: Code1.o Code2.o Code3.o Tools.o 
    ${COMPILER} ${CXXFLAGS} -o ${EXECUTABLE} Code1.o Code2.o Code3.o Tools.o 

Code1.o: Code1.cpp Tools.o 
    ${COMPILER} ${CXXFLAGS} -c Code1.cpp 

Code2.o: Code2.cpp Tools.o 
    ${COMPILER} ${CXXFLAGS} -c Code2.cpp 

Code3.o: Code3.cpp Tools.o 
    ${COMPILER} ${CXXFLAGS} -c Code3.cpp 

Tools.o: Tools.cpp Tools.hh 
    ${COMPILER} ${CXXFLAGS} -c Tools.cpp 

clean: 
    rm *.o 
    rm ${EXECUTABLE}