From c5c69ce239577ce1e0fb468698d7aeb2453a6cbb Mon Sep 17 00:00:00 2001 From: Lin Sun Date: Wed, 10 Aug 2022 00:00:11 +0000 Subject: [PATCH] core: more precise directory byte-compile status for "core/libs/" folder --- core/core-compilation.el | 80 ++++++++++++++++++++++++---------------- core/core-spacemacs.el | 9 +++-- init.el | 4 +- 3 files changed, 55 insertions(+), 38 deletions(-) diff --git a/core/core-compilation.el b/core/core-compilation.el index 99b183d73..4129687c0 100644 --- a/core/core-compilation.el +++ b/core/core-compilation.el @@ -23,6 +23,7 @@ (require 'cl-lib) (require 'subr-x) +(require 'bytecomp) (defvar spacemacs--last-emacs-version "" "This variable is set during Emacs initialization to its version.") @@ -30,43 +31,58 @@ (expand-file-name (concat spacemacs-cache-directory "last-emacs-version")) "File that sets `spacemacs--last-emacs-version' variable.") -(defconst spacemacs--compiled-files - '(;; Built-in libs that we changed - "core/libs/forks/load-env-vars.el" - "core/libs/forks/spacemacs-ht.el" - ;; Rest of built-in libs. - "core/libs/ido-vertical-mode.el" - "core/libs/package-build-badges.el" - "core/libs/package-build.el" - "core/libs/package-recipe-mode.el" - "core/libs/package-recipe.el" - "core/libs/page-break-lines.el" - "core/libs/validate.el" - "core/libs/quelpa.el" - "core/libs/spinner.el") - "List of Spacemacs files that should be compiled. -File paths are relative to the `spacemacs-start-directory'.") - -(defun spacemacs//ensure-byte-compilation (files) - "Make sure that elisp FILES are byte-compiled." - (dolist (file files) - (let ((fbp (file-name-sans-extension (file-truename file)))) - (unless (file-exists-p (concat fbp ".elc")) - (byte-compile-file (concat fbp ".el")))))) - (defun spacemacs//remove-byte-compiled-files-in-dir (dir) "Remove all .elc files in DIR directory." - (dolist (elc (directory-files-recursively dir "\\.elc$")) + (dolist (elc (directory-files-recursively dir "\\.elc\\(\\.gz\\)?$")) (when (file-exists-p elc) (delete-file elc)))) -(defun spacemacs//dir-contains-stale-byte-compiled-files-p (dir) - "Returns true if any .elc file in DIR directory is stale or orphaned." - (cl-dolist (elc (directory-files-recursively dir "\\.elc$")) - (let ((el (substring elc 0 -1))) - (unless (and (file-exists-p el) - (file-newer-than-file-p elc el)) - (cl-return t))))) +(defvar spacemacs--dir-byte-compile-status + (make-hash-table :test 'equal) + "The hash table to store each directory byte compile state. +nil for un-initialized, -1 for stale or orphaned *.elc, +0 for no *.elc, 1 for *.elc corresponding to *.el.") + +(cl-defun spacemacs//dir-byte-compile-state (dir &optional update) + "Get the directory byte-compile state. +When the UPDATE is t, will fouce update the state." + (let ((state (gethash dir spacemacs--dir-byte-compile-status))) + (when (and (not update) state) + (cl-return-from spacemacs//dir-byte-compile-state state)) + (setq state nil) + (remhash dir spacemacs--dir-byte-compile-status) + (let ((afiles '()) + (slist (mapcan + (lambda (x) + (mapcar (lambda (y) (concat x y)) load-file-rep-suffixes)) + (list ".el" (byte-compile-dest-file ".el"))))) + (cl-dolist (file (directory-files-recursively dir "\\.elc?\\(\\.gz\\)?$")) + (let* ((name (file-name-sans-extension file)) + (paths (alist-get name afiles nil nil 'equal))) + (unless paths + (setq paths (list nil nil nil nil)) + (push (cons name paths) afiles)) + (if-let ((idx (cl-loop for i from 0 + for s in slist + until (string-suffix-p s file) + finally return i))) + (setf (nth idx paths) file)))) + (cl-dolist (item (mapcar 'cdr afiles)) + (let ((el (or (nth 0 item) (nth 1 item))) ; .el or .el.gz file + (elc (or (nth 2 item) (nth 3 item)))) ; .elc or .elc.gz file + (pcase nil + ((guard (null el)) ; *.el not exists + (puthash dir -1 spacemacs--dir-byte-compile-status) + (cl-return -1)) + ((guard (null elc)) ; *.elc not exists + (when (null state) + (setq state 0))) + ((guard (file-newer-than-file-p el elc)) ; *.elc is older + (puthash dir -1 spacemacs--dir-byte-compile-status) + (cl-return -1)) + (_ + (setq state 1))))) + (puthash dir state spacemacs--dir-byte-compile-status)))) (defun spacemacs//update-last-emacs-version () "Update `spacemacs--last-emacs-version' and its saved value." diff --git a/core/core-spacemacs.el b/core/core-spacemacs.el index 8ba062a0e..07810ad17 100644 --- a/core/core-spacemacs.el +++ b/core/core-spacemacs.el @@ -255,10 +255,11 @@ Note: the hooked function is not executed when in dumped mode." gc-cons-percentage (cadr dotspacemacs-gc-cons)) (setq read-process-output-max dotspacemacs-read-process-output-max))) - (let ((default-directory spacemacs-start-directory)) - (if dotspacemacs-byte-compile - (spacemacs//ensure-byte-compilation spacemacs--compiled-files) - (spacemacs//remove-byte-compiled-files-in-dir spacemacs-core-directory))) + (if dotspacemacs-byte-compile + (when (> 1 (spacemacs//dir-byte-compile-state + (concat spacemacs-core-directory "libs/"))) + (byte-recompile-directory (concat spacemacs-core-directory "libs/") 0)) + (spacemacs//remove-byte-compiled-files-in-dir spacemacs-core-directory)) ;; Check if revision has changed. (spacemacs//revision-check)) diff --git a/init.el b/init.el index 2ce6f5bf6..7aee0e84c 100644 --- a/init.el +++ b/init.el @@ -42,8 +42,8 @@ nil (not init-file-debug)) (load spacemacs--last-emacs-version-file t (not init-file-debug)) (when (or (not (string= spacemacs--last-emacs-version emacs-version)) - (spacemacs//dir-contains-stale-byte-compiled-files-p - spacemacs-core-directory)) + (> 0 (spacemacs//dir-byte-compile-state + (concat spacemacs-core-directory "libs/")))) (spacemacs//remove-byte-compiled-files-in-dir spacemacs-core-directory)) ;; Update saved Emacs version. (unless (string= spacemacs--last-emacs-version emacs-version)