How do I automatically (re)compile ELPA packages? - emacs

I'm now installing as much as I can through MELPA and Marmalade, and I manage my ~/.emacs.d using git. However, I have git ignore *.elc files.
This means that when I install a package on one system and then start using another system, git pull only gives me the *.el files. Using these files is often slower than using *.elc.
I tried adding the following to ~/.emacs.d/init.el:
;; load the packages we've installed. Note that package-install
;; byte-compiles the packages, but .elc is ignored by git so we force recompilation here
(byte-recompile-directory (expand-file-name "~/.emacs.d/elpa") 0)
(package-initialize)
Unfortunately, this isn't equivalent to the compilation done by package.el. For example, if I install emacs-eclim, package.el doesn't compile emacs-eclim/company-emacs-eclim.el, and I get the following error:
Leaving directory `/home/wilfred/.emacs.d/elpa'
Compiling file /home/wilfred/.emacs.d/elpa/emacs-eclim-20130310.1237/company-emacs-eclim.el at Mon Mar 11 15:40:01 2013
Entering directory `/home/wilfred/.emacs.d/elpa/emacs-eclim-20130310.1237/'
company-emacs-eclim.el:35:1:Error: Cannot open load file: eclim
Warning: reference to free variable `multiple-cursors-mode'
Warning: reference to free variable `mc--read-char'
Warning: assignment to free variable `mc--read-char'
Warning: reference to free variable `multiple-cursors-mode'
Warning: reference to free variable `mc--read-quoted-char'
Warning: assignment to free variable `mc--read-quoted-char'
Warning: reference to free variable `rectangular-region-mode'
Warning: reference to free variable `rectangular-region-mode'
How do I make Emacs byte-compile only the same files as package.el would?

