为什么不在makefile中生成依赖项?

时间:2015-04-19 04:54:42

标签: c++ gcc makefile g++

我最近学会了如何使用Makefiles,我发现GCC / G ++会为你生成依赖:

$ g++ -MM file.cpp
file.o: file.cpp file.h

然后我认为显而易见的事情是使用它直接在文件中生成依赖项而不创建依赖文件:

CXX = g++

SRCS = $(wildcard src/*.cpp)
OBJS = $(SRCS:.cpp=.o)
OCT = $(CXX -MM $(SRCS))
OBJDIR = obj
CPPFLAGS = -Wall -I/usr/local/include -L/usr/local/lib -lGLEW -lglfw -lGL

.PHONY: all
all: $(OBJS)
    $(CXX) $(CPPFLAGS) $(OBJS) -o output

$(OCT)

.PHONY: clean
clean:
    rm -f obj/*

出于某种原因,我从未见过其他人这样做过;他们总是生成一个依赖文件。这个系统有问题吗?在我的情况下是 - 对象不会转到OBJDIR,它们会转到源文件的位置。我相信这可以解决。如果有人知道如何解决这个问题以及为什么通常会生成依赖文件,请告诉我。

1 个答案:

答案 0 :(得分:1)

嗯,人们不这样做的第一个原因是它不可能做到:如果你试图让你的建议在现实生活中发挥作用,你会看到这一点。例如,你的例子根本不做任何事情。这样:

OCT = $(CXX -MM $(SRCS))

(我认为你的意思是$($(CXX) -MM $(SRCS)),但这两种方式无关紧要)是将名为CXX -MM $(SRCS)的make变量引用到变量OCT中:您可能认为它使用的是shell命令调用语法$(...),但这是一个 makefile ,而不是一个shell脚本。所以当你写:

$(OCT)

试图查找make变量,这显然不存在,所以这会扩展为空字符串,什么都没发生。如果您真的尝试通过触摸标题等来测试您的makefile,那么您将看不到任何重建。

你怎么能这样做?你不能这样做。您可以像这样更改变量赋值:

OCT = $(shell $(CXX) -MM $(SRCS))

这实际上会运行编译器,它正在朝着正确的方向移动,但是 shell函数的结果会将所有换行符更改为空格,所以这个:

$(OCT)

将扩展到一行上的编译器命令的整个输出,并且由于它包含多个冒号,您将收到语法错误。

您所能做的就是将编译器的输出重定向到一个文件,并使用make include功能来包含该文件。但现在您基本上回到了方案suggested in the GNU make manual,但您的版本效率较低,因为正如上面的评论中所指出的那样,您重新生成所有标题每次运行make时所有源文件,而不是仅重新生成实际更改的文件的头信息。

有更好/更有效的方法来生成标头,例如the one used by most GNU packages