将函数参数更改为const时,Makefile不起作用

时间:2017-09-14 08:00:19

标签: c++ makefile compiler-errors ld

使用makefile编译C ++代码时遇到一个奇怪的问题。代码首先编译完美。然后我将一个函数参数更改为“const”。如果我然后编译,当代码尝试使用我将参数更改为const的函数时,我将收到错误消息。这可以通过删除所有.o文件然后再次编译来解决,但我很好奇是什么原因导致了这个问题。我的文件是:

MyClass.h

class MyClass {
public:
void fun(double*const c);
};

MyClass.cpp

#include "MyClass.h"
void MyClass::fun(double *const c){
};

Main.cpp的

#include "MyClass.h"
int main(int argc,char* argv[]) {
    MyClass foo;
    double *bar=new double[2];
    foo.fun(bar);
};

生成文件

all: main

main: Main.o MyClass.o 
    g++ -o a.out Main.o MyClass.o


Main.o: Main.cpp
    g++ -c Main.cpp


MyClass.o: MyClass.cpp
    g++ -c MyClass.cpp

如果我现在第一次运行make,一切正常。但后来我将fun的签名更改为fun(const double *const c),收到错误消息

Main.cpp:(.text+0x3b): undefined reference to `MyClass::fun(double*)'
collect2: error: ld returned 1 exit status
Makefile:6: recipe for target 'main' failed
make: *** [main] Error 1

但是,如果我删除所有.o文件然后再次运行make,它就会编译。

2 个答案:

答案 0 :(得分:3)

规则

main.o: Main.cpp

表示main.o目标文件仅取决于Main.cpp源文件。 但是 它实际上取决于另一个文件:MyClass.h头文件。

目标名称的大小写也存在错误。

以上两个问题意味着当您更改头文件MyClass.h以更新函数签名时,将不会重新创建Main.o目标文件并仍引用旧函数。

所以规则应该是

Main.o: Main.cpp MyClass.h

当您更改头文件时,该添加将导致Main.o目标文件被重新编译。

此更改也应针对MyClass.o目标。

另请注意,main目标使用MyClass.o作为依赖项,但在链接时使用MyClass.cpp 文件,而不是目标文件

目标的名称也应该是生成的文件的名称(例如您的a.out)。

答案 1 :(得分:0)

问题是,你的Makefile坏了:它忽略了.o文件不仅依赖于相应的.cpp文件,还依赖于.h文件的事实包括。正确的Makefile规则必须包含所有依赖项,包括直接或间接包含的.h文件。

由于Makefile不完整,make在定义更改时没有重新编译函数的调用站点,因此陈旧对象仍引用非const函数。由于C ++名称更改,链接器在行为中捕获了它,错误在C中没有被注意到!

为了解决这个问题,我建议花一两个小时阅读这个article on automatic dependency generation,并在Makefile中实现它提供的一些解决方案。完成此操作后,您可能只需将现有解决方案复制到未来项目的Makefile中,否则就会忘记问题。