Skip to content

Commit

Permalink
kbuild: let fixdep directly write to .*.cmd files
Browse files Browse the repository at this point in the history
Currently, fixdep writes dependencies to .*.tmp, which is renamed to
.*.cmd after everything succeeds. This is a very safe way to avoid
corrupted .*.cmd files. The if_changed_dep has carried this safety
mechanism since it was added in 2002.

If fixdep fails for some reasons or a user terminates the build while
fixdep is running, the incomplete output from the fixdep could be
troublesome.

This is my insight about some bad scenarios:

[1] If the compiler succeeds to generate *.o file, but fixdep fails
    to write necessary dependencies to .*.cmd file, Make will miss
    to rebuild the object when headers or CONFIG options are changed.
    In this case, fixdep should not generate .*.cmd file at all so
    that 'arg-check' will surely trigger the rebuild of the object.

[2] A partially constructed .*.cmd file may not be a syntactically
    correct makefile. The next time Make runs, it would include it,
    then fail to parse it. Once this happens, 'make clean' is be the
    only way to fix it.

In fact, [1] is no longer a problem since commit 9c2af1c ("kbuild:
add .DELETE_ON_ERROR special target"). Make deletes a target file on
any failure in its recipe. Because fixdep is a part of the recipe of
*.o target, if it fails, the *.o is deleted anyway. However, I am a
bit worried about the slight possibility of [2].

So, here is a solution. Let fixdep directly write to a .*.cmd file,
but allow makefiles to include it only when its corresponding target
exists.

This effectively reverts commit 2982c95 ("kbuild: remove redundant
$(wildcard ...) for cmd_files calculation"), and commit 00d78ab
("kbuild: remove dead code in cmd_files calculation in top Makefile")
because now we must check the presence of targets.

Signed-off-by: Masahiro Yamada <[email protected]>
  • Loading branch information
masahir0y committed Dec 1, 2018
1 parent ce2fd53 commit 392885e
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 19 deletions.
13 changes: 7 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,8 @@ ifdef CONFIG_GDB_SCRIPTS
endif
+$(call if_changed,link-vmlinux)

targets := vmlinux

# Build samples along the rest of the kernel. This needs headers_install.
ifdef CONFIG_SAMPLES
vmlinux-dirs += samples
Expand Down Expand Up @@ -1758,13 +1760,12 @@ quiet_cmd_depmod = DEPMOD $(KERNELRELEASE)
cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \
$(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*)

# read all saved command lines
cmd_files := $(wildcard .*.cmd)
# read saved command lines for existing targets
existing-targets := $(wildcard $(sort $(targets)))

ifneq ($(cmd_files),)
$(cmd_files): ; # Do not try to update included dependency files
include $(cmd_files)
endif
cmd_files := $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
$(cmd_files): ; # Do not try to update included dependency files
-include $(cmd_files)

endif # ifeq ($(config-targets),1)
endif # ifeq ($(mixed-targets),1)
Expand Down
10 changes: 4 additions & 6 deletions scripts/Kbuild.include
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,8 @@ ifndef CONFIG_TRIM_UNUSED_KSYMS

cmd_and_fixdep = \
$(echo-cmd) $(cmd_$(1)); \
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\
rm -f $(depfile); \
mv -f $(dot-target).tmp $(dot-target).cmd;
scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\
rm -f $(depfile);

else

Expand All @@ -289,9 +288,8 @@ cmd_and_fixdep = \
$(echo-cmd) $(cmd_$(1)); \
$(ksym_dep_filter) | \
scripts/basic/fixdep -e $(depfile) $@ '$(make-cmd)' \
> $(dot-target).tmp; \
rm -f $(depfile); \
mv -f $(dot-target).tmp $(dot-target).cmd;
> $(dot-target).cmd; \
rm -f $(depfile);

endif

Expand Down
12 changes: 5 additions & 7 deletions scripts/Makefile.build
Original file line number Diff line number Diff line change
Expand Up @@ -529,18 +529,16 @@ FORCE:
# optimization, we don't need to read them if the target does not
# exist, we will rebuild anyway in that case.

cmd_files := $(wildcard $(foreach f,$(sort $(targets)),$(dir $(f)).$(notdir $(f)).cmd))
existing-targets := $(wildcard $(sort $(targets)))

ifneq ($(cmd_files),)
include $(cmd_files)
endif
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)

ifneq ($(KBUILD_SRC),)
# Create directories for object files if they do not exist
obj-dirs := $(sort $(obj) $(patsubst %/,%, $(dir $(targets))))
# If cmd_files exist, their directories apparently exist. Skip mkdir.
exist-dirs := $(sort $(patsubst %/,%, $(dir $(cmd_files))))
obj-dirs := $(strip $(filter-out $(exist-dirs), $(obj-dirs)))
# If targets exist, their directories apparently exist. Skip mkdir.
existing-dirs := $(sort $(patsubst %/,%, $(dir $(existing-targets))))
obj-dirs := $(strip $(filter-out $(existing-dirs), $(obj-dirs)))
ifneq ($(obj-dirs),)
$(shell mkdir -p $(obj-dirs))
endif
Expand Down

0 comments on commit 392885e

Please sign in to comment.