diff options
| author | dickmao | 2021-11-07 01:28:47 +0100 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2021-11-07 01:28:47 +0100 |
| commit | 9dfd945a2c2055b1af869a685eb2a667daf4daca (patch) | |
| tree | ccfe862dca7223dafd9921c5743686f623c0e41b | |
| parent | 55fa6a2655972017c692b515b8c476bb9705747d (diff) | |
| download | emacs-9dfd945a2c2055b1af869a685eb2a667daf4daca.tar.gz emacs-9dfd945a2c2055b1af869a685eb2a667daf4daca.zip | |
Fix byte compilation of package built-ins
* lisp/emacs-lisp/package.el
(package--activate-autoloads-and-load-path):
(package--load-files-for-activation): Remove.
(package--library-stem): New function, because
file-name-sans-extension is insufficient.
(package--reload-previously-loaded): New function.
(package-activate-1): Reload directly.
(package--files-load-history):
(package--list-of-conflicts):
(package--list-loaded-files): Remove
(package-unpack): Adjust call.
* test/lisp/emacs-lisp/package-tests.el (macro-builtin-func): Test.
(macro-builtin-10-and-90): Test.
(package-test-macro-compilation): Test.
(package-test-macro-compilation-gz): Test (bug#49708).
6 files changed, 151 insertions, 80 deletions
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index fcbcdc79d8e..4761a3d82ba 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -758,47 +758,47 @@ PKG-DESC is a `package-desc' object." | |||
| 758 | (format "%s-autoloads" (package-desc-name pkg-desc)) | 758 | (format "%s-autoloads" (package-desc-name pkg-desc)) |
| 759 | (package-desc-dir pkg-desc))) | 759 | (package-desc-dir pkg-desc))) |
| 760 | 760 | ||
| 761 | (defun package--activate-autoloads-and-load-path (pkg-desc) | ||
| 762 | "Load the autoloads file and add package dir to `load-path'. | ||
| 763 | PKG-DESC is a `package-desc' object." | ||
| 764 | (let* ((old-lp load-path) | ||
| 765 | (pkg-dir (package-desc-dir pkg-desc)) | ||
| 766 | (pkg-dir-dir (file-name-as-directory pkg-dir))) | ||
| 767 | (with-demoted-errors "Error loading autoloads: %s" | ||
| 768 | (load (package--autoloads-file-name pkg-desc) nil t)) | ||
| 769 | (when (and (eq old-lp load-path) | ||
| 770 | (not (or (member pkg-dir load-path) | ||
| 771 | (member pkg-dir-dir load-path)))) | ||
| 772 | ;; Old packages don't add themselves to the `load-path', so we have to | ||
| 773 | ;; do it ourselves. | ||
| 774 | (push pkg-dir load-path)))) | ||
| 775 | |||
| 776 | (defvar Info-directory-list) | 761 | (defvar Info-directory-list) |
| 777 | (declare-function info-initialize "info" ()) | 762 | (declare-function info-initialize "info" ()) |
| 778 | 763 | ||
| 779 | (defvar package--quickstart-pkgs t | 764 | (defvar package--quickstart-pkgs t |
| 780 | "If set to a list, we're computing the set of pkgs to activate.") | 765 | "If set to a list, we're computing the set of pkgs to activate.") |
| 781 | 766 | ||
| 782 | (defun package--load-files-for-activation (pkg-desc reload) | 767 | (defsubst package--library-stem (file) |
| 783 | "Load files for activating a package given by PKG-DESC. | 768 | (catch 'done |
| 784 | Load the autoloads file, and ensure `load-path' is setup. If | 769 | (let (result) |
| 785 | RELOAD is non-nil, also load all files in the package that | 770 | (dolist (suffix (get-load-suffixes) file) |
| 786 | correspond to previously loaded files." | 771 | (setq result (string-trim file nil suffix)) |
| 787 | (let* ((loaded-files-list | 772 | (unless (equal file result) |
| 788 | (when reload | 773 | (throw 'done result)))))) |
| 789 | (package--list-loaded-files (package-desc-dir pkg-desc))))) | 774 | |
| 790 | ;; Add to load path, add autoloads, and activate the package. | 775 | (defun package--reload-previously-loaded (pkg-desc) |
| 791 | (package--activate-autoloads-and-load-path pkg-desc) | 776 | "Force reimportation of files in PKG-DESC already present in `load-history'. |
| 792 | ;; Call `load' on all files in `package-desc-dir' already present in | 777 | New editions of files contain macro definitions and |
| 793 | ;; `load-history'. This is done so that macros in these files are updated | 778 | redefinitions, the overlooking of which would cause |
| 794 | ;; to their new definitions. If another package is being installed which | 779 | byte-compilation of the new package to fail." |
| 795 | ;; depends on this new definition, not doing this update would cause | 780 | (with-demoted-errors "Error in package--load-files-for-activation: %s" |
| 796 | ;; compilation errors and break the installation. | 781 | (let* (result |
| 797 | (with-demoted-errors "Error in package--load-files-for-activation: %s" | 782 | (dir (package-desc-dir pkg-desc)) |
| 798 | (mapc (lambda (feature) (load feature nil t)) | 783 | (load-path-sans-dir |
| 799 | ;; Skip autoloads file since we already evaluated it above. | 784 | (cl-remove-if (apply-partially #'string= dir) |
| 800 | (remove (file-truename (package--autoloads-file-name pkg-desc)) | 785 | (or (bound-and-true-p find-function-source-path) |
| 801 | loaded-files-list))))) | 786 | load-path))) |
| 787 | (files (directory-files-recursively dir "\\`[^\\.].*\\.el\\'")) | ||
| 788 | (history (mapcar #'file-truename | ||
| 789 | (cl-remove-if-not #'stringp | ||
| 790 | (mapcar #'car load-history))))) | ||
| 791 | (dolist (file files) | ||
| 792 | (when-let ((library (package--library-stem | ||
| 793 | (file-relative-name file dir))) | ||
| 794 | (canonical (locate-library library nil load-path-sans-dir)) | ||
| 795 | (found (member (file-truename canonical) history)) | ||
| 796 | (recent-index (length found))) | ||
| 797 | (unless (equal (file-name-base library) | ||
| 798 | (format "%s-autoloads" (package-desc-name pkg-desc))) | ||
| 799 | (push (cons (expand-file-name library dir) recent-index) result)))) | ||
| 800 | (mapc (lambda (c) (load (car c) nil t)) | ||
| 801 | (sort result (lambda (x y) (< (cdr x) (cdr y)))))))) | ||
| 802 | 802 | ||
| 803 | (defun package-activate-1 (pkg-desc &optional reload deps) | 803 | (defun package-activate-1 (pkg-desc &optional reload deps) |
| 804 | "Activate package given by PKG-DESC, even if it was already active. | 804 | "Activate package given by PKG-DESC, even if it was already active. |
| @@ -825,7 +825,11 @@ correspond to previously loaded files (those returned by | |||
| 825 | (if (listp package--quickstart-pkgs) | 825 | (if (listp package--quickstart-pkgs) |
| 826 | ;; We're only collecting the set of packages to activate! | 826 | ;; We're only collecting the set of packages to activate! |
| 827 | (push pkg-desc package--quickstart-pkgs) | 827 | (push pkg-desc package--quickstart-pkgs) |
| 828 | (package--load-files-for-activation pkg-desc reload)) | 828 | (when reload |
| 829 | (package--reload-previously-loaded pkg-desc)) | ||
| 830 | (with-demoted-errors "Error loading autoloads: %s" | ||
| 831 | (load (package--autoloads-file-name pkg-desc) nil t)) | ||
| 832 | (add-to-list 'load-path (directory-file-name pkg-dir))) | ||
| 829 | ;; Add info node. | 833 | ;; Add info node. |
| 830 | (when (file-exists-p (expand-file-name "dir" pkg-dir)) | 834 | (when (file-exists-p (expand-file-name "dir" pkg-dir)) |
| 831 | ;; FIXME: not the friendliest, but simple. | 835 | ;; FIXME: not the friendliest, but simple. |
| @@ -836,48 +840,6 @@ correspond to previously loaded files (those returned by | |||
| 836 | ;; Don't return nil. | 840 | ;; Don't return nil. |
| 837 | t))) | 841 | t))) |
| 838 | 842 | ||
| 839 | (defun package--files-load-history () | ||
| 840 | (delq nil | ||
| 841 | (mapcar (lambda (x) | ||
| 842 | (let ((f (car x))) | ||
| 843 | (and (stringp f) | ||
| 844 | (file-name-sans-extension (file-truename f))))) | ||
| 845 | load-history))) | ||
| 846 | |||
| 847 | (defun package--list-of-conflicts (dir history) | ||
| 848 | (require 'find-func) | ||
| 849 | (declare-function find-library-name "find-func" (library)) | ||
| 850 | (delq | ||
| 851 | nil | ||
| 852 | (mapcar | ||
| 853 | (lambda (x) (let* ((file (file-relative-name x dir)) | ||
| 854 | ;; Previously loaded file, if any. | ||
| 855 | (previous | ||
| 856 | (ignore-error file-error ;"Can't find library" | ||
| 857 | (file-name-sans-extension | ||
| 858 | (file-truename (find-library-name file))))) | ||
| 859 | (pos (when previous (member previous history)))) | ||
| 860 | ;; Return (RELATIVE-FILENAME . HISTORY-POSITION) | ||
| 861 | (when pos | ||
| 862 | (cons (file-name-sans-extension file) (length pos))))) | ||
| 863 | (directory-files-recursively dir "\\`[^\\.].*\\.el\\'")))) | ||
| 864 | |||
| 865 | (defun package--list-loaded-files (dir) | ||
| 866 | "Recursively list all files in DIR which correspond to loaded features. | ||
| 867 | Returns the `file-name-sans-extension' of each file, relative to | ||
| 868 | DIR, sorted by most recently loaded last." | ||
| 869 | (let* ((history (package--files-load-history)) | ||
| 870 | (dir (file-truename dir)) | ||
| 871 | ;; List all files that have already been loaded. | ||
| 872 | (list-of-conflicts (package--list-of-conflicts dir history))) | ||
| 873 | ;; Turn the list of (FILENAME . POS) back into a list of features. Files in | ||
| 874 | ;; subdirectories are returned relative to DIR (so not actually features). | ||
| 875 | (let ((default-directory (file-name-as-directory dir))) | ||
| 876 | (mapcar (lambda (x) (file-truename (car x))) | ||
| 877 | (sort list-of-conflicts | ||
| 878 | ;; Sort the files by ascending HISTORY-POSITION. | ||
| 879 | (lambda (x y) (< (cdr x) (cdr y)))))))) | ||
| 880 | |||
| 881 | ;;;; `package-activate' | 843 | ;;;; `package-activate' |
| 882 | 844 | ||
| 883 | (defun package--get-activatable-pkg (pkg-name) | 845 | (defun package--get-activatable-pkg (pkg-name) |
| @@ -996,7 +958,7 @@ untar into a directory named DIR; otherwise, signal an error." | |||
| 996 | (package--native-compile-async new-desc)) | 958 | (package--native-compile-async new-desc)) |
| 997 | ;; After compilation, load again any files loaded by | 959 | ;; After compilation, load again any files loaded by |
| 998 | ;; `activate-1', so that we use the byte-compiled definitions. | 960 | ;; `activate-1', so that we use the byte-compiled definitions. |
| 999 | (package--load-files-for-activation new-desc :reload))) | 961 | (package--reload-previously-loaded new-desc))) |
| 1000 | pkg-dir)) | 962 | pkg-dir)) |
| 1001 | 963 | ||
| 1002 | (defun package-generate-description-file (pkg-desc pkg-file) | 964 | (defun package-generate-description-file (pkg-desc pkg-file) |
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el new file mode 100644 index 00000000000..724f88ec9ea --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin-aux.el | |||
| @@ -0,0 +1,12 @@ | |||
| 1 | ;;; macro-builtin-aux.el --- laksd -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Author: Artur Malabarba <emacs@endlessparentheses.com> | ||
| 4 | |||
| 5 | ;;; Code: | ||
| 6 | |||
| 7 | (defun macro-builtin-aux-1 ( &rest forms) | ||
| 8 | "Description" | ||
| 9 | `(progn ,@forms)) | ||
| 10 | |||
| 11 | (provide 'macro-builtin-aux) | ||
| 12 | ;;; macro-builtin-aux.el ends here | ||
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el new file mode 100644 index 00000000000..828968a0576 --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-1.0/macro-builtin.el | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | ;;; macro-builtin.el --- laksd -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Author: Artur Malabarba <emacs@endlessparentheses.com> | ||
| 4 | ;; Keywords: tools | ||
| 5 | ;; Version: 1.0 | ||
| 6 | |||
| 7 | ;;; Code: | ||
| 8 | |||
| 9 | (require 'macro-builtin-aux) | ||
| 10 | |||
| 11 | (defmacro macro-builtin-1 ( &rest forms) | ||
| 12 | "Description" | ||
| 13 | `(progn ,@forms)) | ||
| 14 | |||
| 15 | (defun macro-builtin-func () | ||
| 16 | "" | ||
| 17 | (macro-builtin-1 'a 'b) | ||
| 18 | (macro-builtin-aux-1 'a 'b)) | ||
| 19 | |||
| 20 | (provide 'macro-builtin) | ||
| 21 | ;;; macro-builtin.el ends here | ||
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el new file mode 100644 index 00000000000..9f257d9d22c --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin-aux.el | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | ;;; macro-builtin-aux.el --- laksd -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Author: Artur Malabarba <emacs@endlessparentheses.com> | ||
| 4 | |||
| 5 | ;;; Code: | ||
| 6 | |||
| 7 | (defmacro macro-builtin-aux-1 ( &rest forms) | ||
| 8 | "Description" | ||
| 9 | `(progn ,@forms)) | ||
| 10 | |||
| 11 | (defmacro macro-builtin-aux-3 ( &rest _) | ||
| 12 | "Description" | ||
| 13 | 90) | ||
| 14 | |||
| 15 | (provide 'macro-builtin-aux) | ||
| 16 | ;;; macro-builtin-aux.el ends here | ||
diff --git a/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el new file mode 100644 index 00000000000..5d241c082d0 --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/macro-builtin-package-2.0/macro-builtin.el | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | ;;; macro-builtin.el --- laksd -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Author: Artur Malabarba <emacs@endlessparentheses.com> | ||
| 4 | ;; Keywords: tools | ||
| 5 | ;; Version: 2.0 | ||
| 6 | |||
| 7 | ;;; Code: | ||
| 8 | |||
| 9 | (require 'macro-builtin-aux) | ||
| 10 | |||
| 11 | (defmacro macro-builtin-1 ( &rest forms) | ||
| 12 | "Description" | ||
| 13 | `(progn ,(cadr (car forms)))) | ||
| 14 | |||
| 15 | |||
| 16 | (defun macro-builtin-func () | ||
| 17 | "" | ||
| 18 | (list (macro-builtin-1 '1 'b) | ||
| 19 | (macro-builtin-aux-1 'a 'b))) | ||
| 20 | |||
| 21 | (defmacro macro-builtin-3 (&rest _) | ||
| 22 | "Description" | ||
| 23 | 10) | ||
| 24 | |||
| 25 | (defun macro-builtin-10-and-90 () | ||
| 26 | "" | ||
| 27 | (list (macro-builtin-3 haha) (macro-builtin-aux-3 hehe))) | ||
| 28 | |||
| 29 | (provide 'macro-builtin) | ||
| 30 | ;;; macro-builtin.el ends here | ||
diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el index 1fd93bc1be7..c038c91e6a9 100644 --- a/test/lisp/emacs-lisp/package-tests.el +++ b/test/lisp/emacs-lisp/package-tests.el | |||
| @@ -342,9 +342,13 @@ but with a different end of line convention (bug#48137)." | |||
| 342 | 342 | ||
| 343 | (declare-function macro-problem-func "macro-problem" ()) | 343 | (declare-function macro-problem-func "macro-problem" ()) |
| 344 | (declare-function macro-problem-10-and-90 "macro-problem" ()) | 344 | (declare-function macro-problem-10-and-90 "macro-problem" ()) |
| 345 | (declare-function macro-builtin-func "macro-builtin" ()) | ||
| 346 | (declare-function macro-builtin-10-and-90 "macro-builtin" ()) | ||
| 345 | 347 | ||
| 346 | (ert-deftest package-test-macro-compilation () | 348 | (ert-deftest package-test-macro-compilation () |
| 347 | "Install a package which includes a dependency." | 349 | "\"Activation has to be done before compilation, so that if we're |
| 350 | upgrading and macros have changed we load the new definitions | ||
| 351 | before compiling.\" -- package.el" | ||
| 348 | (with-package-test (:basedir (ert-resource-directory)) | 352 | (with-package-test (:basedir (ert-resource-directory)) |
| 349 | (package-install-file (expand-file-name "macro-problem-package-1.0/")) | 353 | (package-install-file (expand-file-name "macro-problem-package-1.0/")) |
| 350 | (require 'macro-problem) | 354 | (require 'macro-problem) |
| @@ -357,6 +361,32 @@ but with a different end of line convention (bug#48137)." | |||
| 357 | ;; `macro-problem-10-and-90' depends on an entirely new macro from `macro-aux'. | 361 | ;; `macro-problem-10-and-90' depends on an entirely new macro from `macro-aux'. |
| 358 | (should (equal (macro-problem-10-and-90) '(10 90))))) | 362 | (should (equal (macro-problem-10-and-90) '(10 90))))) |
| 359 | 363 | ||
| 364 | (ert-deftest package-test-macro-compilation-gz () | ||
| 365 | "Built-in's can be superseded as well." | ||
| 366 | (with-package-test (:basedir (ert-resource-directory)) | ||
| 367 | (let ((dir (expand-file-name "macro-builtin-package-1.0"))) | ||
| 368 | (unwind-protect | ||
| 369 | (let ((load-path load-path)) | ||
| 370 | (add-to-list 'load-path (directory-file-name dir)) | ||
| 371 | (byte-recompile-directory dir 0 t) | ||
| 372 | (mapc (lambda (f) (rename-file f (concat f ".gz"))) | ||
| 373 | (directory-files-recursively dir "\\`[^\\.].*\\.el\\'")) | ||
| 374 | (require 'macro-builtin) | ||
| 375 | (should (member (expand-file-name "macro-builtin-aux.elc" dir) | ||
| 376 | (mapcar #'car load-history))) | ||
| 377 | ;; `macro-builtin-func' uses a macro from `macro-aux'. | ||
| 378 | (should (equal (macro-builtin-func) '(progn a b))) | ||
| 379 | (package-install-file (expand-file-name "macro-builtin-package-2.0/")) | ||
| 380 | ;; After upgrading, `macro-builtin-func' depends on a new version | ||
| 381 | ;; of the macro from `macro-builtin-aux'. | ||
| 382 | (should (equal (macro-builtin-func) '(1 b))) | ||
| 383 | ;; `macro-builtin-10-and-90' depends on an entirely new macro from `macro-aux'. | ||
| 384 | (should (equal (macro-builtin-10-and-90) '(10 90)))) | ||
| 385 | (mapc #'delete-file | ||
| 386 | (directory-files-recursively dir "\\`[^\\.].*\\.elc\\'")) | ||
| 387 | (mapc (lambda (f) (rename-file f (file-name-sans-extension f))) | ||
| 388 | (directory-files-recursively dir "\\`[^\\.].*\\.el.gz\\'")))))) | ||
| 389 | |||
| 360 | (ert-deftest package-test-install-two-dependencies () | 390 | (ert-deftest package-test-install-two-dependencies () |
| 361 | "Install a package which includes a dependency." | 391 | "Install a package which includes a dependency." |
| 362 | (with-package-test () | 392 | (with-package-test () |