diff lisp/update-elc-2.el @ 1298:1b4bc72f433e

[xemacs-hg @ 2003-02-14 12:05:06 by ben] speedups to build process autoload.el: Factor out common code in generate-{c-,}file-autoloads-1 into new function generate-autoload-ish-1. \(I was originally going to use this for custom as well but ended up thinking better of it.) cus-dep.el: Cache the old computed values in custom-load.el and reuse them as necessary, to speed up running cus-dep (which would take 25-30 seconds to do all files in lisp/*, lisp/*/* on my Pentium III 700). Use `message' not `princ' to get correct newline behavior. Output messages showing each file we do actually process. update-elc-2.el: Rewrite algorithm to be much faster -- cache calls to directory-files and don't make needless calls to file-exists-p, file-directory-p because they're way way slow. Autoload early and only when update-elc has told us to. update-elc.el: If no files need byte compilation, signal to update-elc-2 to do any necessary autoload updating (using the file REBUILD_AUTOLOADS) rather than doing it ourselves, which would be way slow. Ignore updates to custom-load.el and auto-autoloads.el when checking to see whether autoloads need updating. Optimize out many unnecessary calls to file-exists-p to speed it up somewhat. (#### The remaining time is 50% or more in locate-file; this is presumably because, even though it has a cache, it's still statting each file to determine it's actually there. By calling directory-files ourselves, building a tree, and then looking in that tree, we could drastically shorten the time needed to do the locate operation.)
author ben
date Fri, 14 Feb 2003 12:05:07 +0000
parents 465bd3c7d932
children f99d3d25df86
line wrap: on
line diff
--- a/lisp/update-elc-2.el	Fri Feb 14 11:50:36 2003 +0000
+++ b/lisp/update-elc-2.el	Fri Feb 14 12:05:07 2003 +0000
@@ -69,6 +69,8 @@
     "^version\\.el$"
     "^very-early-lisp\\.el$"))
 
