Makefiles: add and use wildcard "mkdir -p" template
Add a template to do the "mkdir -p" of $(@D) (the parent dir of $@) for us, and use it for the "make lint-docs" targets I added in8650c6298c
(doc lint: make "lint-docs" non-.PHONY, 2021-10-15). As seen in4c64fb5aad
(Documentation/Makefile: fix lint-docs mkdir dependency, 2021-10-26) maintaining these manual lists of parent directory dependencies is fragile, in addition to being obviously verbose. I used this pattern at the time because I couldn't find another method than "order-only" prerequisites to avoid doing a "mkdir -p $(@D)" for every file being created, which as noted in [1] would be significantly slower. But as it turns out we can use this neat trick of only doing a "mkdir -p" if the $(wildcard) macro tells us the path doesn't exist. A re-run of a performance test similar to that noted downthread of [1] in [2] shows that this is faster, in addition to being less verbose and more reliable (this uses my "git-hyperfine" thin wrapper for "hyperfine"[3]): $ git -c hyperfine.hook.setup= hyperfine -L rev HEAD~1,HEAD~0 -s 'make -C Documentation lint-docs' -p 'rm -rf Documentation/.build' 'make -C Documentation -j1 lint-docs' Benchmark 1: make -C Documentation -j1 lint-docs' in 'HEAD~1 Time (mean ± σ): 2.914 s ± 0.062 s [User: 2.449 s, System: 0.489 s] Range (min … max): 2.834 s … 3.020 s 10 runs Benchmark 2: make -C Documentation -j1 lint-docs' in 'HEAD~0 Time (mean ± σ): 2.315 s ± 0.062 s [User: 1.950 s, System: 0.386 s] Range (min … max): 2.229 s … 2.397 s 10 runs Summary 'make -C Documentation -j1 lint-docs' in 'HEAD~0' ran 1.26 ± 0.04 times faster than 'make -C Documentation -j1 lint-docs' in 'HEAD~1' So let's use that pattern both for the "lint-docs" target, and a few miscellaneous other targets. This method of creating parent directories is explicitly racy in that we don't know if we're going to say always create a "foo" followed by a "foo/bar" under parallelism, or skip the "foo" because we created "foo/bar" first. In this case it doesn't matter for anything except that we aren't guaranteed to get the same number of rules firing when running make in parallel. 1. https://lore.kernel.org/git/211028.861r45y3pt.gmgdl@evledraar.gmail.com/ 2. https://lore.kernel.org/git/211028.86o879vvtp.gmgdl@evledraar.gmail.com/ 3. https://gitlab.com/avar/git-hyperfine/ Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
a9fda017f4
commit
0b6d0bc924
@ -434,25 +434,11 @@ quick-install-html: require-htmlrepo
|
|||||||
print-man1:
|
print-man1:
|
||||||
@for i in $(MAN1_TXT); do echo $$i; done
|
@for i in $(MAN1_TXT); do echo $$i; done
|
||||||
|
|
||||||
## Lint: Common
|
|
||||||
.build:
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
.build/lint-docs: | .build
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
|
|
||||||
## Lint: gitlink
|
## Lint: gitlink
|
||||||
.build/lint-docs/gitlink: | .build/lint-docs
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
.build/lint-docs/gitlink/howto: | .build/lint-docs/gitlink
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
.build/lint-docs/gitlink/config: | .build/lint-docs/gitlink
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
LINT_DOCS_GITLINK = $(patsubst %.txt,.build/lint-docs/gitlink/%.ok,$(HOWTO_TXT) $(DOC_DEP_TXT))
|
LINT_DOCS_GITLINK = $(patsubst %.txt,.build/lint-docs/gitlink/%.ok,$(HOWTO_TXT) $(DOC_DEP_TXT))
|
||||||
$(LINT_DOCS_GITLINK): | .build/lint-docs/gitlink
|
|
||||||
$(LINT_DOCS_GITLINK): | .build/lint-docs/gitlink/howto
|
|
||||||
$(LINT_DOCS_GITLINK): | .build/lint-docs/gitlink/config
|
|
||||||
$(LINT_DOCS_GITLINK): lint-gitlink.perl
|
$(LINT_DOCS_GITLINK): lint-gitlink.perl
|
||||||
$(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.txt
|
$(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.txt
|
||||||
|
$(call mkdir_p_parent_template)
|
||||||
$(QUIET_LINT_GITLINK)$(PERL_PATH) lint-gitlink.perl \
|
$(QUIET_LINT_GITLINK)$(PERL_PATH) lint-gitlink.perl \
|
||||||
$< \
|
$< \
|
||||||
$(HOWTO_TXT) $(DOC_DEP_TXT) \
|
$(HOWTO_TXT) $(DOC_DEP_TXT) \
|
||||||
@ -463,23 +449,18 @@ $(LINT_DOCS_GITLINK): .build/lint-docs/gitlink/%.ok: %.txt
|
|||||||
lint-docs-gitlink: $(LINT_DOCS_GITLINK)
|
lint-docs-gitlink: $(LINT_DOCS_GITLINK)
|
||||||
|
|
||||||
## Lint: man-end-blurb
|
## Lint: man-end-blurb
|
||||||
.build/lint-docs/man-end-blurb: | .build/lint-docs
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
LINT_DOCS_MAN_END_BLURB = $(patsubst %.txt,.build/lint-docs/man-end-blurb/%.ok,$(MAN_TXT))
|
LINT_DOCS_MAN_END_BLURB = $(patsubst %.txt,.build/lint-docs/man-end-blurb/%.ok,$(MAN_TXT))
|
||||||
$(LINT_DOCS_MAN_END_BLURB): | .build/lint-docs/man-end-blurb
|
|
||||||
$(LINT_DOCS_MAN_END_BLURB): lint-man-end-blurb.perl
|
$(LINT_DOCS_MAN_END_BLURB): lint-man-end-blurb.perl
|
||||||
$(LINT_DOCS_MAN_END_BLURB): .build/lint-docs/man-end-blurb/%.ok: %.txt
|
$(LINT_DOCS_MAN_END_BLURB): .build/lint-docs/man-end-blurb/%.ok: %.txt
|
||||||
|
$(call mkdir_p_parent_template)
|
||||||
$(QUIET_LINT_MANEND)$(PERL_PATH) lint-man-end-blurb.perl $< >$@
|
$(QUIET_LINT_MANEND)$(PERL_PATH) lint-man-end-blurb.perl $< >$@
|
||||||
.PHONY: lint-docs-man-end-blurb
|
.PHONY: lint-docs-man-end-blurb
|
||||||
lint-docs-man-end-blurb: $(LINT_DOCS_MAN_END_BLURB)
|
|
||||||
|
|
||||||
## Lint: man-section-order
|
## Lint: man-section-order
|
||||||
.build/lint-docs/man-section-order: | .build/lint-docs
|
|
||||||
$(QUIET)mkdir $@
|
|
||||||
LINT_DOCS_MAN_SECTION_ORDER = $(patsubst %.txt,.build/lint-docs/man-section-order/%.ok,$(MAN_TXT))
|
LINT_DOCS_MAN_SECTION_ORDER = $(patsubst %.txt,.build/lint-docs/man-section-order/%.ok,$(MAN_TXT))
|
||||||
$(LINT_DOCS_MAN_SECTION_ORDER): | .build/lint-docs/man-section-order
|
|
||||||
$(LINT_DOCS_MAN_SECTION_ORDER): lint-man-section-order.perl
|
$(LINT_DOCS_MAN_SECTION_ORDER): lint-man-section-order.perl
|
||||||
$(LINT_DOCS_MAN_SECTION_ORDER): .build/lint-docs/man-section-order/%.ok: %.txt
|
$(LINT_DOCS_MAN_SECTION_ORDER): .build/lint-docs/man-section-order/%.ok: %.txt
|
||||||
|
$(call mkdir_p_parent_template)
|
||||||
$(QUIET_LINT_MANSEC)$(PERL_PATH) lint-man-section-order.perl $< >$@
|
$(QUIET_LINT_MANSEC)$(PERL_PATH) lint-man-section-order.perl $< >$@
|
||||||
.PHONY: lint-docs-man-section-order
|
.PHONY: lint-docs-man-section-order
|
||||||
lint-docs-man-section-order: $(LINT_DOCS_MAN_SECTION_ORDER)
|
lint-docs-man-section-order: $(LINT_DOCS_MAN_SECTION_ORDER)
|
||||||
|
12
Makefile
12
Makefile
@ -2745,7 +2745,8 @@ all:: $(MOFILES)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
|
po/build/locale/%/LC_MESSAGES/git.mo: po/%.po
|
||||||
$(QUIET_MSGFMT)mkdir -p $(dir $@) && $(MSGFMT) -o $@ $<
|
$(call mkdir_p_parent_template)
|
||||||
|
$(QUIET_MSGFMT)$(MSGFMT) -o $@ $<
|
||||||
|
|
||||||
LIB_PERL := $(wildcard perl/Git.pm perl/Git/*.pm perl/Git/*/*.pm perl/Git/*/*/*.pm)
|
LIB_PERL := $(wildcard perl/Git.pm perl/Git/*.pm perl/Git/*/*.pm perl/Git/*/*/*.pm)
|
||||||
LIB_PERL_GEN := $(patsubst perl/%.pm,perl/build/lib/%.pm,$(LIB_PERL))
|
LIB_PERL_GEN := $(patsubst perl/%.pm,perl/build/lib/%.pm,$(LIB_PERL))
|
||||||
@ -2761,15 +2762,16 @@ NO_PERL_CPAN_FALLBACKS_SQ = $(subst ','\'',$(NO_PERL_CPAN_FALLBACKS))
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
perl/build/lib/%.pm: perl/%.pm GIT-PERL-DEFINES
|
perl/build/lib/%.pm: perl/%.pm GIT-PERL-DEFINES
|
||||||
$(QUIET_GEN)mkdir -p $(dir $@) && \
|
$(call mkdir_p_parent_template)
|
||||||
|
$(QUIET_GEN) \
|
||||||
sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
|
sed -e 's|@@LOCALEDIR@@|$(perl_localedir_SQ)|g' \
|
||||||
-e 's|@@NO_GETTEXT@@|$(NO_GETTEXT_SQ)|g' \
|
-e 's|@@NO_GETTEXT@@|$(NO_GETTEXT_SQ)|g' \
|
||||||
-e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
|
-e 's|@@NO_PERL_CPAN_FALLBACKS@@|$(NO_PERL_CPAN_FALLBACKS_SQ)|g' \
|
||||||
< $< > $@
|
< $< > $@
|
||||||
|
|
||||||
perl/build/man/man3/Git.3pm: perl/Git.pm
|
perl/build/man/man3/Git.3pm: perl/Git.pm
|
||||||
$(QUIET_GEN)mkdir -p $(dir $@) && \
|
$(call mkdir_p_parent_template)
|
||||||
pod2man $< $@
|
$(QUIET_GEN)pod2man $< $@
|
||||||
|
|
||||||
$(ETAGS_TARGET): $(FOUND_SOURCE_FILES)
|
$(ETAGS_TARGET): $(FOUND_SOURCE_FILES)
|
||||||
$(QUIET_GEN)$(RM) $@+ && \
|
$(QUIET_GEN)$(RM) $@+ && \
|
||||||
@ -2903,7 +2905,7 @@ test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(
|
|||||||
all:: $(TEST_PROGRAMS) $(test_bindir_programs)
|
all:: $(TEST_PROGRAMS) $(test_bindir_programs)
|
||||||
|
|
||||||
bin-wrappers/%: wrap-for-bin.sh
|
bin-wrappers/%: wrap-for-bin.sh
|
||||||
@mkdir -p bin-wrappers
|
$(call mkdir_p_parent_template)
|
||||||
$(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
$(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
|
||||||
-e 's|@@BUILD_DIR@@|$(shell pwd)|' \
|
-e 's|@@BUILD_DIR@@|$(shell pwd)|' \
|
||||||
-e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%$(X),$(@F))$(patsubst git%,$(X),$(filter $(@F),$(BINDIR_PROGRAMS_NEED_X)))|' < $< > $@ && \
|
-e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%$(X),$(@F))$(patsubst git%,$(X),$(filter $(@F),$(BINDIR_PROGRAMS_NEED_X)))|' < $< > $@ && \
|
||||||
|
17
shared.mak
17
shared.mak
@ -53,6 +53,8 @@ ifndef V
|
|||||||
QUIET = @
|
QUIET = @
|
||||||
QUIET_GEN = @echo ' ' GEN $@;
|
QUIET_GEN = @echo ' ' GEN $@;
|
||||||
|
|
||||||
|
QUIET_MKDIR_P_PARENT = @echo $(wspfx_SQ) MKDIR -p $(@D);
|
||||||
|
|
||||||
## Used in "Makefile"
|
## Used in "Makefile"
|
||||||
QUIET_CC = @echo ' ' CC $@;
|
QUIET_CC = @echo ' ' CC $@;
|
||||||
QUIET_AR = @echo ' ' AR $@;
|
QUIET_AR = @echo ' ' AR $@;
|
||||||
@ -84,3 +86,18 @@ ifndef V
|
|||||||
export V
|
export V
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
### Templates
|
||||||
|
|
||||||
|
## mkdir_p_parent: lazily "mkdir -p" the path needed for a $@
|
||||||
|
## file. Uses $(wildcard) to avoid the "mkdir -p" if it's not
|
||||||
|
## needed.
|
||||||
|
##
|
||||||
|
## Is racy, but in a good way; we might redundantly (and safely)
|
||||||
|
## "mkdir -p" when running in parallel, but won't need to exhaustively create
|
||||||
|
## individual rules for "a" -> "prefix" -> "dir" -> "file" if given a
|
||||||
|
## "a/prefix/dir/file". This can instead be inserted at the start of
|
||||||
|
## the "a/prefix/dir/file" rule.
|
||||||
|
define mkdir_p_parent_template
|
||||||
|
$(if $(wildcard $(@D)),,$(QUIET_MKDIR_P_PARENT)$(shell mkdir -p $(@D)))
|
||||||
|
endef
|
||||||
|
Loading…
Reference in New Issue
Block a user