在使用make re
时创建依赖文件有问题。%.d
模式规则在fclean
之前被调用,all
在fclean
之后只调用%.o
模式规则。以下是我使用make
和make re
时的输出:
mkdir -p srcs/depends
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -MM srcs/tests.cpp -o srcs/depends/tests.d
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -MM srcs/main.cpp -o srcs/depends/main.d
mkdir -p srcs/obj
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/main.cpp -o srcs/obj/main.o
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/tests.cpp -o srcs/obj/tests.o
c++ -lstdc++ srcs/obj/main.o srcs/obj/tests.o -o main
vs (make re
)
rm -f -rv srcs/obj srcs/depends
srcs/obj/main.o
srcs/obj/tests.o
srcs/obj
srcs/depends/main.d
srcs/depends/tests.d
srcs/depends
rm -f main
mkdir -p srcs/obj
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/main.cpp -o srcs/obj/main.o
c++ -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes -c srcs/tests.cpp -o srcs/obj/tests.o
c++ -lstdc++ srcs/obj/main.o srcs/obj/tests.o -o main
我的makefile。
NAME = main
SRCSDIR = srcs
SRCS = $(wildcard $(SRCSDIR)/*.cpp)
OBJSDIR = srcs/obj
OBJS = $(SRCS:$(SRCSDIR)/%.cpp=$(OBJSDIR)/%.o)
DEPENDSDIR = srcs/depends
DEPENDS = $(SRCS:$(SRCSDIR)/%.cpp=$(DEPENDSDIR)/%.d)
CPPFLAGS = -Wall -Werror -Wextra -Wshadow -std=c++98 -pedantic -Iincludes
DEPFLAGS = -MM
LDFLAGS = -lstdc++
all: $(NAME)
$(NAME): $(OBJS)
c++ $(LDFLAGS) $^ -o $@
$(OBJSDIR)/%.o: $(SRCSDIR)/%.cpp | $(OBJSDIR)
c++ $(CPPFLAGS) -c $< -o $@
$(DEPENDSDIR)/%.d: $(SRCSDIR)/%.cpp | $(DEPENDSDIR)
c++ $(CPPFLAGS) $(DEPFLAGS) $< -o $@
$(OBJSDIR) $(DEPENDSDIR):
mkdir -p $@
-include $(DEPENDS)
clean:
$(RM) -rv $(OBJSDIR) $(DEPENDSDIR)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all clean fclean re
我已经查了gnu make文档,找不到任何细节。(也许我不知道去哪里查)。有人知道为什么吗,或者有其他更干净的解决方案吗?提前感谢
您正在使用旧式头文件生成方法,其中make构建依赖文件,然后重新执行自身以读取更改的依赖文件。因此,当您首先运行make时,它会解析当前存在的所有.d
文件(由于include
行),然后它会尝试重新构建.d
文件,然后如果有任何更改,它会重新执行,然后它会运行makefile的其余部分。一旦它加载了所有.d
文件并确定它们是最新的,make就完成了对它们的处理(对于该调用)。如果它们稍后被删除,它将不会尝试重新创建它们。它们将在下次 make运行时被重新创建。
一般来说,将运行clean
和all
作为先决条件的规则是一个坏主意。如果启用并行构建呢?现在make正在并行运行clean
和all
规则。如果您想这样做,您需要将它们作为sub-make调用,而不是通过先决条件调用,就像这样:
re:
$(MAKE) fclean
$(MAKE) all
这将确保每个目标都是串行构建的,即使是并行构建,并且make将从头开始构建all
。
你应该考虑的另一件事是使用更现代的依赖生成形式;例如:https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/