You need this rule so that make knows that it must remake main.o whenever defs.h changes. You can see that for a large program you would have to write dozens of such rules in your makefile. And, you must always be very careful to update the makefile every time you add or remove an #include.
To avoid this hassle, most modern C compilers can write these rules for you, by looking at the #include lines in the source files.
Usually this is done with the -M option to the compiler. For example, the command, cc -M main.c, generates the output: main.o : main.c defs.h.
Thus you no longer have to write all those rules yourself. The compiler will do it for you.
That command would create a file depend containing all the automatically-generated dependencies; then the makefile could use include to read them in (see Including other makefiles).
In GNU make, the feature of remaking makefiles makes this practice obsoleteyou need never tell make explicitly to regenerate the dependencies, because it always regenerates any makefile that is out of date. See How makefiles are remade.
The practice we recommend for automatic dependency generation is to have one makefile corresponding to each source file.
For each source file, name.c, there is a makefile, name.d, listing which files on which the object file, name.o, depends.
That way only the source files that have changed need to be rescanned to produce the new dependencies.
The following is an example
of the pattern rule to generate a file of dependencies (i.e., a makefile)
called name.d
from a C source file called name.c.
See Defining and redefining pattern rules for information on defining pattern rules. The -e flag to the shell makes it exit immediately if the $(CC) command fails (exits with a nonzero status). Normally the shell exits with the status of the last command in the pipeline (sed in this case), so make would not notice a nonzero status from the compiler.
With the GNU C compiler, you may wish to use the -MM flag instead of -M.
This omits dependencies on system header files. See Options Controlling the Preprocessor in Using GNU CC in GNUPro Compiler Tools for details. For example, the purpose of the sed command is to translate main.o : main.c defs.h into: main.o main.d : main.c defs.h.
This makes each .d
file depend on all the source and header files on which the corresponding
.o
file depends. make
then knows it must regenerate the dependencies whenever any of the source
or header files changes. Once youve defined the rule to remake the .d
files, you then use the include
directive to read them all in. See Including
other makefiles. Use the following example, for clarification.
include $(sources:.c=.d)
This example uses a substitution variable reference to translate the list of source files, foo.c bar.c, into a list of dependency makefiles, foo.d bar.d. See Substitution references for information on substitution references. Since the .d files are makefiles like any others, make will remake them as necessary with no further work from you. See How makefiles are remade.