【问题标题】:Makefile not working when changing function argument to const将函数参数更改为 const 时 Makefile 不起作用
【发布时间】:2018-02-23 02:43:59
【问题描述】:

我在使用 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,它会编译。

【问题讨论】:

    标签: c++ makefile compiler-errors ld


    【解决方案1】:

    规则

    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)。

    【讨论】:

    • 谢谢,main.o 与 Main.o 和 MyClass.cpp 是拼写错误,抱歉。然而,将 MyClass.h 作为依赖项包含在内确实解决了问题!但是一个问题,为什么添加 MyClass.h 作为 Main.cpp 的依赖项就足够了,而不是 MyClass.cpp?
    • @JonathanLindgren 因为make 已经识别出您更改了MyClass.cpp,因此需要重新编译。
    • 建议使用 -MD 或类似的 gcc 开关来自动生成这些依赖项
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-16
      • 2015-10-22
      • 1970-01-01
      • 2014-06-28
      • 2018-09-02
      • 1970-01-01
      相关资源
      最近更新 更多