是否修改了makefile中提到的依赖关系,make不能识别?

时间:2013-08-22 11:16:56

标签: c++ makefile virtual

在我的代码中,我使用了三个类。所有类都在单独的文件中。我正在使用Makefile来编译和链接它们。 请参阅以下实施:

class Medicine 
{ 
   int a;
}

class Pain:public Medicine 
{
   int b;
}

class Comb:public Pain   
{
    string salt,com;
}

在所有三个类中,所有类都只有参数化构造函数,虚拟析构函数和具有相同名称call()的函数。 而call()就像

call()
{
     cout<<"You are in class the_name_of_the_class"<<endl;
}

main.cpp的代码如下:

int main()
{       
    Medicine *p[2];
    p[0]= new Comb("Salt","Com",2,110);
    p[1]= new Comb("SALT","COM",1,100);

    p[0]->call();

    delete p[0];
    delete p[1];
    return 0;
}

当我运行这个程序时,我得到了预期的输出。但当我将Medicine :: call()更改为虚函数,并再次使用make命令时,它表示所有文件都是最新的。由于我修改了medicine.h,因此make应创建medicine.o的新版本。当我修改medicine.o时,为什么考虑更新旧版medicine.h

Makefile是这样的:

using .PHONY:clean
OBJ:=medicine.o pain.o comb.o main.o
SOU:=medicine.cpp pain.cpp comb.cpp main.cpp

main:$(OBJ)
        g++ -o $@ $^

%.o:%.cpp
        g++ -c -o $@ $<

clean:
        rm *.o main

如果你想看到medicine.h的实现,

class Medicine
{
    int cost;

 public:

    int getCost();
    void setCost(int);

    Medicine();
    Medicine(int);
    Medicine(Medicine &a);
    virtual string getCompany(){};
    virtual string getSalt(){};
    virtual  ~Medicine ();
    virtual void call();
};

medicine.h我已将其medicine.cpp包括在{{1}}中,其中定义了所有这些功能。

4 个答案:

答案 0 :(得分:3)

问题是medicine.o仅取决于medicine.cpp,而不取决于medicine.h。因此,您必须修改规则以提供缺少的依赖项。它完全与&#34;虚拟&#34;无关。

您可能还希望将Makefile本身添加为依赖项,因此如果您更改它并运行make,则会重新构建。

澄清一下这个通用规则:

%.o:%.cpp
    g++ -c -o $@ $<

表示任何something.o仅取决于something.cpp,并且应使用以下命令构建:

g++ -c -o something.o something.cpp

即。 $@是目标名称,$<是第一个依赖项。

格式为

target : <dependencies>
    command

答案 1 :(得分:1)

make不是语言感知的,所以是的,make不知道函数是否是虚拟的;实际上它甚至不知道C ++是什么以及那里有函数。

make根据目标和依赖关系运行,必须明确指定。这里,创建对象的规则不包含依赖项中的任何.h文件,因此它推断出.8文件未用于目标。

实际上很难获得构建一个.cpp文件所需的传递的正确集合。有一些脚本需要帮助,例如make_depend.pl

答案 2 :(得分:1)

问题是你的makefile没有你的头文件对源文件的依赖关系,所以它不知道你需要在“yh”改变时重新编译“x.cpp”(因为“是的” “包含在”x.cpp“中。

你可以通过以下规则来解决这个问题:

medicine.o : medicine.cpp medicine.h 

但是,随着源文件数量的增加,以及头与源的关系变得越来越复杂,您将忘记/遗漏一些您实际需要的头文件 - 这将始终发生。

我通常做的是这样的事情:

SOU = medicine.cpp pain.cpp comb.cpp main.cpp
... 

main:$(OBJ) .depends

...

.depends: $(SOU)
     g++ -MM $(SOU) > $@

include .depends

这样做是为了让编译器将规则生成到文件.depends中 - 这样,当你在某处更新文件时,你不会“忘记”修复它。

修改 对于大型项目,使用单个依赖项文件是一个糟糕的想法,因为每次更改.cpp文件时,编译器都必须为项目中的每个文件排序所有依赖项。但对于一个小型的业余爱好项目,这很好。对于大型项目,人们会额外承担大量.depends个文件(每个源文件一个,可能在depends目录中)。

答案 3 :(得分:0)

make的工作是这样的: 它检查依赖项的最新修改时间(例如medicine.cpp),然后在创建medicine.cpp时检查medicine.o的最新修改时间。如果两者相同,则不重新编译,否则重新编译。就我而言,medicine.h已被修改,但medicine.cpp的最新修改时间保持不变。这就是make无法检测到这一点而未重新编译medicine.cpp的原因。