Home

Awesome

compile-angel.el - Speed up Emacs by Byte-compiling and Native-compiling all .el files

MELPA Build Status License

The compile-angel package automatically byte-compiles and native-compiles Emacs Lisp libraries. It offers:

The compile-angel modes speed up Emacs by ensuring all libraries are byte-compiled and native-compiled. Byte-compilation reduces the overhead of loading Emacs Lisp code at runtime, while native compilation optimizes performance by generating machine code specific to your system.

The compile-angel author was previously an auto-compile user but encountered an issue where several .el files were not being compiled by auto-compile (see the explanation below), resulting in Emacs performance degradation due to the lack of native compilation.

After extensive experimentation and research, the author developed compile-angel to address this problem. The compile-angel package guarantees that all .el files are both byte-compiled and native-compiled, which significantly speeds up Emacs.

<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->

Table of Contents

<!-- markdown-toc end -->

Why use compile-angel?

Because you are likely running a significant amount of interpreted, slow Elisp code that Emacs did not compile automatically. Ensuring that Elisp is native-compiled significantly improves Emacs' performance. Unfortunately, functions like package-install and package-recompile-all do not compile .el files that were not installed using package.el. Since these files are not byte-compiled, the Emacs JIT compiler does not native-compile them either, as a byte-compiled file signals the JIT compiler to perform native compilation. In contrast, compile-angel modes ensure that all loaded .el files are compiled transparently, regardless of whether they are part of a package.

Before installing

It is highly recommended to set the following variables at the very beginning of your early-init.el:

;; Ensure Emacs loads the most recent byte-compiled files.
(setq load-prefer-newer t)

;; Ensure JIT compilation is enabled for improved performance by
;; native-compiling loaded .elc files asynchronously
(setq native-comp-jit-compilation t)
(setq native-comp-deferred-compilation t) ; Deprecated in Emacs > 29.1

Additionally, ensure that native compilation is enabled:

This should return t: (native-comp-available-p)

Installation

Emacs

To install compile-angel on Emacs from MELPA:

  1. If you haven't already done so, add MELPA repository to your Emacs configuration.

  2. Add the following code at the very beginning of your init.el file, before all other packages:

(use-package compile-angel
  :ensure t
  :demand t
  :custom
  (compile-angel-verbose nil)
  :config
  (compile-angel-on-load-mode)
  (add-hook 'emacs-lisp-mode-hook #'compile-angel-on-save-local-mode))

Doom Emacs

Here is how to install compile-angel on Doom Emacs:

  1. Add to the ~/.doom.d/packages.el file:
(package! compile-angel)
  1. Add to the top of ~/.doom.d/config.el:
(setq compile-angel-predicate-function
      (lambda (file)
        (and (not (file-in-directory-p file doom-user-dir))
             (not (file-in-directory-p file (expand-file-name "lisp" doom-emacs-dir)))
             (not (file-in-directory-p file (expand-file-name doom-modules-dir))))))
(compile-angel-on-load-mode)
(add-hook 'emacs-lisp-mode-hook #'compile-angel-on-save-local-mode)

(This ensures that the Doom Emacs Lisp files and modules are not compiled by compile-angel. This is important because .el files in these directories should never be compiled, or Doom may fail to load some of them correctly.)

Frequently Asked Questions

What are some interesting Emacs customizations to consider alongside compile-angel?

Below are a few interesting options:

;; Ensure that quitting only occurs once Emacs finishes native compiling,
;; preventing incomplete or leftover compilation files in `/tmp`.
(setq native-comp-async-query-on-exit t)
(setq confirm-kill-processes t)

;; Show buffer when there is a warning.
;; (NOT RECOMMENDED, except during development).
(setq compile-angel-verbose t)
(setq warning-minimum-level :warning)
(setq byte-compile-verbose t)
(setq byte-compile-warnings t)
(setq native-comp-async-report-warnings-errors t)
(setq native-comp-warning-on-missing-source t)

;; Non-nil means to native compile packages as part of their installation.
(setq package-native-compile t)

How to exclude certain .el files from compilation in compile-angel

You can make compile-angel exclude specific .el files by adding regular expressions to compile-angel-excluded-files-regexps.

For instance, to prevent compile-angel from compiling .dir-config.el files (the dir-config package) and .dir-locals.el files, add the following to your configuration:

(setq compile-angel-excluded-files-regexps '("/\\.dir-config\\.el$"
                                             "/\\.dir-locals\\.el$"))

How to enable or disable byte-compilation and native-compilation?

You can control whether compile-angel performs byte-compilation or native-compilation of your .el files by setting the following variables in your configuration:

Example configuration:

;; Enable both byte-compilation and native-compilation (default)
(setq compile-angel-enable-byte-compile t)
(setq compile-angel-enable-native-compile t)

Why not just use the package-recompile-all function?

The package-recompile-all function is effective for recompiling files within packages, but it misses other files that are not part of a package.

In the compile-angel author's configuration, for example, package-recompile-all skipped most of the local packages loaded using use-package with :ensure nil or require. Additionally, package-recompile-all does not compile transparently; the user must manually run it and wait for it to complete.

The compile-angel package, on the other hand, transparently compiles all packages without any user intervention. The user simply needs to enable (compile-angel-on-load-mode).

What is the difference between auto-compile and compile-angel?

Jonas Bernouli, the author of auto-compile, has made some design decisions that prevent it from guaranteeing that all .el packages are byte-compiled and native-compiled. For example, if the user deletes all the .elc files or if the .el files have never been compiled before, auto-compile won't recompile them. Here is a quote from Jonas Bernouli, aka u/tarsius_, the auto-compile author (from this discussion):

Both [autocompile] modes only ever re-compile a source file when the respective byte code file already exists but is outdated. Otherwise they do not compile the source file. By "otherwise" I mean if:

This is one of the reasons why opening an issue or submitting a pull request regarding the auto-compile issue above is pointless, as Jonas Bernouli is unlikely to merge it due to his design decision.

Here are the main differences between compile-angel and auto-compile:

Author and License

The compile-angel Emacs package has been written by James Cherti and is distributed under terms of the GNU General Public License version 3, or, at your choice, any later version.

Copyright (C) 2024 James Cherti

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.

Links

Other Emacs packages by the same author: