diff -u b/lisp/update-elc-2.el b/lisp/update-elc-2.el
--- b/lisp/update-elc-2.el	Mon Jun 27 22:14:53 2022 +0900
+++ b/lisp/update-elc-2.el	Thu Jun 30 16:36:19 2022 +0100
@@ -144,12 +144,12 @@
     (load (expand-file-name "auto-autoloads" lisp-directory))
     (when (featurep 'mule)
       (load (expand-file-name "mule/auto-autoloads" lisp-directory)))
+    (when (featurep 'modules)
+      (load (expand-file-name "auto-autoloads" module-directory)))
     ;; We remove all the bad .elcs before any byte-compilation, because
     ;; there may be dependencies between one .el and another (even across
     ;; directories), and we don't want to load an out-of-date .elc while
     ;; byte-compiling a file.
-    (when (featurep 'modules)
-      (load (expand-file-name "auto-autoloads" module-directory)))
     (message "Removing old or spurious .elcs in directory tree `%s'..." dir)
     (do-update-elc-2 dir nil nil)
     (message "Removing old or spurious .elcs in directory tree `%s'...done"
unchanged:
--- a/src/Makefile.in.in	Mon Jun 27 13:31:39 2022 +0100
+++ b/src/Makefile.in.in	Mon Jun 27 22:14:53 2022 +0900
@@ -95,7 +95,12 @@
 SHELL=/bin/sh
 RM = rm -f
 
-LISP = $(SRC)/../lisp
+## Earlier versions had $(SRC)/../lisp here, but currently ../lisp is a
+## link to $(SRC)/../lisp in out-of-source builds.  $(SRC)/../lisp breaks
+## the modules build because the autoloads end up in $(SRCMODULES), but
+## update-elc-2.el looks for them in $(BLDMODULES).
+LISP = ../lisp
+
 ETC = $(SRC)/../etc
 SRCMODULES = $(SRC)/../modules
 LIB_SRC = ../lib-src
@@ -944,10 +949,14 @@
 	-$(RM) $(RAW_EXE) $(DUMP_TARGET) $(DUMP_TARGET).dmp $(LIB_SRC)/DOC
 ##      Remove the generated load files here; they cause lots of problems
 ##      when they don't work right.
+##      Some older versions tried to put module load files in the SRC tree,
+##      but that breaks module builds, which expect them in the BLD tree,
+##      and that's where they belong anyway.  Clean both.
 clean: mostlyclean versionclean
 	-$(RM) libextcli* $(LISP)/auto-autoloads.el* $(LISP)/custom-load.el* \
 	$(LISP)/mule/auto-autoloads.el* $(LISP)/mule/custom-load.el* \
-	$(SRCMODULES)/auto-autoloads.el* $(SRCMODULES)/custom-load.el*
+	$(SRCMODULES)/auto-autoloads.el* $(SRCMODULES)/custom-load.el* \
+	$(BLDMODULES)/auto-autoloads.el* $(BLDMODULES)/custom-load.el*
 ## This is used in making a distribution.
 ## Do not use it on development directories!
 distclean-noconfig: clean
only in patch2:
unchanged:
--- a/lisp/update-elc.el
+++ b/lisp/update-elc.el
@@ -87,8 +87,8 @@
 
 (defvar source-lisp-mule (expand-file-name "mule" source-lisp))
 (defvar source-directory (expand-file-name ".." source-lisp))
-(defconst module-directory (expand-file-name "modules" source-directory))
-
+(defvar source-modules (expand-file-name "../modules" (file-truename source-lisp)))
+(defconst module-directory (expand-file-name "modules" build-directory))
 (defvar aa-lisp (expand-file-name "auto-autoloads.el" source-lisp))
 (defvar aac-lisp (expand-file-name "auto-autoloads.elc" source-lisp))
 (defvar aa-lisp-mule (expand-file-name "auto-autoloads.el" source-lisp-mule))
@@ -280,15 +280,13 @@ If any of these files are changed, we need to redump.")
 
   ;; Check for the module autoloads separately, given the need to run
   ;; directory-files on subdirectories.
-  (let ((autoload-file
-        (expand-file-name "auto-autoloads.el" module-directory)))
-    (mapc
-     #'(lambda (full-dir)
-        (mapc #'(lambda (full-arg)
-                  (when (file-newer-than-file-p full-arg autoload-file)
-                    (setq need-to-rebuild-module-autoloads t)))
-              (directory-files full-dir t "\\.c$" nil t)))
-     (directory-files module-directory t nil t 'subdirs)))
+  (mapc
+   #'(lambda (full-dir)
+       (mapc #'(lambda (full-arg)
+		 (when (file-newer-than-file-p full-arg aa-modules)
+		   (setq need-to-rebuild-module-autoloads t)))
+	     (directory-files full-dir t "\\.c$" nil t)))
+   (directory-files source-modules t nil t 'subdirs))
 
   (if dump-target-out-of-date-wrt-dump-files
       (condition-case nil
@@ -346,9 +344,22 @@ If any of these files are changed, we need to redump.")
 	(if need-to-rebuild-mule-autoloads
 	    (list "-f" "batch-update-directory-autoloads"
 		  "mule" source-lisp-mule))
-        (if need-to-rebuild-module-autoloads
-            (list "-f" "batch-update-directory-autoloads"
-                  "auto" module-directory))
+	(if need-to-rebuild-module-autoloads
+	    (list "-eval"
+		  (concat
+		   "(update-autoload-files '("
+		   (mapconcat #'prin1-to-string
+			      (mapcan
+			       #'(lambda (full-dir)
+				   (unless (member*
+					    (file-name-nondirectory full-dir)
+					    '("." "..") :test #'equal)
+				     (directory-files full-dir
+						      t "\\.c$" nil t)))
+			       (directory-files source-modules
+						t nil t 'subdirs))
+			      " ")
+		   ") \"modules\" " (prin1-to-string aa-modules) ")")))
 	(if need-to-recompile-autoloads
 	    (list "-f" "batch-byte-compile-one-file"
 		  aa-lisp))
