第一次尝试makefile

时间:2016-09-09 14:40:08

标签: c++ makefile

我正在编写第一个第二个makefile,因为在实际启动C ++项目之前我需要了解它们。这是我要链接的文件:

/storage/emulated/0/cpptest/test.h

#ifndef TEST_H_DEF
#define TEST_H_DEF

class Test {
    private:
        int value;
    public:
        Test(int);
        operator int();
        Test operator + (Test);
};

#endif

/storage/emulated/0/cpptest/test.cpp

#include "test.h"

Test::Test(int new_value):
    value(new_value) {}

Test::operator int() {
    return value;
}

Test Test::operator + (Test other) {
    return Test(value + int(other));
}

/storage/emulated/0/cpptest/main.cpp

#include <iostream>
#include "test.h"

int main() {
    Test o1(12);
    Test o2(18);
    std::cout << int(o1) << '\n';
    std::cout << int(o2) << '\n';
    std::cout << int(o1 + o2) << std::endl;
}

这是我对(可维护的)makefile的尝试:

CC = g++

default: test

#I'm actually using four spaces here on SO
test: main.o test.o
    $(CC) -o test main.o test.o

#my issue starts here: what does main.o depends on? My guess is main.cpp only (which is really /storage/emulated...main.cpp)
main.o: main.cpp
    $(CC) -o main.o /storage/emulated/0/cpptest/main.cpp

#same with test.o
test.o: test.cpp
    $(CC) -o test.o /storage/emulated/0/cpptest/test.cpp

然后呢?我现在好吗?如何在不知道的情况下处理test.h的问题?

在编写文件时,我是否也正确使用了.h和.cpp文件?

2 个答案:

答案 0 :(得分:5)

gcc可以为您生成依赖项。因此,不要手动输入源文件的所有依赖项(这将不可避免地是错误的或不完整的),而是使用编译器:

default: test
.PHONY : default

compiler := g++
objects  := main.o test.o
depends  := $(objects:.o=.d)

# include the depends rules if they exist
-include $(depends)

# test depends on all the objects, compiled together
test : $(objects)
    $(compiler) -o $@ $^

# each object depends on its source file
# the recipe here will both compile the source file and generate its dependencies
%.o : %.cpp
    $(compiler) -o $@ -c $< -MP -MMD -MF $(@:.o=.d)

这将为您生成名为main.dtest.d的文件,其中包含的makefile规则具有main.cpptest.cpp的实际依赖关系。

每当您对您的文件的有效性产生怀疑时,运行make -pn并检查在那里打印的所有内容总是有帮助的。这将有助于确保您的依赖项完全符合它们的应用程序。

例如,第一次编译时,*.d文件不存在,因此include $(depends)命令将失败(由于-include而无声),以及此makefile创建一个看起来像的依赖图:

enter image description here

您应该阅读此内容,因为如果任何节点的子节点已经更新,任何节点都需要重新运行其配方(我填写了default蓝色因为它是虚假的规则。)。因此,只要main.o更新,就需要重新编译main.cpp。请注意,test.h没有依赖关系!这似乎是一个错误,但无论如何我们必须重新编译一切,所以我们不会错过。在我们第一次编译之后,我们已经生成了*.d文件然后我们将它们带入了我们的include,新的依赖图看起来像:

enter image description here

这正是我们想要的。

答案 1 :(得分:1)

test.h的依赖关系适用于test.cpp和main cpp:

CC = g++

default: test

test: main.o test.o
    $(CC) -o test main.o test.o

main.o: main.cpp test.h
    $(CC) -o main.o /storage/emulated/0/cpptest/main.cpp

test.o: test.cpp test.h
    $(CC) -o test.o /storage/emulated/0/cpptest/test.cpp

我们的想法是,如果test.h内的某些内容发生变化,test.omain.o都必须重新制作。