Makefile make re没有运行所有模式规则



在使用make re时创建依赖文件有问题。%.d模式规则在fclean之前被调用,allfclean之后只调用%.o模式规则。以下是我使用makemake 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运行时被重新创建。

一般来说,将运行cleanall作为先决条件的规则是一个坏主意。如果启用并行构建呢?现在make正在并行运行cleanall规则。如果您想这样做,您需要将它们作为sub-make调用,而不是通过先决条件调用,就像这样:

re:
$(MAKE) fclean
$(MAKE) all

这将确保每个目标都是串行构建的,即使是并行构建,并且make将从头开始构建all

你应该考虑的另一件事是使用更现代的依赖生成形式;例如:https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/

最新更新