+(defvar dirfiles-table (make-hash-table :test 'equal))
+
 ;; SEEN accumulates the list of already-handled dirs.
 (defun do-update-elc-2 (dir compile-stage-p seen)
   (setq dir (file-name-as-directory dir))
@@ -76,65 +78,104 @@
   (unless (member (file-truename dir) seen)
     (push (file-truename dir) seen)
 
-    ;; Do this directory.
-    (if compile-stage-p
-	;; Stage 2: Recompile necessary .els
-	(let ((files (directory-files dir t "\\.el$"))
-	      file file-c)
-	  (while (setq file (car files))
-	    (setq files (cdr files))
-	    (setq file-c (concat file "c"))
-	    (when (and (file-exists-p file)
-		       (or (not (file-exists-p file-c))
-			   (file-newer-than-file-p file file-c))
-		       (let (ignore)
-			 (mapcar
-			  #'(lambda (regexp)
-			      (if (string-match regexp
-						(file-name-nondirectory file))
-				  (setq ignore t)))
-			  update-elc-ignored-files)
-			 (not ignore)))
-	      (byte-compile-file file))))
+    (let ((files (or (gethash dir dirfiles-table)
+		     (directory-files dir t nil t))))
+
+      ;; Do this directory.
+      (if compile-stage-p
+	  ;; Stage 2: Recompile necessary .els
+	  (dolist (file files)
+	    (when (string-match "\\.el$" file)
+	      (let ((file-c (concat file "c")))
+		(when (and (not (member file-c files))
+			   ;; no need to check for out-of-date-ness because
+			   ;; that was already done, and .elc removed.
+			   (let (ignore)
+			     (mapcar
+			      #'(lambda (regexp)
+				  (if (string-match
+				       regexp
+				       (file-name-nondirectory file))
+				      (setq ignore t)))
+			      update-elc-ignored-files)
+			     (not ignore)))
+		  (byte-compile-file file)))))
 
-      ;; Stage 1.
-      ;; Remove out-of-date elcs
-      (let ((files (directory-files dir t "\\.el$"))
-	    file file-c)
-	(while (setq file (car files))
-	  (setq files (cdr files))
-	  (setq file-c (concat file "c"))
-	  (when (and (file-exists-p file-c)
-		     (file-newer-than-file-p file file-c))
-	    (message "Removing out-of-date %s" file-c)
-	    (delete-file file-c))))
-      ;; Remove elcs without corresponding el
-      (let ((files (directory-files dir t "\\.elc$"))
-	    file file-c)
-	(while (setq file-c (car files))
-	  (setq files (cdr files))
-	  (setq file (replace-in-string file-c "c$" ""))
-	  (when (and (file-exists-p file-c)
-		     (not (file-exists-p file)))
-	    (message "Removing %s; no corresponding .el" file-c)
-	    (delete-file file-c)))))
+	;; Stage 1.
+	;; Remove out-of-date elcs
+	(let (deleted)
+	  (dolist (file files)
+	    (when (string-match "\\.el$" file)
+	      (let ((file-c (concat file "c")))
+		(when (and (member file-c files)
+			   (file-newer-than-file-p file file-c))
+		  (message "Removing out-of-date %s" file-c)
+		  (delete-file file-c)
+		  (push file-c deleted)))))
 
-    ;; We descend recursively
-    (let ((dirs (directory-files dir t nil t))
-          dir)
-      (while (setq dir (pop dirs))
-        (when (and (not (member (file-name-nondirectory dir)
-				update-elc-ignored-dirs))
-                   (file-directory-p dir))
-          (do-update-elc-2 dir compile-stage-p seen))))
+	;; Remove elcs without corresponding el
+	(dolist (file-c files)
+	  (when (string-match "\\.elc$" file-c)
+	    (let ((file (replace-in-string file-c "c$" "")))
+	      (when (not (member file files))
+		(message "Removing %s; no corresponding .el" file-c)
+		(delete-file file-c)
+		(push file-c deleted)))))
 
-    ))
+	(setq files (set-difference files deleted))))
+
+      (puthash dir files dirfiles-table)
+
+      ;; We descend recursively.  On my Windows machine, it is much faster
+      ;; to call directory-files again to recompute than to call
+      ;; file-directory-p on each member of the files list.
+      (dolist (dir (directory-files dir t nil t 'dir))
+	(when (not (member (file-name-nondirectory dir)
+			   update-elc-ignored-dirs))
+	  (do-update-elc-2 dir compile-stage-p seen))))))
 
 (defun batch-update-elc-2 ()
   (defvar command-line-args-left)
   (unless noninteractive
     (error "`batch-update-elc-2' is to be used only with -batch"))
   (let ((dir (car command-line-args-left)))
+    ;; don't depend on being able to autoload `update-autoload-files'!
+    (load "autoload")
+    (load "bytecomp")
+    (load "byte-optimize")
+    ;; #### the API used here is deprecated, convert to one with explicit
+    ;; arguments when it is available
+    ;; update-elc.el signals us to rebuild the autoloads when necessary.
+    ;; in some cases it will rebuild the autoloads itself, but doing it this
+    ;; way is slow, so we avoid it when possible.
+    (when (file-exists-p "../src/REBUILD_AUTOLOADS")
+      (let ((generated-autoload-file (expand-file-name "auto-autoloads.el" dir))
+	    (autoload-package-name "auto")) ; feature prefix
+	(update-autoload-files (list dir))
+	(byte-recompile-file generated-autoload-file 0))
+      (when (featurep 'mule)
+	(let* ((muledir (expand-file-name "../lisp/mule" (file-truename dir)))
+	       (generated-autoload-file
+		(expand-file-name "auto-autoloads.el" muledir))
+	       (autoload-package-name "mule")) ; feature prefix
+	  (update-autoload-files (list muledir))
+	  (byte-recompile-file generated-autoload-file 0))))
+    (when (featurep 'modules)
+      (let* ((moddir (expand-file-name "../modules" (file-truename dir)))
+	     (generated-autoload-file
+	      (expand-file-name "auto-autoloads.el" moddir))
+	     (autoload-package-name "modules")) ; feature prefix
+	(update-autoload-files
+	 (delete (concat (file-name-as-directory moddir) ".")
+		 (delete (concat (file-name-as-directory moddir) "..")
+			 (directory-files moddir t nil nil 0)))
+	 t)
+	(byte-recompile-file generated-autoload-file 0)))
+    ;; now load the (perhaps newly rebuilt) autoloads; we were called with
+    ;; -no-autoloads so they're not already loaded.
+    (load "../lisp/auto-autoloads")
+    (when (featurep 'mule)
+      (load "../lisp/mule/auto-autoloads"))
     ;; 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
@@ -146,32 +187,6 @@
     (message "Recompiling updated .els in directory tree `%s'..." dir)
     (do-update-elc-2 dir t nil)
     (message "Recompiling updated .els in directory tree `%s'...done" dir)
-    ;; don't depend on being able to autoload `update-autoload-files'!
-    (load "autoload")
-    ;; #### the API used here is deprecated, convert to one with explicit
-    ;; arguments when it is available
-    (let ((generated-autoload-file (expand-file-name "auto-autoloads.el" dir))
-	  (autoload-package-name "auto")) ; feature prefix
-      (update-autoload-files (list dir))
-      (byte-recompile-file generated-autoload-file 0))
-    (when (featurep 'modules)
-      (let* ((moddir (expand-file-name "../modules" (file-truename dir)))
-	     (generated-autoload-file
-	      (expand-file-name "auto-autoloads.el" moddir))
-	     (autoload-package-name "modules")) ; feature prefix
-	(update-autoload-files
-	 (delete (concat (file-name-as-directory moddir) ".")
-		 (delete (concat (file-name-as-directory moddir) "..")
-			 (directory-files moddir t nil nil 0)))
-	 t)
-	(byte-recompile-file generated-autoload-file 0)))
-    (when (featurep 'mule)
-      (let* ((muledir (expand-file-name "../lisp/mule" (file-truename dir)))
-	     (generated-autoload-file
-	      (expand-file-name "auto-autoloads.el" muledir))
-	     (autoload-package-name "mule")) ; feature prefix
-	(update-autoload-files (list muledir))
-	(byte-recompile-file generated-autoload-file 0)))
     ;; likewise here.
     (load "cus-dep")
     (Custom-make-dependencies dir)