This introduces a depth field for modules so that they may dictate their
load order explicitly, it also treats depths <= -100 or >= 100 as
special depths, which will be loaded early, before their respective
doom-{before,after}-module-{init,config}-hook. This permits psuedo
modules like :core and :user modules to be treated as normal modules
without too many special cases.
This also fixes a module load order issue on Emacs 29 (#6813), caused by
emacs-mirror/emacs@4311bd0bd7, which changed the return value order of
hash-table-{keys,values} causing modules to be loaded in reverse order;
resulting in the loss of evil keybinds, among other things.
Other notable changes:
- Changes the data structure for module data caches from a list to a
vector. Uses less memory and permits faster lookups. Also adds two
depth fields to the front of it.
- Changes the signature of doom-module-list and doom-package-list.
- Renames doom--read-packages -> doom-packages--read for consistency
with naming convention.
- Add doom-module-depth function.
- Adds a temporary doom-core-dir/init.el file, which is responsible for
loading doom-*.el.
Fix: #6813
Ref: emacs-mirror/emacs@4311bd0bd7
An unintended change snuck into 2c14eff. The :core and :user virtual
modules are no longer stripped from the module list before iterating
through (and loading) them. This meant that Doom would load these two
like regular modules (and first, since these two are always at the start
of the list).
This is harmless for :core, because it has no init.el or config.el, but
:user does! This means $DOOMDIR/{init,config}.el would be loaded
twice (once before all other modules and again afterwards), causing load
order issues (like #6818).
Fix: #6818
Amend: 2c14eff7f1
- Batch more variables in Doom's autoloads files.
- Remove all the register-definition-prefixes calls generated in
autoloads files (for both modules' and packages' autoloads). These
don't serve much purpose, and only incur added cost growing a large
hash table.
To understand this issue, you have to understand these two things:
1. Doom builds an init file which combines all its autoloads (for
packages and modules), and Doom's bootstrapper (which loads modules,
$DOOMDIR, etc). This init file is byte-compiled.
2. When Emacs byte-compiles elisp, docstrings are lazy-loaded (by
embedding them in the elc as commented text to be retrieved later).
This is generally done to save on memory.
Now the issue: when these lazy-loaded docstrings are retrieved, Emacs
may evaluate the whole file to find it, including Doom's bootstrap
process, reloading all its files, the user's config files, and running
all its startup hooks. Not only is this terribly expensive, reloading
these files may have disastrous effects.
One such effect is compounded by Marginalia, which invokes this
docstring fetch process (by calling the `documentation` function in
`marginalia--function-doc`) for *each* symbol in the `M-x` or `C-h
{v,f}` completion lists, which means Doom re-bootstraps multiple times
and rapidly, causing Emacs to totally lock up.
The solution is to simply gate the expensive part of the initfile so it
doesn't run more than once, at startup, and when `doom/reload` is
called. The rest of the file loads instantly.
Still, this is a bit flimsy. I'll think of a more elegant solution
later.
- Adds $DOOMPROFILELOADFILE: Controls where to read and write the
profile loader. Changing this may be helpful for users on nix/guix,
who have deployed Doom to a read-only location. This sets
`doom-profile-load-file`.
- Changed profile load file's default location (used to be
$EMACSDIR/profiles/init.el, is now $EMACSDIR/profiles/load.el). The
gitignore was updated to reflect this.
- Adds $DOOMPROFILELOADPATH: A colon-delimited list of profile config
files and directories (semi-colon on Windows) which dictate what Doom
reads in order to discover your profiles. Config files are required to
have an *.el extension. This sets `doom-profile-load-path`.
- Changes the nomenclature around this loader script. I used to refer to
it as the profile bootstrapper. I'll now refer to it as the profile
load file, and I've renamed `doom-profiles-bootstrap-file` to
`doom-profile-load-file` to reflect this.
- The variables `doom-profile-dirs` and `doom-profile-config-files` were
merged into doom-profile-load-path.
- Both envvars have also been documented in `doom help` (and
$DOOMPROFILE's has been updated).
Ref: #6794
- Swap out the funcall+alist lookup for a pcase (which is expanded to a
cond, which is is faster and easier to read).
- Wrap bootstrap file to $EMACSDIR/profiles/init.el, but byte-compile it
to $EMACSDIR/profiles/init.X.el where X is emacs-major-version.
- Make doom-profiles-save's second argument optional (defaults to
doom-profiles-bootstrap-file).
- Make doom-profiles-save throw a error if byte-compilation fails for
some reason.
- Rename the tempvars to include 'doom' in their name, so debuggers know
where they originate.
The profile bootstrap file's first form is the doom-version it was
generated with. If this has changed, it should be considered outdated,
even if the user's profiles haven't changed.
If Doom doesn't live in ~/.emacs.d or ~/.config/emacs, then it cannot
play the role of bootloader, so opt out of generating the profile
bootstrappper in this case.
That said, don't disable the profile system entirely; it can still be
useful for internal, noninteractive, and sandbox use.
So that the resulting file expands to less code and doesn't apply too
magic to file paths (it may be unwanted).
And don't try to unintern a lexical binding.
Fixes two issues with implicit profiles:
1. Where user-emacs-directory (and sometimes doom-user-dir) would be
unexpanded in the profile init file (generated by 'doom profiles
sync'), which would be ineffective at runtime.
2. Where an implicit profile with a .doomprofile that lacks a
user-emacs-directory setting would not have any user-emacs-directory
set for it at all. Instead, it should fall back to that profile's
location.
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.