我有4个'.cpp'文件和1个头文件:
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 $@
Code2: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $@
Code3: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $@
我得到的错误是:
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
如何纠正错误?
答案 0 :(得分:4)
简而言之,$^
不是你想要的。它评估“所有先决条件的名称,它们之间有空格”。在问题Makefile中,导致所有三个目标使用几乎相同的命令行,每个命令行看起来像
g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1
从引用的错误消息中,g ++已经决定将makefile作为对象传递给链接器。事实并非如此。如果没有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的定义,传统上靠近文件的顶部。
答案 1 :(得分:4)
在这些目标中:
Code1: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $@
结果命令为:
g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1
这显然不是你想要的。 g++
正在尝试编译头文件和makefile ,并且不知道如何处理makefile 。您还要为每个单元声明所有三个主要单元的依赖关系。因此,如果Code3.cpp发生更改,Code1将需要重新编译。 这也是不受欢迎的。
尝试这样的事情:
CXX = g++
all: Code1 Code2 Code3
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $@ $^
Code1: Code1.o Tools.o
$(CXX) -o $@ $^
Code2: Code1.o Tools.o
$(CXX) -o $@ $^
Code3: Code1.o Tools.o
$(CXX) -o $@ $^
答案 2 :(得分:2)
嗯。通常,您可以使用“.o”扩展名指定对象文件的依赖项。 Make可能会被混淆,因为它有各种类型文件的内置规则。
错误是因为你试图通过将$ ^传递给编译器来将makefile链接到程序中。
答案 3 :(得分:1)
在规则的右侧,您应该只将 放在有用的文件中。
Code1: Code1.cpp Tools.cpp
$(CXX) $^ -o $@
Code1: Code2.cpp Tools.cpp
$(CXX) $^ -o $@
Code3: Code3.cpp Tools.cpp
$(CXX) $^ -o $@
虽然这可以解决您的问题,但您一定要阅读Grayfade关于如何以“正确的方式”做事的答案。
答案 4 :(得分: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}