How to Share Your Emacs Configuration Between Different Machines (and Architectures) with Native Compilation

Cover Image for How to Share Your Emacs Configuration Between Different Machines (and Architectures) with Native Compilation
Rahul M. Juliato
Rahul M. Juliato
#emacs#native-compilation# configuration

How to Share Your Emacs Configuration Between Different Machines (and Architectures) with Native Compilation

If you use Emacs on multiple machines, especially ones running different architectures or operating systems, sharing your Emacs configuration across those machines can become tricky. Add native compilation (introduced in Emacs 28) to the mix, and you might run into conflicts when Emacs tries to reuse compiled .eln files between machines.

Fortunately, with a bit of smart configuration, you can make Emacs share your configuration while keeping native compilation enabled for each machine. In this post, I'll show you how to set up your Emacs so that native compilation caches (.eln files) are kept separate for each machine. We'll also discuss why this is important and what your directory structure will look like.

Why Is This Important?

Emacs uses native compilation to compile Elisp files into optimized .eln binaries, which are architecture and system-dependent. If you share your Emacs configuration across machines without accounting for this, you may encounter issues:

  1. Conflicting .eln files: A .eln file compiled for a Linux machine might not work on a macOS machine.

  2. Unnecessary recompilations: Emacs may attempt to recompile packages on each startup, which can slow things down and clutter your eln-cache directory.

By separating the native compilation cache for each machine, you ensure:

• Faster startup times since Emacs doesn't recompile already-compiled code.

• A cleaner and more predictable setup across machines.

The Solution: Machine-Specific eln-cache Directories

To keep .eln files organized and avoid conflicts, you can configure Emacs to use a machine-specific eln-cache directory. Here's the configuration snippet to add into your early-init.el:

;;; Native Compile Settings
;; I use a <emacs-default-dir>/eln-cache-<machine-hostname>/ dir to store
;; my different machines' eln compiled code. This allows the same config
;; to be used on several machines without conflicts.
;; This is added in early-init.el to prevent unwanted recompilations.

(when (featurep 'native-compile)
  ;; Set the right directory to store the native compilation cache
  (let ((path (expand-file-name (concat "eln-cache-" (system-name) "/") user-emacs-directory)))
	(setq-default native-comp-eln-load-path       (list path)
				  native-compile-target-directory path)
	(startup-redirect-eln-cache path))

  (setq-default native-comp-async-report-warnings-errors nil  ;; Silence compiler warnings as they can be disruptive
				native-comp-jit-compilation              t    ;; Enable async native compilation
				package-native-compile                   t))) ;; Compile installed packages

What Does This Code Do?

  1. (system-name): Retrieves the hostname of the machine. This is used to create a unique directory for each machine's eln-cache.

  2. expand-file-name: Combines the Emacs configuration directory (user-emacs-directory) with the machine-specific eln-cache-<hostname> folder.

  3. native-comp-eln-load-path and native-compile-target-directory: Set the paths for Emacs to store and load the compiled .eln files.

  4. startup-redirect-eln-cache: Ensures Emacs uses the specified eln-cache directory right from startup.

Optional settings:

native-comp-async-report-warnings-errors: Silences disruptive compiler warnings.

native-comp-jit-compilation: Enables Just-In-Time (JIT) native compilation for faster execution.

package-native-compile: Ensures all installed packages are natively compiled.

By placing this in your early-init.el, you make sure Emacs sets up the eln-cache directory before it starts loading packages or recompiling files.

Folder Structure Example

Let's say you have two machines, with the following hostnames:

debian: A Linux workstation.

macbook: A macOS laptop.

With the above configuration, your Emacs directory structure will look like this:

~/.emacs.d/
|-- early-init.el
|-- init.el
|-- eln-cache-debian/          # Cache for 'debian'
|   |-- abcdef01-abcdefgh01.eln
|   |-- xyz12345-xyzabc123.eln
|
|-- eln-cache-macbook/         # Cache for 'macbook'
	|-- abcdef01-abcdefgh01.eln
	|-- pqr67890-pqrxyz678.eln

Setting Up for a New Machine

If you're setting up Emacs on a new machine:

  1. Clone or copy your shared Emacs configuration (e.g., from GitHub).

  2. Make sure the above snippet is in your early-init.el.

  3. Start Emacs. It will automatically create a new eln-cache-<hostname> directory and begin compiling packages natively for the current machine.

Conclusion

Sharing Emacs configurations across machines doesn't have to be a hassle, even when using native compilation. By directing Emacs to use machine-specific eln-cache directories, you can:

• Avoid conflicts caused by incompatible .eln files.

• Speed up startup times by preventing unnecessary recompilations.

• Maintain a clean and organized Emacs setup.

I hope with the provided configuration, you can easily manage Emacs on multiple machines—whether you're switching between Linux, macOS, or different hardware architectures.

Happy hacking!