Teach Makefile to check header dependencies
authorJonathan Nieder <jrnieder@gmail.com>
Tue, 26 Jan 2010 15:57:15 +0000 (09:57 -0600)
committerJonathan Nieder <jrnieder@gmail.com>
Wed, 27 Jan 2010 08:47:43 +0000 (02:47 -0600)
Add a target to use the gcc-generated makefile snippets for
dependencies on header files to check the hard-coded dependencies.

With this patch applied, if any dependencies are missing, then

make clean
make COMPUTE_HEADER_DEPENDENCIES=YesPlease
make CHECK_HEADER_DEPENDENCIES=YesPlease

will produce an error message like the following:

CHECK fast-import.o
missing dependencies: exec_cmd.h
make: *** [fast-import.o] Error 1

Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Makefile

index 630687f26e6453d2d0c2744f02b92e4a43ec22eb..45b1f54a6378f887b2f608adebf5fbd3770e791e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -221,6 +221,9 @@ all::
 # Define COMPUTE_HEADER_DEPENDENCIES if your compiler supports the -MMD option
 # and you want to avoid rebuilding objects when an unrelated header file
 # changes.
+#
+# Define CHECK_HEADER_DEPENDENCIES to check for problems in the hard-coded
+# dependency rules.
 
 GIT-VERSION-FILE: FORCE
        @$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -1088,6 +1091,14 @@ endif
 -include config.mak.autogen
 -include config.mak
 
+ifdef CHECK_HEADER_DEPENDENCIES
+USE_COMPUTED_HEADER_DEPENDENCIES =
+endif
+
+ifdef COMPUTE_HEADER_DEPENDENCIES
+USE_COMPUTED_HEADER_DEPENDENCIES = YesPlease
+endif
+
 ifdef SANE_TOOL_PATH
 SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH))
 BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|'
@@ -1681,9 +1692,7 @@ XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
        xdiff/xmerge.o xdiff/xpatience.o
 OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS)
 
-ASM_SRC := $(wildcard $(OBJECTS:o=S))
-ASM_OBJ := $(ASM_SRC:S=o)
-C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
+dep_files := $(foreach f,$(OBJECTS),$(dir $f)deps/$(notdir $f).d)
 
 ifdef COMPUTE_HEADER_DEPENDENCIES
 dep_dirs := $(addsuffix deps,$(sort $(dir $(OBJECTS))))
@@ -1691,33 +1700,89 @@ $(dep_dirs):
        mkdir -p $@
 
 missing_dep_dirs := $(filter-out $(wildcard $(dep_dirs)),$(dep_dirs))
-else
+dep_file = $(dir $@)deps/$(notdir $@).d
+dep_args = -MF $(dep_file) -MMD -MP
+ifdef CHECK_HEADER_DEPENDENCIES
+$(error cannot compute header dependencies outside a normal build. \
+Please unset CHECK_HEADER_DEPENDENCIES and try again)
+endif
+endif
+
+ifndef COMPUTE_HEADER_DEPENDENCIES
+ifndef CHECK_HEADER_DEPENDENCIES
 dep_dirs =
 missing_dep_dirs =
+dep_args =
+endif
+endif
+
+ifdef CHECK_HEADER_DEPENDENCIES
+ifndef PRINT_HEADER_DEPENDENCIES
+missing_deps = $(filter-out $(notdir $^), \
+       $(notdir $(shell $(MAKE) -s $@ \
+               CHECK_HEADER_DEPENDENCIES=YesPlease \
+               USE_COMPUTED_HEADER_DEPENDENCIES=YesPlease \
+               PRINT_HEADER_DEPENDENCIES=YesPlease)))
+endif
 endif
 
+ASM_SRC := $(wildcard $(OBJECTS:o=S))
+ASM_OBJ := $(ASM_SRC:S=o)
+C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS))
+
 .SUFFIXES:
 
+ifdef PRINT_HEADER_DEPENDENCIES
+$(C_OBJ): %.o: %.c FORCE
+       echo $^
+$(ASM_OBJ): %.o: %.S FORCE
+       echo $^
+
+ifndef CHECK_HEADER_DEPENDENCIES
+$(error cannot print header dependencies during a normal build. \
+Please set CHECK_HEADER_DEPENDENCIES and try again)
+endif
+endif
+
+ifndef PRINT_HEADER_DEPENDENCIES
+ifdef CHECK_HEADER_DEPENDENCIES
+$(C_OBJ): %.o: %.c $(dep_files) FORCE
+       @set -e; echo CHECK $@; \
+       missing_deps="$(missing_deps)"; \
+       if test "$$missing_deps"; \
+       then \
+               echo missing dependencies: $$missing_deps; \
+               false; \
+       fi
+$(ASM_OBJ): %.o: %.S $(dep_files) FORCE
+       @set -e; echo CHECK $@; \
+       missing_deps="$(missing_deps)"; \
+       if test "$$missing_deps"; \
+       then \
+               echo missing dependencies: $$missing_deps; \
+               false; \
+       fi
+endif
+endif
+
+ifndef CHECK_HEADER_DEPENDENCIES
 $(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs)
        $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $<
-%.s: %.c GIT-CFLAGS FORCE
-       $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
 $(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs)
        $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $<
+endif
 
-ifdef COMPUTE_HEADER_DEPENDENCIES
+%.s: %.c GIT-CFLAGS FORCE
+       $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $<
+
+ifdef USE_COMPUTED_HEADER_DEPENDENCIES
 # Take advantage of gcc's on-the-fly dependency generation
 # See <http://gcc.gnu.org/gcc-3.0/features.html>.
-dep_files := $(wildcard $(foreach f,$(OBJECTS),$(dir f)deps/$(notdir $f).d))
-ifneq ($(dep_files),)
-include $(dep_files)
+dep_files_present := $(wildcard $(dep_files))
+ifneq ($(dep_files_present),)
+include $(dep_files_present)
 endif
-
-dep_file = $(dir $@)deps/$(notdir $@).d
-dep_args = -MF $(dep_file) -MMD -MP
 else
-dep_args =
-
 # Dependencies on header files, for platforms that do not support
 # the gcc -MMD option.
 #