On Tue, 2025-05-06 at 21:58 +0800, lijh.8 wrote: > I have been so confused for years everytime when I read the example > in manual section 4.14 `Generating Prerequisites Automatically`. > So, The rule in 4.14 tries to keep the `.d` files. > When a `.d` file is deleted eg. from command line, the rule will > regenerate it. > Am i understanding it correctly?
I wouldn't say it as "the rule tries to keep the .d files". Thinking of it as "keeping" the files is perhaps confusing you. There's no difference in how make considers these rules than any other rule. "Something" tells make that this file should become up to date. Make follows its normal behavior: it looks for explicit or implicit rules that can build that target. It finds one, in the pattern rule. That pattern rule says: "if you want to build a .d file, you can build it from a .c file". So make checks the timestamp of the .c file and compares it to the .d file. If the .c file is newer, the .d file is out of date and make runs its recipe to bring it up to date. In addition, the sed command creates various .d files and these files add extra prerequisites to the .d file target. You can go look at the contents of these .d files to see what they do. This means that if any of those extra prerequisites (header files) change, that will ALSO cause the .d file to be out of date and rebuilt. This is all pretty standard make: no magic really. The unusual/magic part is the "something that tells make that these files should become up to date". Normally that's done either by a command-line goal (like "make all") or the default target. But GNU Make also adds a special extra set of goals: all the makefiles that were parsed. Make will consider each of those as targets to be built, before any other targets. And the second magic bit is, if any of those makefile targets are rebuilt, make will re-exec itself and start all over again: re-read all the makefiles from scratch so that the updated dependency information is used. > Also the 4.14 example works with the first two style of the include > in makefile. Why the last two do not work? > > -include $(patsubst %.cpp,%.d,$(wildcard *.cpp)) # ok > -include $(sources:.c=.d) # ok > -include $(wildcard *.d) # error > -include *.d # error It's not clear what you meany by "error" here. make should not generate any error messages for these lines. However, the reason the last two will not do what what you want is exactly the same reason that you can't write this rule: myprog : $(wildcard *.o) and have it work the way you want: the wildcard / globbing pattern is expanded when the makefile is parsed, and it just looks at the files that exist on the disk at that time. When you run your build with a clean directory, there are no .d files and so the wildcard/include will include nothing. Because nothing is included, make will not try to rebuild anything (remember, make is only rebuilding the makefiles that were included). So, none of the .d files will ever be created.