简体   繁体   English

简单的Makefile问题(具有简单的依赖性)

[英]Simple Makefile Problem (with a simple dependency)

I have 4 '.cpp' files and 1 header files: 我有4个'.cpp'文件和1个头文件:

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

and Tools.hh

Now all Code1.cpp, Code2.cpp, Code3.cpp use functions stored in Tools.cpp . 现在,所有Code1.cpp, Code2.cpp, Code3.cpp使用存储在Tools.cpp函数。

Currently, what I do to compile all of them is using this simple shell script: 目前,我要编译所有这些文件的工作是使用以下简单的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

It all works fine. 一切正常。

Now I want to do that using a standard makefile. 现在,我想使用标准的makefile来做到这一点。 But why this doesnt' work: 但是为什么这不起作用:

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 $@  

The error I got is this: 我得到的错误是这样的:

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

How can I correct the mistakes? 我该如何纠正错误?

In short, $^ isn't what you want here. 简而言之, $^不是您想要的。 It evaluates to the "names of all the prerequisites, with spaces between them." 评估结果为“所有必备项的名称,并在它们之间留有空格”。 In the problem Makefile, that causes all three targets to use almost identical command lines, that each look like 在问题Makefile中,这导致所有三个目标使用几乎相同的命令行,每个命令行看起来像

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

From the error message quoted, g++ has decided that makefile should be passed to the linker as if it were an object. 根据所引用的错误消息,g ++决定将makefile当作对象传递给链接器。 It isn't. 不是。 Without makefile on the line, you would still be compiling and linking all four of your source files, and quite likely leaving the linker to decide which of four main() functions to use. 如果没有makefile,您仍然会编译和链接所有四个源文件,并且很可能让链接器决定要使用四个main()函数中的哪个。

You probably want to leverage the fact that make has a huge number of builtin rules for common cases. 您可能想利用make在常见情况下具有大量内置规则的事实。 Compiling two source files and linking the result fits neatly into those common cases. 编译两个源文件并将结果链接起来非常适合那些常见情况。 Its untested, but the following should do all you want (assuming a recent build of gnu make, at least), and have the advantage of only compiling each object once. 它未经测试,但是下面的命令可以满足您的所有需求(至少假设是最近构建的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

If you needed to set some compiler options you could add a definition for CXXFLAGS, traditionally near the top of the file. 如果需要设置一些编译器选项,则可以为CXXFLAGS添加一个定义,通常在文件顶部附近。

In these targets: 在这些目标中:

Code1: $(TOOLSRC) $(TOOLSINC) makefile
    $(CXX) $^ -o $@

The resulting command will be: 结果命令将是:

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

This is clearly not what you want. 这显然不是您想要的。 g++ is attempting to compile both the header file and the makefile and doesn't know what to do with the makefile . g++试图同时编译头文件和makefile ,但不知道如何处理makefile You're also declaring dependencies on all three of your main units for each unit. 您还要声明每个单元对所有三个主要单元的依赖性。 So if Code3.cpp changes, Code1 will require recompilation. 因此,如果Code3.cpp更改,则Code1将需要重新编译。 This is also undesirable. 这也是不希望的。

Try something like this instead: 尝试这样的事情:

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 $@ $^

Hm. Normally you'd specify dependencies on object files, with ".o" extensions. 通常,您将使用.o扩展名指定对目标文件的依赖性。 It might be that Make is being confused, since it has built-in rules for files of various types. 因为Make具有针对各种类型文件的内置规则,所以可能会感到困惑。

The error is because you're trying to link the makefile into the program, by passing $^ to the compiler. 该错误是因为您试图通过将$ ^传递给编译器来将makefile链接到程序中。

On the right hand side of a rule you should put only the files that are usefull. 在规则的右侧,您应该放置有用的文件。

Code1: Code1.cpp Tools.cpp
    $(CXX) $^ -o $@
Code1: Code2.cpp Tools.cpp
    $(CXX) $^ -o $@
Code3: Code3.cpp Tools.cpp
    $(CXX) $^ -o $@

While this solves your problem you should definitely read Grayfade's answer on how to do things the "Right Way". 当这解决了您的问题时,您绝对应该阅读Grayfade的“正确方法”答案。

I am no expert at makefiles, but this is how I usually do it, and it works well. 我不是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}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM