Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCHv2: Allow parallel make
- X-seq: zsh-workers 55157
- From: Mikael Magnusson <mikachu@xxxxxxxxx>
- To: zsh-workers@xxxxxxx
- Cc: Oliver Kiddle <opk@xxxxxxx>
- Subject: PATCHv2: Allow parallel make
- Date: Thu, 17 Sep 2026 05:51:48 +0200
- Archived-at: <https://zsh.org/workers/55157>
- In-reply-to: <13984-1789506903.632902@cuVR.tBQQ.Mc7z>
- List-id: <zsh-workers.zsh.org>
- References: <13984-1789506903.632902@cuVR.tBQQ.Mc7z>
---
On Tue, Sep 15, 2026 at 11:15 PM Oliver Kiddle <opk@xxxxxxx> wrote:
>
> On 8 Sep, Mikael Magnusson wrote:
> > I won't commit this unless a lot of people says it works on various make
> > implementations (I only have GNU Make), and please try it at different
> > job counts. The newuser.c failure only happened to me with make -j3, not
> > make -j10 for example. The others didn't happen and are purely by
> > inspection.
>
> In my testing, this is working for FreeBSD make, openBSD make and
> Solaris' dmake.
>
> However, there may be some extra rules still missing. On a fast system
> with -j32, I get errors from one or .epro file that the opening #ifndef
> is not terminated. Is probably using it before it has been created.
> Tends to be an epro file from down in Src/Zle included from ksh93.mdh.
This should hopefully address that. (The src/Makefile.in.in hunk and the
second hunk in Src/mkmakemod.sh, specifically). Separately, I noticed
that if you compile more than one module statically (including zsh/main
in this count), the stamp-modobjs generation was fairly problematic, so
those now generate a separate file per mdd and then glorp them all
together at the end.
I also noticed a problem with the previous terminfo.mdd and curses.mdd
fix, in that rerunning make would always regenerate the header files, so
stop doing that by adding an intermediate rule, so the actual file
doesn't depend on a PHONY rule. (Make certainly is a very strange
language).
Also obviously folded in the texi thing from before.
I think that's all the changes.
> This does allow builds to be much faster so it would be great to have
> this committed.
👍
Config/defs.mk.in | 6 ----
Doc/Makefile.in | 5 +--
Src/Makefile.in | 11 ++++--
Src/Makemod.in.in | 9 +++--
Src/Modules/curses.mdd | 9 ++++-
Src/Modules/newuser.mdd | 5 ++-
Src/Modules/terminfo.mdd | 12 +++++++
Src/mkmakemod.sh | 17 ++++-----
Src/zsh.mdd | 75 +++++++++++++++++++++-------------------
9 files changed, 89 insertions(+), 60 deletions(-)
diff --git a/Config/defs.mk.in b/Config/defs.mk.in
index 116875fb9c..00119eac97 100644
--- a/Config/defs.mk.in
+++ b/Config/defs.mk.in
@@ -105,9 +105,3 @@ FUNCTIONS_INSTALL='$(FUNCTIONS_INSTALL)' tzsh='$(tzsh)'
# override built-in suffix list
.SUFFIXES:
-
-# parallel build is not supported (pmake, gmake)
-.NOTPARALLEL:
-
-# parallel build is not supported (dmake)
-.NO_PARALLEL:
diff --git a/Doc/Makefile.in b/Doc/Makefile.in
index 3b68ed61a1..0731e278b7 100644
--- a/Doc/Makefile.in
+++ b/Doc/Makefile.in
@@ -39,9 +39,9 @@ LN_S = @LN_S@
@DEFS_MK@
MAKEINFO = makeinfo
-TEXI2DVI = @TEXI2DVI@
+TEXI2DVI = @TEXI2DVI@ --tidy
DVIPS = dvips
-TEXI2PDF = @TEXI2PDF@
+TEXI2PDF = @TEXI2PDF@ --tidy
TEXI2HTML = @TEXI2HTML@
SET_TEXI2ANY_VAR = @SET_TEXI2ANY_VAR@
PAPERSIZE = @PAPERSIZE@
@@ -416,6 +416,7 @@ clean-here:
rm -f *.html *.info* *.dvi *.ps *.pdf
rm -f *.aux *.cp *.cps *.fn *.fns *.ky *.kys *.log *.idx
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs
+ rm -rf *.t2d
rm -rf infodir
rm -f texi2html.conf
.PHONY: clean-here
diff --git a/Src/Makefile.in b/Src/Makefile.in
index 0fdbb73d2d..7fc0b364d4 100644
--- a/Src/Makefile.in
+++ b/Src/Makefile.in
@@ -92,6 +92,9 @@ zsh.res.o: $(sdir)/zsh.rc $(sdir)/zsh.ico
windres -O coff --include-dir $(sdir) -i $(sdir)/zsh.rc -o zsh.res.o
stamp-modobjs: modobjs
+ @cat stamp-modobjs.tmp-* > stamp-modobjs.tmp.$$$$; \
+ rm -f stamp-modobjs.tmp-*; \
+ mv -f stamp-modobjs.tmp.$$$$ stamp-modobjs.tmp
@if cmp -s stamp-modobjs.tmp stamp-modobjs; then \
rm -f stamp-modobjs.tmp; \
else \
@@ -103,7 +106,7 @@ modobjs: headers rm-modobjs-tmp
.PHONY: modobjs
rm-modobjs-tmp:
- rm -f stamp-modobjs.tmp
+ rm -f stamp-modobjs.tmp stamp-modobjs.tmp-*
.PHONY: rm-modobjs-tmp
@CONFIG_MK@
@@ -185,8 +188,8 @@ uninstall.cygwin-lib:
# forces module stuff to get cleaned before Makemod itself gets
# deleted.
-mostlyclean-here:
- rm -f stamp-modobjs stamp-modobjs.tmp
+mostlyclean-here: rm-modobjs-tmp
+ rm -f stamp-modobjs
.PHONY: mostlyclean-here
clean-here:
@@ -218,6 +221,8 @@ mostlyclean-modules clean-modules distclean-modules realclean-modules:
# ========== RECURSIVE MAKES ==========
+install.modules uninstall.modules \
+modobjs modules proto $(MAIN_OBJS) zsh.export: headers
install.modules uninstall.modules \
modobjs modules headers proto $(MAIN_OBJS) zsh.export: Makemod
@$(MAKE) -f Makemod $(MAKEDEFS) $@
diff --git a/Src/Makemod.in.in b/Src/Makemod.in.in
index 3343ae1d06..2aa47c1a0d 100644
--- a/Src/Makemod.in.in
+++ b/Src/Makemod.in.in
@@ -64,13 +64,16 @@ OBJ=.o
$(DLCOMPILE) -o $@ $<
.c.syms:
- $(AWK) -f $(sdir_src)/makepro.awk $< $(subdir) > $@
+ $(AWK) -f $(sdir_src)/makepro.awk $< $(subdir) > $@.$$$$.tmp; \
+ mv $@.$$$$.tmp $@
.syms.epro:
(echo '/* Generated automatically */'; sed -n '/^E/{s/^E//;p;}' < $<) \
- > $@
+ > $@.$$$$.tmp; \
(echo '/* Generated automatically */'; sed -n '/^L/{s/^L//;p;}' < $<) \
- > `echo $@ | sed 's/\.epro$$/.pro/'`
+ > `echo $@ | sed 's/\.epro$$/.pro.'$$$$.tmp/`; \
+ mv $@.$$$$.tmp $@; \
+ mv `echo $@ | sed 's/\.epro$$/.pro.'$$$$.tmp/` `echo $@ | sed 's/\.epro$$/.pro'/`
PROTODEPS = $(sdir_src)/makepro.awk
diff --git a/Src/Modules/curses.mdd b/Src/Modules/curses.mdd
index 75da29a6d2..f7fb7b585b 100644
--- a/Src/Modules/curses.mdd
+++ b/Src/Modules/curses.mdd
@@ -7,11 +7,18 @@ autofeatures="b:zcurses"
objects="curses.o"
:<<\Make
-curses.o curses..o: curses_keys.h
+curses.o curses..o: curses_keys.h ../zshcurses.h
curses_keys.h: curses_keys.awk @CURSES_KEYS_H@
$(AWK) -f $(sdir)/curses_keys.awk @CURSES_KEYS_H@ /dev/null >curses_keys.h
+../zshcurses.h: CURSES_HEADER_RULE
+
+CURSES_HEADER_RULE: FORCE
+ @cd .. && $(MAKE) $(MAKEDEFS) -f Makemod zshcurses.h
+
+.PHONY: CURSES_HEADER_RULE
+
clean-here: clean.curses
clean.curses:
rm -f curses_keys.h
diff --git a/Src/Modules/newuser.mdd b/Src/Modules/newuser.mdd
index 82a08a52e3..923602041c 100644
--- a/Src/Modules/newuser.mdd
+++ b/Src/Modules/newuser.mdd
@@ -8,6 +8,9 @@ functions='Scripts/newuser Functions/Newuser/*'
objects="newuser.o"
:<<\Make
-newuser.o: ../zshpaths.h
+newuser.o newuser..o: ../zshpaths.h
+
+../zshpaths.h: FORCE
+ @cd .. && $(MAKE) $(MAKEDEFS) -f Makemod zshpaths.h
Make
diff --git a/Src/Modules/terminfo.mdd b/Src/Modules/terminfo.mdd
index a9a3f1b49b..91a6be0466 100644
--- a/Src/Modules/terminfo.mdd
+++ b/Src/Modules/terminfo.mdd
@@ -15,3 +15,15 @@ load=yes
autofeatures="b:echoti p:terminfo"
objects="terminfo.o"
+
+:<<\Make
+terminfo.o terminfo..o: ../zshcurses.h ../zshterm.h
+
+../zshcurses.h ../zshterm.h: TERMCAP_HEADER_RULE
+
+TERMCAP_HEADER_RULE: FORCE
+ @cd .. && $(MAKE) $(MAKEDEFS) -f Makemod zshcurses.h zshterm.h
+
+.PHONY: TERMCAP_HEADER_RULE
+
+Make
diff --git a/Src/mkmakemod.sh b/Src/mkmakemod.sh
index 5e5adc070e..1692b58ee7 100644
--- a/Src/mkmakemod.sh
+++ b/Src/mkmakemod.sh
@@ -190,6 +190,7 @@ if $first_stage; then
unset objects proto headers hdrdeps otherincs libs
. $top_srcdir/$the_subdir/${mddname}.mdd
q_name=`echo $name | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
+ q_mddname=`echo $the_subdir/$mddname | sed 's,Q,Qq,g;s,_,Qu,g;s,/,Qs,g'`
test -n "${moddeps+set}" || moddeps=
test -n "$nozshdep" || moddeps="$moddeps zsh/main"
test -n "${proto+set}" ||
@@ -307,7 +308,7 @@ if $first_stage; then
echo " @( echo '#!'; cat \$(SYMS_${mddname}) | sed -n '/^X/{s/^X//;p;}' | sort -u ) > \$@"
echo
echo "modobjs.${mddname}: \$(MODOBJS_${mddname})"
- echo " @echo '' \$(MODOBJS_${mddname}) $modobjs_sed>> \$(dir_src)/stamp-modobjs.tmp"
+ echo " @echo '' \$(MODOBJS_${mddname}) $modobjs_sed> \$(dir_src)/stamp-modobjs.tmp-${q_mddname}"
echo
if test -z "$alwayslink"; then
case " $all_modules" in *" ${mddname}."*)
@@ -332,22 +333,22 @@ if $first_stage; then
echo " @test -f \$@ || echo 'do not delete this file' > \$@"
echo
echo "${mddname}.mdhs: ${mddname}.mdd"
- echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
- echo " @if cmp -s ${mddname}.mdh ${mddname}.mdh.tmp; then \\"
- echo " rm -f ${mddname}.mdh.tmp; \\"
+ echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) MDHPID=\$\$\$\$ ${mddname}.mdh.tmp.\$\$\$\$; \\"
+ echo " if cmp -s ${mddname}.mdh ${mddname}.mdh.tmp.\$\$\$\$; then \\"
+ echo " rm -f ${mddname}.mdh.tmp.\$\$\$\$; \\"
echo " echo \"\\\`${mddname}.mdh' is up to date.\"; \\"
echo " else \\"
- echo " mv -f ${mddname}.mdh.tmp ${mddname}.mdh; \\"
+ echo " mv -f ${mddname}.mdh.tmp.\$\$\$\$ ${mddname}.mdh; \\"
echo " echo \"Updated \\\`${mddname}.mdh'.\"; \\"
echo " fi"
echo " echo 'timestamp for ${mddname}.mdh against ${mddname}.mdd' > \$@"
echo
echo "${mddname}.mdh: ${modhdeps} ${headers} ${hdrdeps} ${mddname}.mdhi"
- echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) ${mddname}.mdh.tmp"
- echo " @mv -f ${mddname}.mdh.tmp ${mddname}.mdh"
+ echo " @\$(MAKE) -f \$(makefile) \$(MAKEDEFS) MDHPID=\$\$\$\$ ${mddname}.mdh.tmp.\$\$\$\$; \\"
+ echo " mv -f ${mddname}.mdh.tmp.\$\$\$\$ ${mddname}.mdh"
echo " @echo \"Updated \\\`${mddname}.mdh'.\""
echo
- echo "${mddname}.mdh.tmp:"
+ echo "${mddname}.mdh.tmp.\$(MDHPID):"
echo " @( \\"
echo " echo '#ifndef have_${q_name}_module'; \\"
echo " echo '#define have_${q_name}_module'; \\"
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index 9a5e9daab1..8480538501 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -61,56 +61,59 @@ FORCE:
zshcurses.h: ../config.h
@if test x$(ZSH_CURSES_H) != x; then \
- echo "#include <$(ZSH_CURSES_H)>" >zshcurses.h; \
+ echo "#include <$(ZSH_CURSES_H)>" >zshcurses.h.tmp.$$$$; \
+ mv zshcurses.h.tmp.$$$$ zshcurses.h; \
else \
echo >zshcurses.h; \
fi
zshterm.h: ../config.h
@if test x$(ZSH_TERM_H) != x; then \
- echo "#include <$(ZSH_TERM_H)>" >zshterm.h; \
+ echo "#include <$(ZSH_TERM_H)>" >zshterm.h.tmp.$$$$; \
+ mv zshterm.h.tmp.$$$$ zshterm.h; \
else \
echo >zshterm.h; \
fi
zshpaths.h: Makemod $(CONFIG_INCS)
- @echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
- @if test x$(sitescriptdir) != xno; then \
- echo '#define SITESCRIPT_DIR "'$(sitescriptdir)'"' >> zshpaths.h.tmp; \
- fi
- @if test x$(scriptdir) != xno; then \
- echo '#define SCRIPT_DIR "'$(scriptdir)'"' >> zshpaths.h.tmp; \
- fi
- @if test x$(sitefndir) != xno; then \
- echo '#define SITEFPATH_DIR "'$(sitefndir)'"' >> zshpaths.h.tmp; \
- fi
- @if test x$(fixed_sitefndir) != x; then \
- echo '#define FIXED_FPATH_DIR "'$(fixed_sitefndir)'"' >> zshpaths.h.tmp; \
- fi
- @if test x$(fndir) != xno; then \
- echo '#define FPATH_DIR "'$(fndir)'"' >> zshpaths.h.tmp; \
- if test x$(FUNCTIONS_SUBDIRS) != x && \
- test x$(FUNCTIONS_SUBDIRS) != xno; then \
- fpath_tmp="`grep ' functions=.' \
- $(dir_top)/config.modules | sed -e '/^#/d' -e '/ link=no/d' \
- -e 's/^.* functions=//'`"; \
- fpath_tmp=`for f in $$fpath_tmp; do \
- echo $$f | sed -e 's%^Functions/%%' -e 's%/[^/]*$$%%' -e 's%/\*%%'; \
- done | grep -v Scripts | sort | uniq`; \
- fpath_tmp=`echo $$fpath_tmp | sed 's/ /\", \"/g'`; \
- echo "#define FPATH_SUBDIRS { \"$$fpath_tmp\" }" \
- >>zshpaths.h.tmp; \
+ @{ \
+ echo '#define MODULE_DIR "'$(MODDIR)'"'; \
+ if test x$(sitescriptdir) != xno; then \
+ echo '#define SITESCRIPT_DIR "'$(sitescriptdir)'"'; \
fi; \
- fi
- @if test x$(additionalfpath) != x; then \
- fpath_tmp="`echo $(additionalfpath) | sed -e 's:,:\", \":g'`"; \
- echo "#define ADDITIONAL_FPATH { \"$$fpath_tmp\" }" >> zshpaths.h.tmp; \
- fi
- @if cmp -s zshpaths.h zshpaths.h.tmp; then \
- rm -f zshpaths.h.tmp; \
+ if test x$(scriptdir) != xno; then \
+ echo '#define SCRIPT_DIR "'$(scriptdir)'"'; \
+ fi; \
+ if test x$(sitefndir) != xno; then \
+ echo '#define SITEFPATH_DIR "'$(sitefndir)'"'; \
+ fi; \
+ if test x$(fixed_sitefndir) != x; then \
+ echo '#define FIXED_FPATH_DIR "'$(fixed_sitefndir)'"'; \
+ fi; \
+ if test x$(fndir) != xno; then \
+ echo '#define FPATH_DIR "'$(fndir)'"'; \
+ if test x$(FUNCTIONS_SUBDIRS) != x && \
+ test x$(FUNCTIONS_SUBDIRS) != xno; then \
+ fpath_tmp="`grep ' functions=.' \
+ $(dir_top)/config.modules | sed -e '/^#/d' -e '/ link=no/d' \
+ -e 's/^.* functions=//'`"; \
+ fpath_tmp=`for f in $$fpath_tmp; do \
+ echo $$f | sed -e 's%^Functions/%%' -e 's%/[^/]*$$%%' -e 's%/\*%%'; \
+ done | grep -v Scripts | sort | uniq`; \
+ fpath_tmp=`echo $$fpath_tmp | sed 's/ /\", \"/g'`; \
+ echo "#define FPATH_SUBDIRS { \"$$fpath_tmp\" }"; \
+ fi; \
+ fi; \
+ if test x$(additionalfpath) != x; then \
+ fpath_tmp="`echo $(additionalfpath) | sed -e 's:,:\", \":g'`"; \
+ echo "#define ADDITIONAL_FPATH { \"$$fpath_tmp\" }"; \
+ fi; \
+ } > zshpaths.h.tmp.$$$$; \
+ if cmp -s zshpaths.h zshpaths.h.tmp.$$$$; then \
+ rm -f zshpaths.h.tmp.$$$$; \
echo "\`zshpaths.h' is up to date." ; \
else \
- mv -f zshpaths.h.tmp zshpaths.h; \
+ mv -f zshpaths.h.tmp.$$$$ zshpaths.h; \
echo "Updated \`zshpaths.h'." ; \
fi
--
2.38.1
Messages sorted by:
Reverse Date,
Date,
Thread,
Author