[#different-emacs-versions]
== Executing on different Emacs versions

Since Eldev itself is an Elisp program, version of Emacs you use can
affect any aspect of execution — even before it gets to running
something out of your project.  Therefore, inside its “cache”
directory called `.eldev`, the utility creates a subdirectory named
after Emacs version it is executed on.  If it is run with a different
Emacs, it will not use dependencies or previous test results, but
rather install or recompute them from scratch.

Normally, Eldev uses command `emacs` that is supposed to be resolvable
through `PATH` environment variable.  However, you can always tell it
to use a different Emacs version, though in this case, Eldev cannot
install it for you, since this is much more complicated than
installing _Elisp packages_.  You need to make sure that Emacs of
desired version is available on your machine (and can be looked up via
`PATH`) as an executable — either by installing via your OS’s package
manager, compiling from sources or maybe using <<evm,EVM>>.  Once you
have it installed, you can tell Eldev to use it by setting either
`ELDEV_EMACS` or just `EMACS` in the environment, e.g.:

    $ EMACS=emacs25 eldev eval emacs-version

This is especially useful for testing your project with different
Emacs versions.

Remember, however, that Eldev cannot separate byte-compiled files
(`.elc`) from sources.  From documentation of
`byte-compile-dest-file-function`:

____
Note that the assumption that the source and compiled files are found
in the same directory is hard-coded in various places in Emacs.
____

Therefore, if you use byte-compilation and switch Emacs versions,
don’t forget to clean the directory.

[#docker]
=== Using Docker or Podman

Alternatively, if you are on a Linux or macOS system and have
{uri-docker}[Docker] or (since 1.10) {uri-podman}[Podman] installed,
you can run arbitrary Eldev commands within containers based on the
images distributed by {uri-docker-emacs}[docker-emacs].  For example:

    $ eldev docker 27.2 emacs --eval '(insert (format "Emacs version: %s" emacs-version))'

will start an Emacs 27.2 container and run `eldev emacs --eval
'(insert (format "Emacs version: %s" emacs-version))'` in it.

[#podman]
{since-1-10} Podman, from Eldev’s point of view, works just the
same.  There is a special command for it, but it is basically
indistinguishable (except for the name):

    $ eldev podman 27.2 emacs --eval '(insert (format "Emacs version: %s" emacs-version))'

NOTE: You may have to run `xhost +local:root` which allows the Docker
(Podman) container to make connections to the host X server.  However,
this does come with some security considerations, see `man xhost`.

This command can be used not only to start Emacs of given version, but
to run _any_ Eldev command.  For example, run project’s tests on an
older editor version:

    $ eldev docker 25.3 test

or evaluate something using project’s functions:

    $ eldev docker 26.3 eval "(my-project-read-data \"foo.bin\")"

Docker’s (Podman’s) output is forwarded to normal Eldev output,
however, because of {uri-emacs-forwarding}[Elisp limitations], it all
ends up on Eldev’s stdout!  There might also be unwieldy delays, so
that output doesn’t come smoothly as generated by the process inside
Docker, but instead in larger chunks.  Before Eldev 1.2 the output
would instead only appear when Docker has exited.

It is also possible to use a custom image.  For this, replace Emacs
version argument (26.3 in the last example above) with the full image
name.  The image must contain a preinstalled Emacs of a version
supported by Eldev (i.e. 24.4 and up), but not Eldev itself.  Eldev
itself uses the smallest available image provided by Silex.  This may
be too restrictive, for example it doesn’t include Git.  But you can
easily tell Eldev to use any other {uri-docker-emacs-images}[Silex
image] (or an image provided elsewhere):

    $ eldev docker silex/emacs:28-ci eval "(eldev-git-executable)"

Additionally, `docker run` arguments are customisable via the variable
`eldev-docker-run-extra-args` (and likewise for Podman:
`eldev-podman-run-extra-args`).  For example, adding the following to
your project’s `Eldev`:

....
(setf eldev-docker-run-extra-args '("--name" "my_cool_container"))
....

will set the container name to “my_cool_container”.
