Skip to content
This repository was archived by the owner on Aug 23, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,69 @@ such cases, use the `:no-require` keyword, which implies `:defer`:
(message "This is evaluated when `foo' is loaded"))
```

### Byte-compiling with `package.el`

For general discussion on `package.el`, please first read the "For
package.el users" section.

If you would like to byte-compile your init file, and in the
byte-compiled version would like to avoid the `package-initialize`
call (which is quite expensive), then you can use the
`use-package-with-elpa` helper function.

A fully working `.emacs` example:
```elisp
(setq package-user-dir "~/my-new-elpa-dir"
package-archives '(("melpa" . "http://melpa.milkbox.net/packages/")
("gnu" . "http://elpa.gnu.org/packages/")))

;; Install use-package if not yet installed.
(eval-when-compile
(package-initialize)
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package)))

(use-package-with-elpa)

(use-package bind-key)
(use-package diminish)

(use-package magit
:bind ("C-c s" . magit-status))

(use-package yaml-mode
:mode ("\\.yaml\\'"))
```

The `use-package-with-elpa` call provides the following functionality
in case of an interpreted init file:

- `use-package-always-ensure` is set to `t`,
- `use-package-verbose` logging is enabled.

These settings together with the `eval-when-compile` initialization
block mean that you can just start Emacs with the init file above.
Even if your elpa directory is completely empty, everything will be
installed automatically with dependencies.

Byte compilation of your init file can be done with a command like this:
```
rm -f ~/.emacs.elc; emacs -Q --batch -l ~/.emacs -f batch-byte-compile ~/.emacs
```

Once your init file is byte-compiled, this configuration provides the
following functionality:

- `package.el` initialization is completely disabled,
- the `load-path` variable is set the same way as it was in the
interpreted init file,
- `use-package-verbose` is set to nil.

Using `use-package` this way together with `package.el` provides very
quick startup times even with a lot of packages, once your init file
is byte-compiled.

## Extending the load-path

If your package needs a directory added to the `load-path` in order to load,
Expand Down
36 changes: 36 additions & 0 deletions use-package.el
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,42 @@ This is in contrast to merely setting it to 0."

(font-lock-add-keywords 'emacs-lisp-mode use-package-font-lock-keywords)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Little bit opinionated helper function for package.el users
;;

;;;###autoload
(defmacro use-package-with-elpa ()
"Set up use-package to optimal usage with package.el.

For full documentation on the meaning and usage of this, please
consult the README file that came with this file at the section
called `Byte-compiling with Package.el'."
'(progn
;; Disable package initialize after us. We either initialize it
;; anyway in case of interpreted .emacs, or we don't want slow
;; initizlization in case of byte-compiled .emacs.elc.
(setq package-enable-at-startup nil)
;; Set use-package-verbose to t for interpreted .emacs,
;; and to nil for byte-compiled .emacs.elc.
(eval-and-compile
(setq use-package-verbose (not (bound-and-true-p byte-compile-current-file))))
;; Add the macro generated list of package.el loadpaths to load-path.
(mapc (lambda (add) (add-to-list 'load-path add))
(eval-when-compile
(setq use-package-always-ensure t)
(let ((package-user-dir-real (file-truename package-user-dir)))
;; The reverse is necessary, because outside we mapc
;; add-to-list element-by-element, which reverses.
(nreverse (apply #'nconc
;; Only keep package.el provided loadpaths.
(mapcar (lambda (path)
(if (string-prefix-p package-user-dir-real path)
(list path)
nil))
load-path))))))))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Keyword processing
Expand Down