2022-09-12 18:05:14 +02:00
|
|
|
;;; early-init.el --- Doom's universal bootstrapper -*- lexical-binding: t -*-
|
2022-06-18 15:04:12 +02:00
|
|
|
;;; Commentary:
|
|
|
|
;;
|
2022-09-12 18:05:14 +02:00
|
|
|
;; early-init.el was introduced in Emacs 27.1 and is loaded before init.el, and
|
|
|
|
;; before Emacs initializes its UI or package.el, and before site files are
|
|
|
|
;; loaded. This is good place for startup optimizating, because only here can
|
|
|
|
;; you *prevent* things from loading, rather than turn them off after-the-fact.
|
|
|
|
;; As such, Doom does all its initializing here.
|
2022-06-18 15:04:12 +02:00
|
|
|
;;
|
2022-09-12 18:05:14 +02:00
|
|
|
;; This file is Doom's "universal bootstrapper" for both interactive and
|
|
|
|
;; non-interactive sessions. It's also the heart of its profile bootloader,
|
|
|
|
;; which allows you to switch between Emacs configs on demand using
|
|
|
|
;; `--init-directory DIR' (which was backported from Emacs 29) or `--profile
|
|
|
|
;; NAME` (more about profiles at `https://docs.doomemacs.org/-/developers' or
|
|
|
|
;; docs/developers.org).
|
2022-07-27 12:06:07 +02:00
|
|
|
;;
|
2022-09-12 18:05:14 +02:00
|
|
|
;; In summary, this file is responsible for:
|
|
|
|
;; - Setting up some universal startup optimizations.
|
|
|
|
;; - Determining where `user-emacs-directory' is from one of:
|
|
|
|
;; - `--init-directory DIR' (backported from 29)
|
|
|
|
;; - `--profile PROFILENAME'
|
|
|
|
;; - Do one of the following:
|
|
|
|
;; - Load `doom' and one of `doom-start' or `doom-cli'.
|
|
|
|
;; - Or (if the user is trying to load a non-Doom config) load
|
|
|
|
;; `user-emacs-directory'/early-init.el.
|
2022-06-18 15:04:12 +02:00
|
|
|
;;
|
|
|
|
;;; Code:
|
2018-03-28 00:41:57 -04:00
|
|
|
|
2022-09-06 21:01:46 +02:00
|
|
|
;; PERF: Garbage collection is a big contributor to startup times. This fends it
|
2022-09-12 18:05:14 +02:00
|
|
|
;; off, but will be reset later by `gcmh-mode'. Not resetting it later will
|
2022-09-06 21:01:46 +02:00
|
|
|
;; cause stuttering/freezes.
|
2019-07-21 03:01:15 +02:00
|
|
|
(setq gc-cons-threshold most-positive-fixnum)
|
2018-09-19 00:25:17 +01:00
|
|
|
|
2022-09-13 13:08:37 +02:00
|
|
|
;; PERF: Don't use precious startup time checking mtime on elisp bytecode.
|
|
|
|
;; Ensuring correctness is 'doom sync's job, not the interactive session's.
|
|
|
|
;; Still, stale byte-code will cause *heavy* losses in startup efficiency.
|
|
|
|
(setq load-prefer-newer noninteractive)
|
2022-06-18 15:04:12 +02:00
|
|
|
|
2022-09-17 20:07:51 +02:00
|
|
|
;; UX: Respect DEBUG envvar as an alternative to --debug-init, and to make are
|
|
|
|
;; startup sufficiently verbose from this point on.
|
|
|
|
(when (getenv-internal "DEBUG")
|
|
|
|
(setq init-file-debug t
|
|
|
|
debug-on-error t))
|
|
|
|
|
2022-07-27 11:15:30 +02:00
|
|
|
|
2022-07-27 12:05:56 +02:00
|
|
|
;;
|
|
|
|
;;; Bootstrap
|
2022-07-27 11:15:30 +02:00
|
|
|
|
2022-09-13 13:08:37 +02:00
|
|
|
(or
|
|
|
|
;; PERF: `file-name-handler-alist' is consulted often. Unsetting it offers a
|
2022-09-17 14:19:46 +02:00
|
|
|
;; notable saving in startup time. This let-binding is just a stopgap though,
|
|
|
|
;; a more complete version of this optimization can be found in lisp/doom.el.
|
2022-09-13 13:08:37 +02:00
|
|
|
(let (file-name-handler-alist)
|
|
|
|
;; FEAT: First, we process --init-directory and --profile to detect what
|
|
|
|
;; `user-emacs-directory' to load from. I avoid using
|
|
|
|
;; `command-switch-alist' to process --profile and --init-directory because
|
|
|
|
;; it is processed too late to change `user-emacs-directory' in time.
|
|
|
|
;; REVIEW: Backported from Emacs 29. Remove when 28 support is dropped.
|
|
|
|
(let ((initdir (or (cadr (member "--init-directory" command-line-args))
|
|
|
|
(getenv-internal "EMACSDIR"))))
|
2022-09-17 15:24:20 +02:00
|
|
|
(if (null initdir)
|
|
|
|
;; FIX: If we've been loaded directly (via 'emacs -batch -l
|
|
|
|
;; early-init.el') or by a doomscript (like bin/doom), and Doom is
|
|
|
|
;; in a non-standard location (and/or Chemacs is used), then
|
|
|
|
;; `user-emacs-directory' will be wrong.
|
|
|
|
(when noninteractive
|
|
|
|
(setq user-emacs-directory
|
|
|
|
(file-name-directory (file-truename load-file-name))))
|
2022-09-13 13:08:37 +02:00
|
|
|
;; FIX: Discard the switch to prevent "invalid option" errors later.
|
|
|
|
(push (cons "--init-directory" (lambda (_) (pop argv))) command-switch-alist)
|
|
|
|
(setq user-emacs-directory (expand-file-name initdir))))
|
|
|
|
;; Initialize a known profile, if requested.
|
|
|
|
(let ((profile (or (cadr (member "--profile" command-line-args))
|
|
|
|
(getenv-internal "DOOMPROFILE"))))
|
|
|
|
(when profile
|
|
|
|
;; FIX: Discard the switch to prevent "invalid option" errors later.
|
|
|
|
(push (cons "--profile" (lambda (_) (pop argv))) command-switch-alist)
|
refactor!: complete profile gen and init systems
BREAKING CHANGE: This commit makes three breaking changes:
- Doom now fully and dynamically generates (and byte-compiles) your
profile and its init files, which includes your autoloads, loading
your init files and modules, and then some. This replaces
doom-initialize-modules, doom-initialize-core-modules, and
doom-module-loader, which have been removed. This has also improved
startup time by a bit, but if you use these functions in your CLIs,
for instance, this will be a breaking change.
- `doom sync` is now required for Doom to see your profiles (and must be
run whenever you change them, or when you up/downgrade Emacs across
major versions).
- $DOOMDIR/init.el is now read much earlier than it used to be. Before
any of doom-{ui,keybinds,editor,projects}, before any autoloads are
loaded, and before your load-path has been populated with your
packages. It now runs in the context of early-init.el, giving users
freer range over what they can affect, but a more minimalistic
environment to do it in.
If you must have some logic run when all that is set up, add it to one
of the module hooks added in e08f68b or 283308a.
This also poses a significant change to Doom's load order (see the
commentary change in lib/doom.el), along with the following (non
breaking) changes:
1. Adds a new `doom profiles sync` command. This will forcibly resync
your profiles, while `doom sync` will only do so if your profiles
have changed.
2. Doom now fully and dynamically generates (and byte-compiles) your
user-init-file, which includes loading all your init files, modules,
and custom-file. This replaces the job of doom-initialize-modules,
doom-initialize-core-modules, and doom-module-loader, which have been
removed. This has also improved startup time by a bit.
3. Defines new doom-state-dir variable, though not used yet (saving that
and the other breaking changes for the 3.0 release).
4. Redesigns profile directory variables (doom-profile-*-dir) to prepare
for future XDG-compliance.
5. Removed unused/unimportant profile variables in doom.el.
6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's
enough to power the system as it is now.
7. Updates the "load order" commentary in doom.el to reflect these
changes.
2022-09-15 18:53:06 +02:00
|
|
|
;; Running 'doom sync' will (re)generate a lightweight profile
|
|
|
|
;; bootstrapper in $EMACSDIR/profiles/init.el, after reading
|
|
|
|
;; $EMACSDIR/profiles.el, $DOOMDIR/profiles,
|
|
|
|
;; $XDG_CONFIG_HOME/doom-profiles.el, and ~/.doom-profiles.el. All it
|
|
|
|
;; needs is for `$DOOMPROFILE' to be set.
|
|
|
|
(setenv "DOOMPROFILE" profile)
|
2022-09-17 20:21:43 +02:00
|
|
|
(or (load (expand-file-name (format "profiles/init.%d.elc" emacs-major-version)
|
refactor!: complete profile gen and init systems
BREAKING CHANGE: This commit makes three breaking changes:
- Doom now fully and dynamically generates (and byte-compiles) your
profile and its init files, which includes your autoloads, loading
your init files and modules, and then some. This replaces
doom-initialize-modules, doom-initialize-core-modules, and
doom-module-loader, which have been removed. This has also improved
startup time by a bit, but if you use these functions in your CLIs,
for instance, this will be a breaking change.
- `doom sync` is now required for Doom to see your profiles (and must be
run whenever you change them, or when you up/downgrade Emacs across
major versions).
- $DOOMDIR/init.el is now read much earlier than it used to be. Before
any of doom-{ui,keybinds,editor,projects}, before any autoloads are
loaded, and before your load-path has been populated with your
packages. It now runs in the context of early-init.el, giving users
freer range over what they can affect, but a more minimalistic
environment to do it in.
If you must have some logic run when all that is set up, add it to one
of the module hooks added in e08f68b or 283308a.
This also poses a significant change to Doom's load order (see the
commentary change in lib/doom.el), along with the following (non
breaking) changes:
1. Adds a new `doom profiles sync` command. This will forcibly resync
your profiles, while `doom sync` will only do so if your profiles
have changed.
2. Doom now fully and dynamically generates (and byte-compiles) your
user-init-file, which includes loading all your init files, modules,
and custom-file. This replaces the job of doom-initialize-modules,
doom-initialize-core-modules, and doom-module-loader, which have been
removed. This has also improved startup time by a bit.
3. Defines new doom-state-dir variable, though not used yet (saving that
and the other breaking changes for the 3.0 release).
4. Redesigns profile directory variables (doom-profile-*-dir) to prepare
for future XDG-compliance.
5. Removed unused/unimportant profile variables in doom.el.
6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's
enough to power the system as it is now.
7. Updates the "load order" commentary in doom.el to reflect these
changes.
2022-09-15 18:53:06 +02:00
|
|
|
user-emacs-directory)
|
2022-09-17 20:21:43 +02:00
|
|
|
'noerror (not init-file-debug) 'nosuffix)
|
refactor!: complete profile gen and init systems
BREAKING CHANGE: This commit makes three breaking changes:
- Doom now fully and dynamically generates (and byte-compiles) your
profile and its init files, which includes your autoloads, loading
your init files and modules, and then some. This replaces
doom-initialize-modules, doom-initialize-core-modules, and
doom-module-loader, which have been removed. This has also improved
startup time by a bit, but if you use these functions in your CLIs,
for instance, this will be a breaking change.
- `doom sync` is now required for Doom to see your profiles (and must be
run whenever you change them, or when you up/downgrade Emacs across
major versions).
- $DOOMDIR/init.el is now read much earlier than it used to be. Before
any of doom-{ui,keybinds,editor,projects}, before any autoloads are
loaded, and before your load-path has been populated with your
packages. It now runs in the context of early-init.el, giving users
freer range over what they can affect, but a more minimalistic
environment to do it in.
If you must have some logic run when all that is set up, add it to one
of the module hooks added in e08f68b or 283308a.
This also poses a significant change to Doom's load order (see the
commentary change in lib/doom.el), along with the following (non
breaking) changes:
1. Adds a new `doom profiles sync` command. This will forcibly resync
your profiles, while `doom sync` will only do so if your profiles
have changed.
2. Doom now fully and dynamically generates (and byte-compiles) your
user-init-file, which includes loading all your init files, modules,
and custom-file. This replaces the job of doom-initialize-modules,
doom-initialize-core-modules, and doom-module-loader, which have been
removed. This has also improved startup time by a bit.
3. Defines new doom-state-dir variable, though not used yet (saving that
and the other breaking changes for the 3.0 release).
4. Redesigns profile directory variables (doom-profile-*-dir) to prepare
for future XDG-compliance.
5. Removed unused/unimportant profile variables in doom.el.
6. Added lisp/doom-profiles.el. It's hardly feature complete, but it's
enough to power the system as it is now.
7. Updates the "load order" commentary in doom.el to reflect these
changes.
2022-09-15 18:53:06 +02:00
|
|
|
(user-error "Profiles not initialized yet; run 'doom sync' first"))))
|
2022-09-13 13:08:37 +02:00
|
|
|
|
|
|
|
;; PERF: When `load'ing or `require'ing files, each permutation of
|
|
|
|
;; `load-suffixes' and `load-file-rep-suffixes' (then `load-suffixes' +
|
|
|
|
;; `load-file-rep-suffixes') is used to locate the file. Each permutation
|
|
|
|
;; is a file op, which is normally very fast, but they can add up over the
|
|
|
|
;; hundreds/thousands of files Emacs needs to load.
|
|
|
|
;;
|
|
|
|
;; To reduce that burden -- and since Doom doesn't load any dynamic modules
|
|
|
|
;; -- I remove `.so' from `load-suffixes' and pass the `must-suffix' arg to
|
|
|
|
;; `load'. See the docs of `load' for details.
|
2022-09-16 11:51:19 +02:00
|
|
|
(if (let ((load-suffixes '(".elc" ".el")))
|
2022-09-13 13:08:37 +02:00
|
|
|
;; Load the heart of Doom Emacs.
|
2022-09-16 11:51:19 +02:00
|
|
|
(load (expand-file-name "lisp/doom" user-emacs-directory)
|
2022-09-17 20:07:51 +02:00
|
|
|
'noerror (not init-file-debug) nil 'must-suffix))
|
2022-09-16 11:51:19 +02:00
|
|
|
;; ...and prepare for the rest of the session.
|
|
|
|
(doom-require (if noninteractive 'doom-cli 'doom-start))
|
|
|
|
;; Failing that, assume we're loading a non-Doom config and prepare.
|
|
|
|
(setq user-init-file (expand-file-name "early-init" user-emacs-directory)
|
|
|
|
;; I make no assumptions about the config we're about to load, so
|
|
|
|
;; to limit side-effects, undo any leftover optimizations:
|
|
|
|
load-prefer-newer t)
|
|
|
|
nil))
|
2022-09-13 13:08:37 +02:00
|
|
|
|
|
|
|
;; Then continue on to the config/profile we want to load.
|
2022-09-17 20:07:51 +02:00
|
|
|
(load early-init-file 'noerror (not init-file-debug) nil 'must-suffix))
|
2022-06-18 15:04:12 +02:00
|
|
|
|
|
|
|
;;; early-init.el ends here
|