package.el actually uses exactly the same method, it's just recompiling on startup makes the errors more noticable.
The function used is package--make-autoloads-and-compile, which calls:
(byte-recompile-directory pkg-dir 0 t)
So the original code in the question is correct. However, to recompile a directory that isn't yet compiled, you can do the following:
(require 'dash)
(require 'f)
(defun was-compiled-p (path)
"Does the directory at PATH contain any .elc files?"
(--any-p (f-ext? it "elc") (f-files path)))
(defun ensure-packages-compiled ()
"If any packages installed with package.el aren't compiled yet, compile them."
(--each (f-directories package-user-dir)
(unless (was-compiled-p it)
(byte-recompile-directory it 0))))
(ensure-packages-compiled)

I recommend not keeping the packages in version control (you wouldn't put .o files under revision control, would you?). Here is the code I use to keep my packages in sync:
(setq jpk-packages
'(
ac-dabbrev
...
yasnippet
))
(package-initialize)
(add-to-list 'package-archives
'("melpa" . "http://melpa.milkbox.net/packages/"))
(add-to-list 'package-archives
'("org" . "http://orgmode.org/elpa/"))
(when (not package-archive-contents)
(package-refresh-contents))
(dolist (pkg jpk-packages)
(when (and (not (package-installed-p pkg))
(assoc pkg package-archive-contents))
(package-install pkg)))
(defun package-list-unaccounted-packages ()
"Like `package-list-packages', but shows only the packages that
are installed and are not in `jpk-packages'. Useful for
cleaning out unwanted packages."
(interactive)
(package-show-package-list
(remove-if-not (lambda (x) (and (not (memq x jpk-packages))
(not (package-built-in-p x))
(package-installed-p x)))
(mapcar 'car package-archive-contents))))
I put the above in init.el (which of course is under version control), and it installs any packages that don't exist yet when emacs starts up. Updating is done from the buffer package-list-packages creates. package-list-unaccounted-packages shows all the packages that are installed but not in my jpk-packages list, and makes it easy to remove the ones that I took out of the list.
To answer your specific question, I'd just delete the elpa directory and reinstall everything (using the above code).

The solution I like to the more general question of "How do I automatically re-compile any outdated .elc file" is to use https://github.com/tarsius/auto-compile
I used to have a handful of custom solutions which covered most situations I ran into, but this library covers everything I was doing and more besides. Just initialise it before loading anything else, and you're sorted.
As to the original question of not compiling files which were not originally compiled, that's what the 0 argument to byte-recompile-directory does, so you're explicitly asking for that behaviour. The default behaviour is to only recompile existing outdated .elc files, so you should simply remove that 0.

I do not know the answer to your specific issue about byte-compiling packages exactly the same way package.el would.
However, for your more general problem about maintaining your emacs configuration directory in git while installing extensions through Melpa or marmalade, I suggest you give a look to pallet, which has been designed to solve this very problem.

(byte-compile-file) worked for me when I need to manually recompile packages I have previously installed using elpa.
Particularly for this situation: https://github.com/yjwen/org-reveal/issues/76t

The problem you have is simply that you byte-compile files before initializing your packages. If you switch the two lines, your problem should disappear. The error you get (Cannot open load file: eclim) is because ~/.emacs.d/elpa/emacs-eclim-20130310.1237/ is not yet in your load-path, and package-initialize will add it to your load-path (along with a few other things).

Related

I can't load an .el package on emacs

So I downloaded an .el file, I put it on the ~/.emacs.d/elpa/ folder, but it won't appear on the M-x list-packages. How do I make it appear there or how can I install this file/package?
There are two ways of installing an Emacs package: either type M-x list-packages and install it from the list, letting Emacs download it for you, or download the package yourself and install it with M-x package-install-file.
Installing from a package archive
In the first case, note that there are several different package archives. The default value for the variable package-archives only contains GNU ELPA, but most people want to add MELPA to that list since it has more packages. To do that, you need to add the following to your .emacs file (copied from the MELPA web page):
(require 'package) ;; You might already have this line
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/"))
(when (< emacs-major-version 24)
;; For important compatibility libraries like cl-lib
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))
(package-initialize) ;; You might already have this line
After that, typing M-x list-packages should list more packages than you'll ever need :)
Installing from a downloaded file
There are two types of packages: single-file packages and multi-file packages. The former can be downloaded as a single .el file, while the latter are distributed as tarballs (.tar). Both types can be installed with M-x package-install-file.
Note that not every .el file can be installed as a package. The comments at the beginning of the file need to follow a certain convention, documented in the Simple packages node of the Emacs Lisp reference manual.
That leaves the possibility that the .el file you've downloaded is not installable as a package. In that case, you should put it in some other directory (~/.emacs.d/elpa is meant for installed packages only), add that directory to the load-path variable, and require the package. If you have foo.el and put it in ~/path/to/foo, it would look something like this:
(add-to-list 'load-path "~/path/to/foo")
(require 'foo)
An .el file is not a package. Installing it via ELPA is probably vastly preferrable to manually downloading a static .el file; perhaps the maintainer has a home page with ELPA (or Marmalade, etc) instructions.
In particular, a package will receive updates as they are made available, so you will not be forever stuck on an increasingly obsolete, unmanaged version (though quiet, fully automatic updates are not yet available or feasible, AFAICT).
But if you have to get by with just the file you already downloaded, you can put it pretty much anywhere you like, as long as that directory is included in the load-path. Manually mucking with the elpa directory is a bad idea, though; put it somewhere else.
Look for comments near the top of the file for any additional instructions; any autoloads, for example, will probably have to be configured separately, and usually completely manually.
This used to be how you always did things in older versions of Emacs, so you should find that the Internet is still practically bulging with guides and tutorials which explain the finer details of this mechanism, if this answer alone isn't sufficient.

Updating packages in Emacs

I have the following setup for packages (not sure if there is a better recommended one):
(require 'package)
(setq package-archives '(("ELPA" . "http://tromey.com/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")
("marmalade" . "http://marmalade-repo.org/packages/")))
; Apparently needed for the package auto-complete (why?)
(add-to-list 'package-archives
'("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)
(setq url-http-attempt-keepalives nil)
I have three questions related to the installation and updating of packages.
Q1. Is there a way to update the list of available packages (and most recent versions) and update a specific package?
Q.2 What is the difference between the following package sources?:
ELPA,
GNU
marmalade
melpa
Q.3 Does it matter the order in which they are added to package-archives?
In order to automatically update the list of packages, only if there is no package list already, use the following:
(when (not package-archive-contents)
(package-refresh-contents))
In order to update all installed packages, type package-list-packages, which will take you to the *Packages* buffer (and also update the list of packages), and then type U x.
package-refresh-contents unconditionally tries to download a package list from all repos you've added to package-archives; package-archive-contents is non nil if you have already downloaded the package list.
ELPA is the original. I don't think it's really maintained anymore, but I'm not sure. I don't use it.
GNU is "official". It's maintained along with Emacs, which means things should always work but updates and new packages don't come very often.
Marmalade is basically a website where you can upload a complete package, and it will be added to the marmalade repo. You don't just submit a link to the package's upstream, and it doesn't quite automate the creation of the package completely. I think this is the Right Thing, because you don't necessarily want to track upstream. Unfortunately, it has been unmaintained for a while, but someone recently took it over so it should be back and better at some point.
Melpa takes a URL to e.g. the EmacsWiki lisp area or a github repo, and builds a package automatically from it. Thus it is usually at most a day behind whatever it is tracking. Although it tracks upstream, I've never had a problem in practice, and this is where most of my packages are from. There is also Melpa Stable, which is like Melpa but grabs tagged revisions of the upstream repo instead of the latest revision. Melpa stable has fewer packages than Melpa.
Org mode has its own package.el repo (http://orgmode.org/elpa/).
All of the package repos work the same, you just add them to your package-archives.
Here's a more in-depth blog post about this subject, which I mostly agree with.
I'm not sure, but I think if a package is duplicated in different repos, the order the repos appear in in package-archives determines precedence. I don't know if higher precedence is at the beginning or end of the list.
Update: In Emacs 25, there is a variable package-archive-priorities that you can use to prioritize your package repos (e.g. prefer ELPA over MELPA).
Here is the relevant section of my init.el, if you're interested:
(setq jpk-packages
'(
ac-dabbrev
...
yasnippet
))
(package-initialize)
(add-to-list 'package-archives
'("melpa" . "http://melpa.org/packages/"))
(add-to-list 'package-archives
'("org" . "http://orgmode.org/elpa/"))
;; install any packages in jpk-packages, if they are not installed already
(let ((refreshed nil))
(when (not package-archive-contents)
(package-refresh-contents)
(setq refreshed t))
(dolist (pkg jpk-packages)
(when (and (not (package-installed-p pkg))
(assoc pkg package-archive-contents))
(unless refreshed
(package-refresh-contents)
(setq refreshed t))
(package-install pkg))))
(defun package-list-unaccounted-packages ()
"Like `package-list-packages', but shows only the packages that
are installed and are not in `jpk-packages'. Useful for
cleaning out unwanted packages."
(interactive)
(package-show-package-list
(remove-if-not (lambda (x) (and (not (memq x jpk-packages))
(not (package-built-in-p x))
(package-installed-p x)))
(mapcar 'car package-archive-contents))))
Within Emacs, use M-x list-packages to list all packages which will automatically refresh the archive contents. Afterwards use U to mark all upgradable packages to be upgraded, and x to actually perform the new updates. Emacs will then fetch and install all upgrades, and ask you to whether to remove the old, obsolete versions afterwards.
You may also want to take a look at Carton which provides a more convenient way to manage your packages by declaring them in a dedicated file, and includes a convenient command line client to automatically install and upgrade packages declared in this way.
The order of package-archives does not matter. Emacs aggregates the contents of all archives into a single coherent list of available packages and their versions, stored in package-archive-contents.
Upon package-install, Emacs will simply pick the newest version of a package, regardless of the originating archive. For more control about package origin, MELPA provides the melpa package which allows to black- or whitelist packages from specified archives.
In terminal:
emacs
M-x list-packages
this puts you in the *packages* buffer
shift-u x
emacs will ask you (y/n), wait for updates
C-x k <ret>
this will kill the *packages* buffer and return you back to *scratch*
C-x-C-c
this will exit emacs, and let you relaunch via, but you might have to debug :(
emacs
my 2ยข
This is more of an extended comment on jpkotta's answer.
This is an adjustment I am experimenting with for jpkotta's answer above:
(setq n 0) ; set n as 0
(dolist (pkg pkgs-2b-present) ; for each pkg in list
(unless (or ; unless
(package-installed-p pkg) ; pkg is installed or
(assoc pkg ; pkg is in the archive list
package-archive-contents))
(setq n (+ n 1)))) ; add one to n
(when (> n 0) ; if n > 0,
(package-refresh-contents)) ; refresh packages
(replacing (when (not package-archive-contents) (package-refresh-contents))).
The package-list was not refreshing sufficiently often enough for my use-case.
I haven't considered if there is a more efficient solution to my problem; first, I've to see if the problem goes away with this adjustment.

Loading packages installed through 'package.el' in Emacs24 [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Emacs 24 Package System Initialization Problems
I am using Emacs 24. I have the ELPA and Marmalade repos added. Using 'package' I installed 'auto-complete'. I have the following lines added to my init.el:
(require 'auto-complete-config)
(ac-config-default)
When I start Emacs, I get the error
File error: Cannot open load file, auto-complete-config
But then I use
M-x load-file
and load the same ~/.emacs.d/init.el file, it then works fine with the prompt saying
Loading /home/user/.emacs.d/init.el (source)...done
How is the usual loading different from the 'M-x load-file' command? In the start of the init.el file I do the following, is this somehow effecting the package from loading.
(add-to-list 'load-path "~/.emacs.d")
(load "custom_code")
As mentioned in the comment below: The answer by phils to the duplicate question is probably more helpful than this one
This almost certainly means that your init.el file is getting run before the code that sorts out the packages for package.el. The latter code adds the directory with the auto-complete library to your load path.
I'm still using ELPA, rather than package.el. With elpa, there's a snippet that looks like this that gets installed at the bottom of your .emacs.
;;; This was installed by package-install.el.
;;; This provides support for the package system and
;;; interfacing with ELPA, the package archive.
;;; Move this code earlier if you want to reference
;;; packages in your .emacs.
(when
(load
(expand-file-name "~/.emacs.d/elpa/package.el"))
(package-initialize))
As the comment suggests, you probably want to put your equivalent package.el initialization code before the stuff that loads init.el.
Finally: I notice you mention adding .emacs.d to your load-path. The Emacs load path is not recursive, so that probably won't do what you need (assuming that your libraries live in subdirectories). Years ago, I wrote this snippet to load up various libraries of elisp code that I'd written. You might find it useful. (Obviously, it'll only work on unixy systems with a shell and a find command. It's reasonably slow, but this seems to be shell-command-to-string, which takes several milliseconds even running "echo hello" or the like)
(defun find-elisp-dirs (dir)
"Find all directories below DIR containing elisp sources, ignoring those"
(split-string
(shell-command-to-string
(format "find %s -iname '*.el' -printf '%%h\\n' | sort -u"
(expand-file-name dir t)))))

Customize the list of packages that emacs-prelude provides

I see at this link how emacs prelude ensures that a set of packages is installed when emacs starts. I was wondering if I could somehow extend the variable prelude-packages to add some other packages, without changing the prelude-packages.el file?
Barring that I was wondering how I could define a list of packages that are installed at start-up if they aren't currently installed.
You can place a .el file in personal/ directory in Prelude. Prelude loads any .el file it finds there in an alphabetical order. Below is the content of my personal/00-packages.el file.:
(require 'package)
(add-to-list 'package-archives
'("marmalade" .
"http://marmalade-repo.org/packages/"))
(package-initialize)
;; My packages
(setq prelude-packages (append '(
drupal-mode
nginx-mode
) prelude-packages))
;; Install my packages
(prelude-install-packages)
"00" is added to the file name to ensure that the file is loaded before all personal customizations. Add any new package you need to the list being appended to prelude-packages.
Also, if you want to use any mode that is not available in MELPA or Marmalade, you can simply drop the mode's file in personal folder and Prelude will pick it up while loading. If there are any customizations to that mode, simply create another .el file and add the Emacs Lisp code there.
Prelude recommends to use
(prelude-require-packages '(some-package some-other-package))
if you have several package. Or in case you want to add just one package:
(prelude-require-package 'some-package)
If you want you can still maintain your package list in a variable:
(setq my-packages '(drupal-mode nginx-mode toto-mode)
(prelude-require-package my-packages)
In your .emacs file you could add code like this (very similar to the code in the link you sent) to check if each package is installed and install it if is not:
(dolist (package '(eredis anything erlang elnode))
(unless (package-installed-p package)
(package-install package)))
In answer to your question there's no reason you can't do this after the prelude code has run.

How do I check if emacs has a library installed?

I want to check whether pymacs has been installed.
M-x locate-library will tell you if emacs can find the library in its load-path. If it does not return anything you might need to edit your load-path first.
There are many ways to do it.
type apropos, then pymacs. If it finds the symbols, it was loaded.
(require 'pymacs) -- if it does not return error, it was loaded
if you already loaded it, it called (provide 'pymacs), and the variable load-history keeps the symbols
There are still other ways to ckeck it.
Not sure if you're talking about ELPA packages, but I have the following definitions in my .emacs:
(defun sh-elpa-ensure-package (name)
"Make sure that a particular package is installed; if not then
automatically download, compile and install it.
This is primarily used by sh-elpa-require to allow deployment of
the configuration to a new machine - packages will therefore be
downloaded on that fresh machine (following installation they are
automatically kept up to date by the package manager).
Use this as follows:
(sh-elpa-ensure-package 'org)"
(if (not (package-installed-p name))
(package-install name)))
(defun sh-elpa-require (name)
"A replacement for the standard Emacs 'require'
function. This uses sh-elpa-require to download and install a
package if necessary prior to using the standard 'require'
function to import it. This is useful to allow the configuration
to just 'sh-elpa-require' a package and not have to bother
checking whether it has been installed yet."
(sh-elpa-ensure-package name)
(require name))
I can then include code such as the following in my .emacs to activate the package - if it's not already installed then this will download it from ELPA and byte-compile it before it is "required":
(sh-elpa-require 'pymacs)
If you're just talking about checking whether a package is installed from elisp, then you can also pick the bones of that out of the above snippet - see the (if (not (package-installed-p name)) bit.