1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
;;; package-quickstart.el --- Accelerating Package Startup -*- lexical-binding: t; -*-
;; Copyright (C) 2025 Philip Kaludercic
;; Author: Philip Kaludercic <philipk@posteo.net>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Activating packages via `package-initialize' is costly: for N installed
;; packages, it needs to read all N <pkg>-pkg.el files first to decide
;; which packages to activate, and then again N <pkg>-autoloads.el files.
;; To speed this up, we precompute a mega-autoloads file which is the
;; concatenation of all those <pkg>-autoloads.el, so we can activate
;; all packages by loading this one file (and hence without initializing
;; package.el).
;; Other than speeding things up, this also offers a bootstrap feature:
;; it lets us activate packages according to `package-load-list' and
;; `package-user-dir' even before those vars are set.
;;; Code:
(require 'package-core)
(defcustom package-quickstart nil
"Precompute activation actions to speed up startup.
This requires the use of `package-quickstart-refresh' every time the
activations need to be changed, such as when `package-load-list' is modified."
:type 'boolean
:version "27.1"
:group 'package)
;;;###autoload
(defcustom package-quickstart-file
(locate-user-emacs-file "package-quickstart.el")
"Location of the file used to speed up activation of packages at startup."
:type 'file
:group 'applications
:initialize #'custom-initialize-delay
:version "27.1")
(defun package--quickstart-maybe-refresh ()
(if package-quickstart
;; FIXME: Delay refresh in case we're installing/deleting
;; several packages!
(package-quickstart-refresh)
(delete-file (concat package-quickstart-file "c"))
(delete-file package-quickstart-file)))
(defvar package--quickstart-dir nil
"Set by `package-quickstart-file' to the directory containing it.")
(defun package--quickstart-rel (file)
"Return an expr depending on `package--quickstart-dir' which evaluates to FILE.
If FILE is in `package--quickstart-dir', returns an expression that is
relative to that directory, so if that directory is moved we can still
find FILE."
(if (file-in-directory-p file package--quickstart-dir)
`(file-name-concat package--quickstart-dir ,(file-relative-name file package--quickstart-dir))
file))
(defun package-quickstart-refresh ()
"(Re)Generate the `package-quickstart-file'."
(interactive)
(package-initialize 'no-activate)
(require 'info)
(let ((package--quickstart-pkgs ())
;; Pretend we haven't activated anything yet!
(package-activated-list ())
;; Make sure we can load this file without load-source-file-function.
(coding-system-for-write 'emacs-internal)
;; Ensure that `pp' and `prin1-to-string' calls further down
;; aren't truncated.
(print-length nil)
(print-level nil)
(Info-directory-list '(""))
(package--quickstart-dir nil))
(dolist (elt package-alist)
(condition-case err
(package-activate (car elt))
;; Don't let failure of activation of a package arbitrarily stop
;; activation of further packages.
(error (message "%s" (error-message-string err)))))
(setq package--quickstart-pkgs (nreverse package--quickstart-pkgs))
(with-temp-file package-quickstart-file
(emacs-lisp-mode) ;For `syntax-ppss'.
(insert ";;; Quickstart file to activate all packages at startup -*- lexical-binding:t -*-\n")
(insert ";; ¡¡ This file is autogenerated by `package-quickstart-refresh', DO NOT EDIT !!\n\n")
(setq package--quickstart-dir
(file-name-directory (expand-file-name package-quickstart-file)))
(pp '(setq package--quickstart-dir
(file-name-directory (expand-file-name load-file-name)))
(current-buffer))
(dolist (pkg package--quickstart-pkgs)
(let* ((file
;; Prefer uncompiled files (and don't accept .so files).
(let ((load-suffixes '(".el" ".elc")))
(locate-library (package--autoloads-file-name pkg))))
(pfile (prin1-to-string (package--quickstart-rel file))))
(insert "(let* ((load-file-name " pfile ")\
\(load-true-file-name load-file-name))\n")
(insert-file-contents file)
;; Fixup the special #$ reader form and throw away comments.
(while (re-search-forward "#\\$\\|^;\\(.*\n\\)" nil 'move)
(unless (ppss-string-terminator (save-match-data (syntax-ppss)))
(replace-match (if (match-end 1) "" pfile) t t)))
(unless (bolp) (insert "\n"))
(insert ")\n")))
(pp `(defvar package-activated-list) (current-buffer))
(pp `(setq package-activated-list
(delete-dups
(append ',(mapcar #'package-desc-name package--quickstart-pkgs)
package-activated-list)))
(current-buffer))
(let ((info-dirs
(mapcar #'package--quickstart-rel (butlast Info-directory-list))))
(when info-dirs
(pp `(progn (require 'info)
(info-initialize)
(setq Info-directory-list
(append (list . ,info-dirs) Info-directory-list)))
(current-buffer))))
;; Use `\s' instead of a space character, so this code chunk is not
;; mistaken for an actual file-local section of package.el.
(insert "
;; Local\sVariables:
;; version-control: never
;; no-update-autoloads: t
;; byte-compile-warnings: (not make-local)
;; End:
"))
;; FIXME: Do it asynchronously in an Emacs subprocess, and
;; don't show the byte-compiler warnings.
(byte-compile-file package-quickstart-file)))
(provide 'package-quickstart)
;;; package-quickstart.el ends here
|