Makefile - 使用修改后的头文件重建
Makefile - rebuild with modified header files
在我的项目中,我有一些包含方法的头文件(例如模板 类)。所有这些头文件都包含在一个文件 header.h
中,然后该文件包含在每个 cpp 文件中。这样,我只需要在一个地方更改代码。还有一些 .h
文件没有相应的 .cpp
文件。
然后我有这个生成文件:
# Makefile
.PHONY: run clean rebuild
CC = g++
CFLAGS = -Wall -Ofast -std=c++0x -pthread
RM = rm -f
EXEC = main
SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
$(EXEC): $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
%.o: %.cpp
$(CC) $(CFLAGS) -c $^
run: $(EXEC)
./$(EXEC)
clean:
$(RM) $(EXEC) *.o *.gch *~
rebuild: clean $(EXEC)
一切正常,除了一个小但恼人的细节:如果我修改一个 cpp 文件,那么我可以 make
并且一切都正确更新,但是如果我修改一个头文件,那么我必须删除所有内容并从头开始重新编译(这就是为什么我有那个丑陋的 rebuild
目标的原因),否则编辑将无效。
有没有一种方法可以在不重构整个代码的情况下使事情变得更好?
编辑
我试过这个 makefile
.PHONY: run clean rebuild
CC = g++
CFLAGS = -Wall -Ofast -std=c++0x -pthread
RM = rm -f
EXEC = main
SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
$(EXEC): $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
%.o: %.cpp headers.h
$(CC) $(CFLAGS) -c $<
run: $(EXEC)
./$(EXEC)
clean:
$(RM) $(EXEC) *.o *.gch *.d *~
rebuild: clean $(EXEC)
但结果不是我想要的:如果我修改单个头文件并执行 make
,它告诉我目标是最新的,而我希望重新编译它。
不是 Makefile 专家,看看 this。有多种使用 -MM
、-MD
和 -MF
gcc 标志的解决方案。投票最高的答案建议如下:
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
据我了解,这应该会为您生成正确的依赖项,这似乎是正确的方法。但是,我从未使用过它,我会尝试在依赖项中添加头文件(为 %.o
附加一个新目标):
%.o: %.cpp %.h header.h
$(CC) $(CFLAGS) -c $<
请注意,我已将 $^
更改为 $<
以便仅获取第一个依赖项(即 cpp),并且我附加了 header.h
以在更改时强制重新编译.最后一个可能不是必需的,这取决于你在那里做什么,它会导致编译效率低下,因为更改它会重新编译你所有的 .o
文件
假设您有 foo.cpp
,其中包含行:
#include "bar.h"
您的通用规则:
%.o: %.cpp
$(CC) $(CFLAGS) -c $^
当 bar.h
已被修改(并且 foo.o
被调用)时, 将不会重建 foo.o
。如果您有 foo.o
:
的附加规则,它将起作用
%.o: %.cpp
$(CC) $(CFLAGS) -c $< # note the change of automatic variable
foo.o: bar.h
手动编写这样的规则会很痛苦,但 g++ 会为您完成:
%.o: %.cpp
$(CC) $(CFLAGS) -c -MMD $<
此命令将生成文件 foo.d
(作为构建 foo.o
的副作用),其中包含以下行:
foo.o: bar.h
将那一行放在单独的文件中对您有什么好处?您可以使用如下一行(在 makefile 的末尾)将其拉入 makefile 中:
-include *.d
(如果这种方法看起来非常简单,那是因为很多聪明人对它进行了很多思考。)
在我的项目中,我有一些包含方法的头文件(例如模板 类)。所有这些头文件都包含在一个文件 header.h
中,然后该文件包含在每个 cpp 文件中。这样,我只需要在一个地方更改代码。还有一些 .h
文件没有相应的 .cpp
文件。
然后我有这个生成文件:
# Makefile
.PHONY: run clean rebuild
CC = g++
CFLAGS = -Wall -Ofast -std=c++0x -pthread
RM = rm -f
EXEC = main
SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
$(EXEC): $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
%.o: %.cpp
$(CC) $(CFLAGS) -c $^
run: $(EXEC)
./$(EXEC)
clean:
$(RM) $(EXEC) *.o *.gch *~
rebuild: clean $(EXEC)
一切正常,除了一个小但恼人的细节:如果我修改一个 cpp 文件,那么我可以 make
并且一切都正确更新,但是如果我修改一个头文件,那么我必须删除所有内容并从头开始重新编译(这就是为什么我有那个丑陋的 rebuild
目标的原因),否则编辑将无效。
有没有一种方法可以在不重构整个代码的情况下使事情变得更好?
编辑
我试过这个 makefile
.PHONY: run clean rebuild
CC = g++
CFLAGS = -Wall -Ofast -std=c++0x -pthread
RM = rm -f
EXEC = main
SRC = $(wildcard *.cpp)
OBJ = $(SRC:.cpp=.o)
$(EXEC): $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
%.o: %.cpp headers.h
$(CC) $(CFLAGS) -c $<
run: $(EXEC)
./$(EXEC)
clean:
$(RM) $(EXEC) *.o *.gch *.d *~
rebuild: clean $(EXEC)
但结果不是我想要的:如果我修改单个头文件并执行 make
,它告诉我目标是最新的,而我希望重新编译它。
不是 Makefile 专家,看看 this。有多种使用 -MM
、-MD
和 -MF
gcc 标志的解决方案。投票最高的答案建议如下:
depend: .depend
.depend: $(SRCS)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
据我了解,这应该会为您生成正确的依赖项,这似乎是正确的方法。但是,我从未使用过它,我会尝试在依赖项中添加头文件(为 %.o
附加一个新目标):
%.o: %.cpp %.h header.h
$(CC) $(CFLAGS) -c $<
请注意,我已将 $^
更改为 $<
以便仅获取第一个依赖项(即 cpp),并且我附加了 header.h
以在更改时强制重新编译.最后一个可能不是必需的,这取决于你在那里做什么,它会导致编译效率低下,因为更改它会重新编译你所有的 .o
文件
假设您有 foo.cpp
,其中包含行:
#include "bar.h"
您的通用规则:
%.o: %.cpp
$(CC) $(CFLAGS) -c $^
当 bar.h
已被修改(并且 foo.o
被调用)时, 将不会重建 foo.o
。如果您有 foo.o
:
%.o: %.cpp
$(CC) $(CFLAGS) -c $< # note the change of automatic variable
foo.o: bar.h
手动编写这样的规则会很痛苦,但 g++ 会为您完成:
%.o: %.cpp
$(CC) $(CFLAGS) -c -MMD $<
此命令将生成文件 foo.d
(作为构建 foo.o
的副作用),其中包含以下行:
foo.o: bar.h
将那一行放在单独的文件中对您有什么好处?您可以使用如下一行(在 makefile 的末尾)将其拉入 makefile 中:
-include *.d
(如果这种方法看起来非常简单,那是因为很多聪明人对它进行了很多思考。)