diff options
Diffstat (limited to 'lisp/package/package-compile.el')
| -rw-r--r-- | lisp/package/package-compile.el | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/lisp/package/package-compile.el b/lisp/package/package-compile.el new file mode 100644 index 00000000000..ffe94880efd --- /dev/null +++ b/lisp/package/package-compile.el | |||
| @@ -0,0 +1,111 @@ | |||
| 1 | ;;; package-compile.el --- Byte-Compilation of Packages -*- lexical-binding: t; -*- | ||
| 2 | |||
| 3 | ;; Copyright (C) 2025 Philip Kaludercic | ||
| 4 | |||
| 5 | ;; Author: Philip Kaludercic <philipk@posteo.net> | ||
| 6 | |||
| 7 | ;; This program is free software; you can redistribute it and/or modify | ||
| 8 | ;; it under the terms of the GNU General Public License as published by | ||
| 9 | ;; the Free Software Foundation, either version 3 of the License, or | ||
| 10 | ;; (at your option) any later version. | ||
| 11 | |||
| 12 | ;; This program is distributed in the hope that it will be useful, | ||
| 13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | ;; GNU General Public License for more details. | ||
| 16 | |||
| 17 | ;; You should have received a copy of the GNU General Public License | ||
| 18 | ;; along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ;;; Commentary: | ||
| 21 | |||
| 22 | ;;; Code: | ||
| 23 | |||
| 24 | (require 'package-core) | ||
| 25 | |||
| 26 | (defvar warning-minimum-level) | ||
| 27 | (defvar byte-compile-ignore-files) | ||
| 28 | |||
| 29 | (defcustom package-native-compile nil | ||
| 30 | "Non-nil means to natively compile packages as part of their installation. | ||
| 31 | This controls ahead-of-time compilation of packages when they are | ||
| 32 | installed. If this option is nil, packages will be natively | ||
| 33 | compiled when they are loaded for the first time. | ||
| 34 | |||
| 35 | This option does not have any effect if Emacs was not built with | ||
| 36 | native compilation support." | ||
| 37 | :type '(boolean) | ||
| 38 | :risky t | ||
| 39 | :version "28.1" | ||
| 40 | :group 'package) | ||
| 41 | |||
| 42 | (defun package--parse-elpaignore (pkg-desc) | ||
| 43 | "Return a list of regular expressions to match files ignored by PKG-DESC." | ||
| 44 | (let* ((pkg-dir (file-name-as-directory (package-desc-dir pkg-desc))) | ||
| 45 | (ignore (expand-file-name ".elpaignore" pkg-dir)) | ||
| 46 | files) | ||
| 47 | (when (file-exists-p ignore) | ||
| 48 | (with-temp-buffer | ||
| 49 | (insert-file-contents ignore) | ||
| 50 | (goto-char (point-min)) | ||
| 51 | (while (not (eobp)) | ||
| 52 | (push (wildcard-to-regexp | ||
| 53 | (let ((line (buffer-substring | ||
| 54 | (line-beginning-position) | ||
| 55 | (line-end-position)))) | ||
| 56 | (file-name-concat pkg-dir (string-trim-left line "/")))) | ||
| 57 | files) | ||
| 58 | (forward-line))) | ||
| 59 | files))) | ||
| 60 | |||
| 61 | (defun package--compile (pkg-desc) | ||
| 62 | "Byte-compile installed package PKG-DESC. | ||
| 63 | This assumes that `pkg-desc' has already been activated with | ||
| 64 | `package-activate-1'." | ||
| 65 | (let ((byte-compile-ignore-files (package--parse-elpaignore pkg-desc)) | ||
| 66 | (warning-minimum-level :error) | ||
| 67 | (load-path load-path)) | ||
| 68 | (byte-recompile-directory (package-desc-dir pkg-desc) 0 t))) | ||
| 69 | |||
| 70 | (defun package--native-compile-async (pkg-desc) | ||
| 71 | "Native compile installed package PKG-DESC asynchronously. | ||
| 72 | This assumes that `pkg-desc' has already been activated with | ||
| 73 | `package-activate-1'." | ||
| 74 | (when (native-comp-available-p) | ||
| 75 | (let ((warning-minimum-level :error)) | ||
| 76 | (native-compile-async (package-desc-dir pkg-desc) t)))) | ||
| 77 | |||
| 78 | |||
| 79 | |||
| 80 | ;;;###autoload | ||
| 81 | (defun package-recompile (pkg) | ||
| 82 | "Byte-compile package PKG again. | ||
| 83 | PKG should be either a symbol, the package name, or a `package-desc' | ||
| 84 | object." | ||
| 85 | (interactive (list (intern (completing-read | ||
| 86 | "Recompile package: " | ||
| 87 | (mapcar #'symbol-name | ||
| 88 | (mapcar #'car package-alist)))))) | ||
| 89 | (let ((pkg-desc (if (package-desc-p pkg) | ||
| 90 | pkg | ||
| 91 | (cadr (assq pkg package-alist))))) | ||
| 92 | ;; Delete the old .elc files to ensure that we don't inadvertently | ||
| 93 | ;; load them (in case they contain byte code/macros that are now | ||
| 94 | ;; invalid). | ||
| 95 | (dolist (elc (directory-files-recursively | ||
| 96 | (package-desc-dir pkg-desc) "\\.elc\\'")) | ||
| 97 | (delete-file elc)) | ||
| 98 | (package--compile pkg-desc))) | ||
| 99 | |||
| 100 | ;;;###autoload | ||
| 101 | (defun package-recompile-all () | ||
| 102 | "Byte-compile all installed packages. | ||
| 103 | This is meant to be used only in the case the byte-compiled files | ||
| 104 | are invalid due to changed byte-code, macros or the like." | ||
| 105 | (interactive) | ||
| 106 | (pcase-dolist (`(_ ,pkg-desc) package-alist) | ||
| 107 | (with-demoted-errors "Error while recompiling: %S" | ||
| 108 | (package-recompile pkg-desc)))) | ||
| 109 | |||
| 110 | (provide 'package-compile) | ||
| 111 | ;;; package-compile.el ends here | ||