This article essentially describes the top of my Emacs init file. That part of the code is devoted to modify the session bootstrap process, that is, some things that are normally done very early. It mostly deals with the package infrastructure but also contains a couple of other tricks that some people may consider useful. It goes like this…

The first line is self-explanatory (and please, be warned that I will discard any comment about it. You know why).

(require 'cl)

Platform-specific tweaks

A self-contained Emacs.app on MacOS X has its own site-lisp directory, but I want to make sure that the standard Unix one is here as well, and takes precedence.

(when (featurep 'ns)
  (add-to-list 'load-path "/usr/local/share/emacs/site-lisp"))

Updated When /not/ starting Emacs from the command-line (e.g. MacOS X app clicks or Quicksilver/Alfred, Unitiy launcher on Ubuntu etc.), I don't necessarily get my environment-based exec-path which can be problematic (e.g. for finding auxiliary programs such as movemail, gpg etc.). Emacs used to store the build-time value of exec-path in the custom's standard-value property, which was convenient for me because since I compile it myself, I could reuse that. This has changed however since this commit:

commit 2fc11b3fa3418e0e8a624376ea8bf4cbc70c2657
Author: Ludovic Courtès <ludo@gnu.org>
Date:   Mon Apr 20 17:44:23 2015 -0400

So now instead, I have patched it to save the build-time value in a new variable called BUILD-TIME-EXEC-PATH.

(when (boundp 'build-time-exec-path)
  (mapc (lambda (path) (setq exec-path (remove path exec-path)))
	build-time-exec-path)
  (setq exec-path (append build-time-exec-path exec-path)))

ELPA infrastructure

Initialize ELPA now so that the rest of the initialization process may rely on packages without having to go through after-init-hook.

(require 'package)

I want system-wide directories to be named emacs-packages instead of site-lisp/elpa.

(setq package-directory-list
      (let (result)
        (dolist (path load-path)
          (and (stringp path)
                 (equal (file-name-nondirectory path) "site-lisp")
                 (push (expand-file-name "emacs-packages"
                                                     (file-name-directory
                                                       (directory-file-name path)))
                          result)))
	(nreverse result)))

I want my local directory to follow the same convention.

(setq package-user-dir "~/.emacs.d/emacs-packages")

Now, it's okay to initialize ELPA.

(package-initialize)

Now that the packages have been initialized, I actually want ELPA to install in /usr/local/share/emacs/emacs-packages by default, and keep my local directory for manual installations. One simple way to achieve that is to set my local directory to /usr/local/share/emacs/emacs-packages and to remove that from the system-wide directory list. One small drawback of this is that my local path is gone, so any new package installed there won't be seen until the next restart. This is not much of a problem though.

(setq package-user-dir "/usr/local/share/emacs/emacs-packages"
        package-directory-list (remove "/usr/local/share/emacs/emacs-packages"
						     package-directory-list))

Site and local (non ELPA) packages infrastructure

The purpose of this other infrastructure is to support packages that would be installed manually, outside ELPA, and in a way similar to XEmacs packages. A packages directory has lisp/, etc/ and info/ subdirectories. Every package installs its stuff directly in etc/ and info/, but adds its own subdirectory to lisp/ and puts its code (including a potential autoloads file) in there.

This additional infrastructure comes in handy in several situations. For instance, having Slime (auto)loaded in your session now becomes as simple as this:

ln -s /path/to/slime /usr/local/share/emacs/local-packages/lisp/

(defun dvl-initialize-packages (directory)
  "Initialize non-ELPA packages DIRECTORY.
This means:
  - adding the whole lisp/ subtree to LOAD-PATH,
  - loading the autoload files found there.
  - adding DIRECTORY to INFO-DEFAULT-DIRECTORY-LIST."
  (let ((default-directory (expand-file-name "lisp" directory)))
    ;; 1. Update LOAD-PATH
    (setq load-path
	  (append
	   (let ((load-path (copy-sequence load-path)))
	     (append (copy-sequence (normal-top-level-add-to-load-path '(".")))
			  (normal-top-level-add-subdirs-to-load-path)))
	   load-path))
    ;; 2. Load autoload files
    (loop for directory in load-path
	    while (string-prefix-p default-directory directory)
	    do (mapc #'load (directory-files directory t "-autoloads\\.el$"))))
  ;; 3. Update the default Info directory list
  (add-to-list 'Info-default-directory-list
   (expand-file-name "info" directory)))

(require 'info)

Be sure to do this by increasing priority order.

(mapc #'dvl-initialize-packages
      `("/usr/local/share/emacs/local-packages"
	 "~/.emacs.d/local-packages"))

And now we can re-initialize Info with the proper defaults.

(setq Info-directory-list nil)
(info-initialize)

Custom settings

Now that we have bootstrapped the complete packages infrastructure, we can set the Custom file to something that makes sense and load it now.

(setq custom-file "~/.emacs.d/custom.el")
(load custom-file)

RC Files

Finally, install the rc files loader and we're done bootstrapping.

(rcfiles-register-rc-files)

That completes my session bootstrap process.