Mercurial > hg > xemacs-beta
changeset 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 | 6c21360a544b |
children | 20da06d05889 |
files | lisp/ChangeLog lisp/autoload.el lisp/cus-dep.el lisp/update-elc-2.el lisp/update-elc.el |
diffstat | 5 files changed, 425 insertions(+), 387 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/ChangeLog Fri Feb 14 11:50:36 2003 +0000 +++ b/lisp/ChangeLog Fri Feb 14 12:05:07 2003 +0000 @@ -17,57 +17,46 @@ * autoload.el (generate-autoload-ish-1): * autoload.el (generate-file-autoloads-1): * autoload.el (generate-c-file-autoloads-1): - * byte-optimize.el: - * byte-optimize.el (byte-compile-inline-expand): - * byte-optimize.el (byte-compile-unfold-lambda): - * byte-optimize.el (byte-optimize-form-code-walker): - * byte-optimize.el (byte-optimize-form): - * byte-optimize.el (byte-decompile-bytecode-1): - * byte-optimize.el (byte-optimize-lapcode): + 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: * cus-dep.el (cusload-hash-table-marker): New. * cus-dep.el (Custom-make-dependencies-1): + 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: * update-elc-2.el (dirfiles-table): New. * update-elc-2.el (do-update-elc-2): * update-elc-2.el (batch-update-elc-2): + 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: * update-elc.el (dumped-exe): Removed. * update-elc.el (dumped-exe-out-of-date-wrt-undumped-exe): Removed. * update-elc.el (lisp-files-ignored-when-checking-for-autoload-updating): New. * update-elc.el ((preloaded-file-list site-load-packages files-to-process)): - -2003-02-11 Ben Wing <ben@xemacs.org> - - * byte-optimize.el: - * byte-optimize.el (byte-compile-inline-expand): - * byte-optimize.el (byte-compile-unfold-lambda): - * byte-optimize.el (byte-optimize-form-code-walker): - * byte-optimize.el (byte-optimize-form): - * byte-optimize.el (byte-decompile-bytecode-1): - * byte-optimize.el (byte-optimize-lapcode): + 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.) - * update-elc-2.el: - * update-elc-2.el (dirfiles-table): New. - * update-elc-2.el (dolist): New. - * update-elc-2.el (do-update-elc-2): - * update-elc-2.el (batch-update-elc-2): - 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: - * update-elc.el (dumped-exe-exists): New. - * update-elc.el (lisp-files-ignored-when-checking-for-autoload-updating): New. - * update-elc.el ((preloaded-file-list site-load-packages files-to-process)): - If no files need byte compilation, signal to update-elc-2 to do - any necessary autoload updating 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. - 2003-02-12 Jerry James <james@xemacs.org> * about.el (about-url-alist): Add my home page.
--- a/lisp/autoload.el Fri Feb 14 11:50:36 2003 +0000 +++ b/lisp/autoload.el Fri Feb 14 12:05:07 2003 +0000 @@ -2,7 +2,7 @@ ;; Copyright (C) 1991, 1992, 1993, 1994, 1997 Free Software Foundation, Inc. ;; Copyright (C) 1995 Tinker Systems and INS Engineering Corp. -;; Copyright (C) 1996, 2000, 2002 Ben Wing. +;; Copyright (C) 1996, 2000, 2002, 2003 Ben Wing. ;; Author: Roland McGrath <roland@gnu.ai.mit.edu> ;; Keywords: maint @@ -291,31 +291,33 @@ are used." (interactive "fGenerate autoloads for file: ") (cond ((string-match "\\.el$" file) - (generate-file-autoloads-1 file funlist)) + (generate-autoload-ish-1 + file + (replace-in-string (file-name-nondirectory file) "\\.elc?$" "") + nil #'generate-file-autoloads-1 + funlist)) ;; #### jj, are C++ modules possible? ((string-match "\\.c$" file) - (generate-c-file-autoloads-1 file funlist)) + (generate-autoload-ish-1 + file + (replace-in-string (file-name-nondirectory file) "\\.c$" "") + t #'generate-c-file-autoloads-1)) (t (error 'wrong-type-argument file "not a C or Elisp source file")))) -(defun* generate-file-autoloads-1 (file funlist) - "Insert at point an autoload section for FILE. -autoloads are generated for defuns and defmacros in FILE -marked by `generate-autoload-cookie' (which see). -If FILE is being visited in a buffer, the contents of the buffer -are used." +(defun* generate-autoload-ish-1 (file load-name literal fun-to-call &rest args) + "Insert at point an autoload-type section for FILE. +If LITERAL, open the file literally, without decoding. +Calls FUN-TO-CALL to compute the autoloads, passing it OUTBUF, LOAD-NAME, + TRIM-NAME, and ARGS." (let ((outbuf (current-buffer)) + (trim-name (autoload-trim-file-name file)) (autoloads-done '()) - (load-name (replace-in-string (file-name-nondirectory file) - "\\.elc?$" - "")) - (trim-name (autoload-trim-file-name file)) - (dofiles (not (null funlist))) (print-length nil) (print-readably t) ; XEmacs (float-output-format nil) + (visited (get-file-buffer file)) ;; (done-any nil) - (visited (get-file-buffer file)) output-end) ;; If the autoload section we create here uses an absolute @@ -332,74 +334,19 @@ (progn (let ((find-file-hooks nil) (enable-local-variables nil)) - (set-buffer (or visited (find-file-noselect file))) + (set-buffer (or visited (find-file-noselect file literal literal + ))) + ;; This doesn't look right for C files, but it is. The only + ;; place we need the syntax table is when snarfing the Lisp + ;; function name. (set-syntax-table emacs-lisp-mode-syntax-table)) - (save-excursion - (save-restriction - (widen) - (goto-char (point-min)) - (unless (search-forward generate-autoload-cookie nil t) - (message "No autoloads found in %s" trim-name) - (return-from generate-file-autoloads-1)) - - (message "Generating autoloads for %s..." trim-name) - (goto-char (point-min)) - (while (if dofiles funlist (not (eobp))) - (if (not dofiles) - (skip-chars-forward " \t\n\f") - (goto-char (point-min)) - (re-search-forward - (concat "(def\\(un\\|var\\|const\\|macro\\) " - (regexp-quote (symbol-name (car funlist))) - "\\s ")) - (goto-char (match-beginning 0))) - (cond - ((or dofiles - (looking-at (regexp-quote generate-autoload-cookie))) - (if dofiles - nil - (search-forward generate-autoload-cookie) - (skip-chars-forward " \t")) - ;; (setq done-any t) - (if (or dofiles (eolp)) - ;; Read the next form and make an autoload. - (let* ((form (prog1 (read (current-buffer)) - (or (bolp) (forward-line 1)))) - (autoload (make-autoload form load-name)) - (doc-string-elt (get (car-safe form) - 'doc-string-elt))) - (if autoload - (setq autoloads-done (cons (nth 1 form) - autoloads-done)) - (setq autoload form)) - (print-autoload autoload doc-string-elt outbuf "")) - ;; Copy the rest of the line to the output. - (let ((begin (point))) - ;; (terpri outbuf) - (cond ((looking-at "immediate\\s *$") ; XEmacs - ;; This is here so that you can automatically - ;; have small hook functions copied to - ;; auto-autoloads.el so that it's not necessary - ;; to load a whole file just to get a two-line - ;; do-nothing find-file-hook... --Stig - (forward-line 1) - (setq begin (point)) - (forward-sexp) - (forward-line 1)) - (t - (forward-line 1))) - (princ (buffer-substring begin (point)) outbuf)))) - ((looking-at ";") - ;; Don't read the comment. - (forward-line 1)) - (t - (forward-sexp 1) - (forward-line 1))) - (if dofiles - (setq funlist (cdr funlist))))))) + (unless (setq autoloads-done + (apply fun-to-call outbuf load-name trim-name args)) + (return-from generate-autoload-ish-1)) + ) (unless visited - ;; We created this buffer, so we should kill it. - (kill-buffer (current-buffer))) + ;; We created this buffer, so we should kill it. + (kill-buffer (current-buffer))) (set-buffer outbuf) (setq output-end (point-marker)))) (if t ;; done-any @@ -432,119 +379,153 @@ (or noninteractive ; XEmacs: only need one line in -batch mode. (message "Generating autoloads for %s...done" file)))) -(defun* generate-c-file-autoloads-1 (file funlist) +(defun* generate-file-autoloads-1 (outbuf load-name trim-name funlist) + "Insert at point an autoload section for FILE. +autoloads are generated for defuns and defmacros in FILE +marked by `generate-autoload-cookie' (which see). +If FILE is being visited in a buffer, the contents of the buffer +are used." + (let ((autoloads-done '()) + (dofiles (not (null funlist))) + ) + + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (unless (search-forward generate-autoload-cookie nil t) + (message "No autoloads found in %s" trim-name) + (return-from generate-file-autoloads-1 nil)) + + (message "Generating autoloads for %s..." trim-name) + (goto-char (point-min)) + (while (if dofiles funlist (not (eobp))) + (if (not dofiles) + (skip-chars-forward " \t\n\f") + (goto-char (point-min)) + (re-search-forward + (concat "(def\\(un\\|var\\|const\\|macro\\) " + (regexp-quote (symbol-name (car funlist))) + "\\s ")) + (goto-char (match-beginning 0))) + (cond + ((or dofiles + (looking-at (regexp-quote generate-autoload-cookie))) + (if dofiles + nil + (search-forward generate-autoload-cookie) + (skip-chars-forward " \t")) + ;; (setq done-any t) + (if (or dofiles (eolp)) + ;; Read the next form and make an autoload. + (let* ((form (prog1 (read (current-buffer)) + (or (bolp) (forward-line 1)))) + (autoload (make-autoload form load-name)) + (doc-string-elt (get (car-safe form) + 'doc-string-elt))) + (if autoload + (setq autoloads-done (cons (nth 1 form) + autoloads-done)) + (setq autoload form)) + (print-autoload autoload doc-string-elt outbuf "")) + ;; Copy the rest of the line to the output. + (let ((begin (point))) + ;; (terpri outbuf) + (cond ((looking-at "immediate\\s *$") ; XEmacs + ;; This is here so that you can automatically + ;; have small hook functions copied to + ;; auto-autoloads.el so that it's not necessary + ;; to load a whole file just to get a two-line + ;; do-nothing find-file-hook... --Stig + (forward-line 1) + (setq begin (point)) + (forward-sexp) + (forward-line 1)) + (t + (forward-line 1))) + (princ (buffer-substring begin (point)) outbuf)))) + ((looking-at ";") + ;; Don't read the comment. + (forward-line 1)) + (t + (forward-sexp 1) + (forward-line 1))) + (if dofiles + (setq funlist (cdr funlist)))))) + autoloads-done)) + +(defun* generate-c-file-autoloads-1 (outbuf load-name trim-name funlist) "Insert at point an autoload section for the C file FILE. autoloads are generated for defuns and defmacros in FILE marked by `generate-c-autoload-cookie' (which see). If FILE is being visited in a buffer, the contents of the buffer are used." - (let ((outbuf (current-buffer)) - (autoloads-done '()) - (load-name (replace-in-string (file-name-nondirectory file) - "\\.c?$" - "")) - (exists-p-format + (let ((exists-p-format "(file-exists-p (expand-file-name \"%s.%s\" module-directory))") - (trim-name (autoload-trim-file-name file)) - (print-length nil) - (print-readably t) - (float-output-format nil) - ;; (done-any nil) - (visited (get-file-buffer file)) - output-end) - - ;; If the autoload section we create here uses an absolute - ;; pathname for FILE in its header, and then Emacs is installed - ;; under a different path on another system, - ;; `update-autoloads-here' won't be able to find the files to be - ;; autoloaded. So, if FILE is in the same directory or a - ;; subdirectory of the current buffer's directory, we'll make it - ;; relative to the current buffer's directory. - (setq file (expand-file-name file)) + (autoloads-done '()) + ) (save-excursion - (unwind-protect - (progn - (let ((find-file-hooks nil) - (enable-local-variables nil)) - (set-buffer (or visited (find-file-noselect file t t))) - ;; This doesn't look right, but it is. The only place we need - ;; the syntax table is when snarfing the Lisp function name. - (set-syntax-table emacs-lisp-mode-syntax-table)) - (save-excursion - (save-restriction - (widen) + (save-restriction + (widen) + (goto-char (point-min)) + ;; Is there a module name comment? + (when (search-forward generate-c-autoload-module nil t) + (skip-chars-forward " \t") + (let ((begin (point))) + (skip-chars-forward "^ \t\n\f") + (setq load-name (buffer-substring begin (point))))) + (if funlist + (progn + (message "Generating autoloads for %s..." trim-name) + (princ "(when (or\n " outbuf) + (princ (format exists-p-format load-name "ell") outbuf) + (princ "\n " outbuf) + (princ (format exists-p-format load-name "dll") outbuf) + (princ "\n " outbuf) + (princ (format exists-p-format load-name "so") outbuf) + ;; close the princ'd `or' form + (princ ")\n " outbuf) + (dolist (arg funlist) (goto-char (point-min)) - ;; Is there a module name comment? - (when (search-forward generate-c-autoload-module nil t) - (skip-chars-forward " \t") - (let ((begin (point))) - (skip-chars-forward "^ \t\n\f") - (setq load-name (buffer-substring begin (point))))) - (if funlist - (progn - (message "Generating autoloads for %s..." trim-name) - (princ "(when (or\n " outbuf) - (princ (format exists-p-format load-name "ell") outbuf) - (princ "\n " outbuf) - (princ (format exists-p-format load-name "dll") outbuf) - (princ "\n " outbuf) - (princ (format exists-p-format load-name "so") outbuf) - ;; close the princ'd `or' form - (princ ")\n " outbuf) - (dolist (arg funlist) - (goto-char (point-min)) - (re-search-forward - (concat "DEFUN (\"" - (regexp-quote (symbol-name arg)) - "\"")) - (goto-char (match-beginning 0)) - (let ((autoload (make-c-autoload load-name))) - (when autoload - (push (nth 1 (nth 1 autoload)) autoloads-done) - (print-autoload autoload 3 outbuf " ")))) - ;; close the princ'd `when' form - (princ ")" outbuf)) - (goto-char (point-min)) - (let ((match - (search-forward generate-c-autoload-cookie nil t))) - (unless match - (message "No autoloads found in %s" trim-name) - (return-from generate-c-file-autoloads-1)) - - (message "Generating autoloads for %s..." trim-name) - (princ "(when (or\n " outbuf) - (princ (format exists-p-format load-name "ell") outbuf) - (princ "\n " outbuf) - (princ (format exists-p-format load-name "dll") outbuf) - (princ "\n " outbuf) - (princ (format exists-p-format load-name "so") outbuf) - ;; close the princ'd `or' form - (princ ")\n " outbuf) - (while match - (forward-line 1) - (let ((autoload (make-c-autoload load-name))) - (when autoload - (push (nth 1 (nth 1 autoload)) autoloads-done) - (print-autoload autoload 3 outbuf " "))) - (setq match - (search-forward generate-c-autoload-cookie nil t))) - ;; close the princ'd `when' form - (princ ")" outbuf)))))) - (unless visited - ;; We created this buffer, so we should kill it. - (kill-buffer (current-buffer))) - (set-buffer outbuf) - (setq output-end (point-marker)))) - (insert generate-autoload-section-header) - (prin1 (list 'autoloads autoloads-done load-name trim-name) outbuf) - (terpri outbuf) - (when (< output-end (point)) - (setq output-end (point-marker))) - (goto-char output-end) - (insert generate-autoload-section-trailer) - (or noninteractive ; XEmacs: only need one line in -batch mode. - (message "Generating autoloads for %s...done" trim-name)))) + (re-search-forward + (concat "DEFUN (\"" + (regexp-quote (symbol-name arg)) + "\"")) + (goto-char (match-beginning 0)) + (let ((autoload (make-c-autoload load-name))) + (when autoload + (push (nth 1 (nth 1 autoload)) autoloads-done) + (print-autoload autoload 3 outbuf " ")))) + ;; close the princ'd `when' form + (princ ")" outbuf)) + (goto-char (point-min)) + (let ((match + (search-forward generate-c-autoload-cookie nil t))) + (unless match + (message "No autoloads found in %s" trim-name) + (return-from generate-c-file-autoloads-1 nil)) + + (message "Generating autoloads for %s..." trim-name) + (princ "(when (or\n " outbuf) + (princ (format exists-p-format load-name "ell") outbuf) + (princ "\n " outbuf) + (princ (format exists-p-format load-name "dll") outbuf) + (princ "\n " outbuf) + (princ (format exists-p-format load-name "so") outbuf) + ;; close the princ'd `or' form + (princ ")\n " outbuf) + (while match + (forward-line 1) + (let ((autoload (make-c-autoload load-name))) + (when autoload + (push (nth 1 (nth 1 autoload)) autoloads-done) + (print-autoload autoload 3 outbuf " "))) + (setq match + (search-forward generate-c-autoload-cookie nil t))) + ;; close the princ'd `when' form + (princ ")" outbuf))))) + autoloads-done)) ;; Assorted utilities for generating autoloads and pieces thereof
--- a/lisp/cus-dep.el Fri Feb 14 11:50:36 2003 +0000 +++ b/lisp/cus-dep.el Fri Feb 14 12:05:07 2003 +0000 @@ -1,6 +1,7 @@ ;;; cus-dep.el --- Find customization dependencies. ;; ;; Copyright (C) 1997 Free Software Foundation, Inc. +;; Copyright (C) 2003 Ben Wing. ;; ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>, then ;; Richard Stallman <rms@gnu.ai.mit.edu>, then @@ -76,6 +77,11 @@ ;; files. This is not necessary under FSF (they simply use `put'), ;; since they have only one file with custom dependencies. With the ;; advent of packages, we cannot afford the same luxury. +;; +;; Feb 2003: Added code to speed up building by caching the values we've +;; constructed, and using them instead of scanning a file when custom-load +;; is up-to-date w.r.t. the file. Also use `message' not `princ' to print +;; out messages so nl's are correctly inserted when necessary. --ben ;;; Code: @@ -90,6 +96,7 @@ ;; Don't change this, unless you plan to change the code in ;; cus-start.el, too. (defconst cusload-base-file "custom-load.el") +(defconst cusload-hash-table-marker ";old-cus-dep-hash: ") ;; Be very careful when changing this function. It looks easy to ;; understand, but is in fact very easy to break. Be sure to read and @@ -99,9 +106,11 @@ (setq subdirs (mapcar #'expand-file-name subdirs)) (with-temp-buffer (let ((enable-local-eval nil) - (hash (make-hash-table :test 'eq))) + (hash (make-hash-table :test 'eq)) + (hash-cache (make-hash-table :test 'equal)) + old-hash) (dolist (dir subdirs) - (princ (format "Processing %s\n" dir)) + (message "Processing %s\n" dir) (let ((cusload-file (expand-file-name cusload-base-file dir)) (files (directory-files dir t "\\`[^=].*\\.el\\'"))) ;; A trivial optimization: if no file in the directory is @@ -110,46 +119,77 @@ (dolist (file files t) (when (file-newer-than-file-p file cusload-file) (return nil)))) - (princ "(No changes need to be written)\n") + (message "(No changes need to be written)") + (when (file-exists-p cusload-file) + (let ((buf (find-file-noselect cusload-file))) + (with-current-buffer buf + (goto-char (point-min)) + (when (search-forward cusload-hash-table-marker nil t) + (setq old-hash (read buf)))) + (kill-buffer buf))) ;; Process directory (dolist (file files) - (when (file-exists-p file) - (erase-buffer) - (insert-file-contents file) - (goto-char (point-min)) - (let ((name (file-name-sans-extension - (file-name-nondirectory file)))) - ;; Search for defcustom/defface/defgroup - ;; expressions, and evaluate them. - (while (re-search-forward - "^(defcustom\\|^(defface\\|^(defgroup" - nil t) - (beginning-of-line) - (let ((expr (read (current-buffer)))) - ;; We need to ignore errors here, so that - ;; defcustoms with :set don't bug out. Of - ;; course, their values will not be assigned in - ;; case of errors, but their `custom-group' - ;; properties will by that time be in place, and - ;; that's all we care about. - (ignore-errors - (eval expr)) - ;; Hash the file of the affected symbol. - (setf (gethash (nth 1 expr) hash) name)))))) + (let ((old-cache (if (hash-table-p old-hash) + (gethash file old-hash t) + t))) + (if (and (not (file-newer-than-file-p file cusload-file)) + (not (eq old-cache t))) + (progn + (dolist (c old-cache) + (puthash (car c) (cdr c) hash)) + (puthash file old-cache hash-cache)) + (erase-buffer) + (insert-file-contents file) + (goto-char (point-min)) + (let ((name (file-name-sans-extension + (file-name-nondirectory file))) + cache + (first t)) + ;; Search for defcustom/defface/defgroup + ;; expressions, and evaluate them. + (while (re-search-forward + "^(defcustom\\|^(defface\\|^(defgroup" + nil t) + (when first + (message "Computing custom-loads for %s..." name) + (setq first nil)) + (beginning-of-line) + (let ((expr (read (current-buffer)))) + ;; We need to ignore errors here, so that + ;; defcustoms with :set don't bug out. Of + ;; course, their values will not be assigned in + ;; case of errors, but their `custom-group' + ;; properties will by that time be in place, and + ;; that's all we care about. + (ignore-errors + (eval expr)) + ;; Hash the file of the affected symbol. + (setf (gethash (nth 1 expr) hash) name) + ;; Remember the values computed. + (push (cons (nth 1 expr) name) cache))) + (or cache + (message "No custom-loads for %s" name)) + (puthash file cache hash-cache))) + )) (cond ((zerop (hash-table-count hash)) - (princ "(No customization dependencies") - (when (file-exists-p cusload-file) - (princ (format ", deleting %s" cusload-file)) - (delete-file cusload-file)) - (princ ")\n")) + (if (not (file-exists-p cusload-file)) + (message "(No customization dependencies)") + (message "(No customization dependencies, deleting %s)" + cusload-file) + (delete-file cusload-file))) (t - (princ (format "Generating %s...\n" cusload-base-file)) + (message "Generating %s...\n" cusload-base-file) (with-temp-file cusload-file (insert ";;; " cusload-base-file " --- automatically extracted custom dependencies\n" - "\n;;; Code:\n\n" - "(autoload 'custom-add-loads \"cus-load\")\n\n") + "\n;;; Code:\n\n") + (insert cusload-hash-table-marker) + (let ((print-readably t) + (standard-output (current-buffer))) + (princ hash-cache) + (terpri)) + (insert "(autoload 'custom-add-loads \"cus-load\")\n\n") (mapatoms (lambda (sym) (let ((members (get sym 'custom-group))
--- 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)
--- a/lisp/update-elc.el Fri Feb 14 11:50:36 2003 +0000 +++ b/lisp/update-elc.el Fri Feb 14 12:05:07 2003 +0000 @@ -59,9 +59,9 @@ (defvar need-to-recompile-autoloads nil) (defvar need-to-recompile-mule-autoloads nil) (defvar undumped-exe nil) -(defvar dumped-exe nil) +;(defvar dumped-exe nil) (defvar dumped-exe-out-of-date-wrt-dump-files nil) -(defvar dumped-exe-out-of-date-wrt-undumped-exe nil) +;(defvar dumped-exe-out-of-date-wrt-undumped-exe nil) ;(setq update-elc-files-to-compile ; (delq nil @@ -112,6 +112,11 @@ "very-early-lisp.el") "Lisp files that should not be byte compiled.") +(defvar lisp-files-ignored-when-checking-for-autoload-updating + '("custom-load.el" + "auto-autoloads.el") + "Lisp files that should not trigger auto-autoloads rebuilding.") + (defun update-elc-chop-extension (file) (if (string-match "\\.elc?$" file) (substring file 0 (match-beginning 0)) @@ -130,30 +135,31 @@ ((file-exists-p "../src/xemacs") "../src/xemacs") (t nil))) - (let ((temacs-exe - (cond ((file-exists-p "../src/temacs.exe") "../src/temacs.exe") - ((file-exists-p "../src/temacs") "../src/temacs") - (t nil))) - (data-file - (cond ((file-exists-p "../src/xemacs.dmp") "../src/xemacs.dmp") - (t nil)))) + ;; Not currently used but might be at some point. +; (let ((temacs-exe +; (cond ((file-exists-p "../src/temacs.exe") "../src/temacs.exe") +; ((file-exists-p "../src/temacs") "../src/temacs") +; (t nil))) +; (data-file +; (cond ((file-exists-p "../src/xemacs.dmp") "../src/xemacs.dmp") +; (t nil)))) - ;; two setups here: - ;; (1) temacs.exe is undumped, dumped into xemacs.exe. Happens with - ;; unexec, but also with pdump under MS Windows native, since - ;; the dumped data is stored as a resource in the xemacs.exe - ;; executable. - ;; (2) xemacs.exe is dumped or undumped. Running `xemacs -nd' gets - ;; you the equivalent of `temacs'. Dumping creates a file - ;; `xemacs.dmp'. +; ;; two setups here: +; ;; (1) temacs.exe is undumped, dumped into xemacs.exe. Happens with +; ;; unexec, but also with pdump under MS Windows native, since +; ;; the dumped data is stored as a resource in the xemacs.exe +; ;; executable. +; ;; (2) xemacs.exe is dumped or undumped. Running `xemacs -nd' gets +; ;; you the equivalent of `temacs'. Dumping creates a file +; ;; `xemacs.dmp'. - (setq dumped-exe-out-of-date-wrt-undumped-exe - (cond ((not dumped-exe) t) - (temacs-exe (file-newer-than-file-p temacs-exe dumped-exe)) - ((not data-file) t) - (t (file-newer-than-file-p dumped-exe data-file)))) - ) - +; (setq dumped-exe-out-of-date-wrt-undumped-exe +; (cond ((not dumped-exe) t) +; (temacs-exe (file-newer-than-file-p temacs-exe dumped-exe)) +; ((not data-file) t) +; (t (file-newer-than-file-p dumped-exe data-file)))) +; (setq dumped-exe-exists (or (and temacs-exe dumped-exe) +; (and data-file dumped-exe)))) ;; Path setup (let ((package-preloaded-file-list @@ -200,18 +206,18 @@ ;; now check if .el or .elc is newer than the dumped exe. ;; if so, need to redump. (when (and dumped-exe arg-is-preloaded - (or (and (file-exists-p full-arg-el) - (file-newer-than-file-p full-arg-el dumped-exe)) - (and (file-exists-p full-arg-elc) - (file-newer-than-file-p full-arg-elc dumped-exe)))) + ;; no need to check for existence of either of the files + ;; because of the definition of file-newer-than-file-p. + (or (file-newer-than-file-p full-arg-el dumped-exe) + (file-newer-than-file-p full-arg-elc dumped-exe))) (setq dumped-exe-out-of-date-wrt-dump-files t)) (if (and (not (member (file-name-nondirectory arg) unbytecompiled-lisp-files)) (not (member full-arg-el processed)) - (file-exists-p full-arg-el) - (or (not (file-exists-p full-arg-elc)) - (file-newer-than-file-p full-arg-el full-arg-elc))) + ;; no need to check for existence of either of the files + ;; because of the definition of file-newer-than-file-p. + (file-newer-than-file-p full-arg-el full-arg-elc)) (setq processed (cons full-arg-el processed))) (setq files-to-process (cdr files-to-process)))) @@ -228,9 +234,14 @@ (autoload-is-mule (equal dir "../lisp/mule"))) (while all-files-in-dir (let* ((full-arg (car all-files-in-dir))) - (when (or (not (file-exists-p autoload-file)) - (and (file-exists-p full-arg) - (file-newer-than-file-p full-arg autoload-file))) + ;; custom-load.el always gets regenerated so don't let that + ;; trigger us. + (when (and (not + (member + (file-name-nondirectory full-arg) + lisp-files-ignored-when-checking-for-autoload-updating + )) + (file-newer-than-file-p full-arg autoload-file)) (if autoload-is-mule (setq need-to-rebuild-mule-autoloads t) (setq need-to-rebuild-autoloads t)))) @@ -245,15 +256,22 @@ ) (when (or need-to-rebuild-autoloads + ;; no real need for the following check either, because if the file + ;; doesn't exist, need-to-rebuild-autoloads gets set above. but + ;; it's only one call, so it won't slow things down much and it keeps + ;; the logic cleaner. (not (file-exists-p "../lisp/auto-autoloads.el")) - (not (file-exists-p "../lisp/auto-autoloads.elc")) + ;; no need to check for file-exists of .elc due to definition + ;; of file-newer-than-file-p (file-newer-than-file-p "../lisp/auto-autoloads.el" "../lisp/auto-autoloads.elc")) (setq need-to-recompile-autoloads t)) (when (or need-to-rebuild-mule-autoloads + ;; not necessary but ... see comment above. (not (file-exists-p "../lisp/mule/auto-autoloads.el")) - (not (file-exists-p "../lisp/mule/auto-autoloads.elc")) + ;; no need to check for file-exists of .elc due to definition + ;; of file-newer-than-file-p (file-newer-than-file-p "../lisp/mule/auto-autoloads.el" "../lisp/mule/auto-autoloads.elc")) (setq need-to-recompile-mule-autoloads t)) @@ -285,6 +303,9 @@ (if need-to-recompile-mule-autoloads '("-f" "batch-byte-compile-one-file" "../lisp/mule/auto-autoloads.el"))))) + (condition-case nil + (delete-file "../src/REBUILD_AUTOLOADS") + (file-error nil)) (cond ((and (not update-elc-files-to-compile) (not need-to-rebuild-autoloads) (not need-to-rebuild-mule-autoloads) @@ -297,24 +318,16 @@ (condition-case nil (delete-file "../src/BYTECOMPILE_CHANGE") (file-error nil))) - ((and (not update-elc-files-to-compile) - (not dumped-exe-out-of-date-wrt-dump-files) - (not dumped-exe-out-of-date-wrt-undumped-exe)) + ((not update-elc-files-to-compile) ;; (2) We have no files to byte-compile, but we do need to - ;; regenerate and compile the auto-autoloads file. (This will - ;; be needed to be up-to-date before we run update-elc-2.) - ;; If the dumped exe exists and is up-to-date, both with - ;; respect to the undumped exe and the files that will be dumped - ;; into it, then we can use the dumped exe to rebuild the - ;; autoloads. Else, we have to do it the "hard way" by loading - ;; raw temacs, running loadup, then regenerating the autoloads. - ;; #### We should see whether it's possible to load up a - ;; minimal number of files in order to get autoload.el to work. - (load "raw-process.el") - (apply 'call-process-internal dumped-exe nil t nil - (append - '("-batch -no-autoloads -no-packages") - do-autoload-commands)) + ;; regenerate and compile the auto-autoloads file, so signal + ;; update-elc-2 to do it. This is much faster than loading + ;; all the .el's and doing it here. (We only need to rebuild + ;; the autoloads here when we have files to compile, since + ;; they may depend on the updated autoloads.) + (condition-case nil + (write-region-internal "foo" nil "../src/REBUILD_AUTOLOADS") + (file-error nil)) (condition-case nil (delete-file "../src/BYTECOMPILE_CHANGE") (file-error nil))) @@ -384,6 +397,6 @@ ;;(print command-line-args) (load "loadup-el.el")))) -(kill-emacs) +;(kill-emacs) ;;; update-elc.el ends here