Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #3379 - core: different elpa dir per emacs version #3384

Closed
wants to merge 1 commit into from

Conversation

bmag
Copy link
Collaborator

@bmag bmag commented Oct 14, 2015

For emacs 24.5.1 packages will be installed in .emacs.d/elpa/24.5.1, for emacs 24.4.1 packages will be installed in .emacs.d/elpa/24.4.1, etc.
For a user that uses several emacs versions with the same config, the packages for version X will be in .emacs.d/elpa/X and the packages for version Y will be in .emacs.d/elpa/Y. This is instead of using the same .emacs.d/elpa and possibly having copmiled elisp packages the are incompatible with one of the emacs versions in use.

I've also changed the rollback directory to be version-dependent (.cache/.rollback/VERSION/), so rollback mechanism should work. If I've missed something, please point it out.

ref #3379

@d12frosted
Copy link
Collaborator

Wow. Nice idea. I rarely switch between versions, but when I do, I rm -rf ~/.emacs.d.spacemacs/elpa. This should help me avoid the time loose.

@justbur
Copy link
Contributor

justbur commented Oct 14, 2015

Yes please. This should be done by Emacs itself IMO

@swsnr
Copy link
Contributor

swsnr commented Oct 15, 2015

I’m very much against this change. It’s addressing an issue which is purely theoretical in my opinion. Emacs’ byte code and its interfaces are fairly stable. It's packages that create havoc, usually by mis- and abuse of eval-and-compile and macros (looking at you, H...), but a version-dependent ELPA directory is not going to fix it.

But it's going to make using multiple Emacs version much harder, because you'll have to update packages independently for each Emacs version.

I presume that there are not many people which actually use multiple Emacs versions, but to those that do—e.g. myself—it's an important part of their workflow: I regularly start older Emacs versions to test Flycheck, and I keep a stable release ready in case Emacs master breaks (which happens from time to time). I'd hate to update packages separately for each version, on at least two different systems.

Please, don't do this, and if you do, please, please, do add means to disable it.

@justbur
Copy link
Contributor

justbur commented Oct 15, 2015

@lunaryorn so don't the packages in question need to be recompiled at least?

@syl20bnr
Copy link
Owner

We are to be sure that we are effectively fixing a problem by isolating packages like this.

@bmag @d12frosted do you have real world examples about such incompatibility which force you to have multiple elpa directories ?

@d12frosted
Copy link
Collaborator

Well, I've run into incompatibility problem only once, and can't recall what was the problem, but it was fixed by removing elpa dir and installing all packages again. After that whenever I need to change my emacs - I wipe out elpa dir. For me it's not critical to miss this PR, because I don't switch between versions very often plus it doesn't take much to install packages from scratch.

So if this PR brings more (possible) problems than the amount of good it adds, then I don't feel bad about having to reinstall* packages on emacs version switch.

  • probably I should try once again switching version without removing elpa dir

@justbur
Copy link
Contributor

justbur commented Oct 15, 2015

@syl20bnr To add to this, "nuke elpa" is a relatively common solution to problems given in the gitter chat (perhaps that's wrong). It might be worth investigating further, but I believe that solution was at least partly attributed to people switching versions of emacs and using the same elpa directory. Of course, that's speculative. I believe I ran into this once switching between 24.4 and 25, and redownloading and compiling packages fixed it, which is why I supported this idea.

@d12frosted
Copy link
Collaborator

Yeah, indeed. I have a habit of nuking elpa time to time when I update Spacemacs. Cause sometimes I am running into problems that are solved greatly by this ultimate tool.

@justbur
Copy link
Contributor

justbur commented Oct 15, 2015

Maybe we could slowly build a list of packages that can't handle version changes and make a function to recompile just those packages?

@bmag
Copy link
Collaborator Author

bmag commented Oct 15, 2015

In response to @syl20bnr:

do you have real world examples about such incompatibility which force you to have multiple elpa directories ?

@eggcaker had a problem yesterday in the chat (search for "eggcaker", there aren't many messages) that sounds like he used emacs 24.5.1 after using emacs 25.0 (trunk) and encountered an incompatible elc file. I didn't confirm that @eggcaker really used 25.0, but I think it's safe to assume so based on the following:

  1. the error he encounterd: Error (use-package): evil-jumper :init: Symbol's function definition is void: cl-struct-define
  2. he said he uses emacs 24.5.1
  3. cl-struct-define doesn't exist (or I couldn't find it) in emacs 24.5.1, but does exist in 25.0.50.6

I myself use only emacs 24.5.1 so I can't offer a real world example of my own.


In response to @lunaryorn:

It’s addressing an issue which is purely theoretical in my opinion.

To me it doesn't seem theoretical, since according to the chat it seems to have happened, but it is probably rare.

But it's going to make using multiple Emacs version much harder, because you'll have to update packages independently for each Emacs version.

True, but I don't think it will "much harder", only a bit annoyting. Another concern (which I have not considered earlier) is that different emacs versions may have different versions of the same packages, resulting in slightly different behavior for different emacs versions. That could be very surprising if the user doesn't know what's going on, and most users won't know.

I'd also like to know the answer to @justbur's earlier question.

do add means to disable it

I'm not sure what's the best way to add a means for disabling, but I agree.

@justbur
Copy link
Contributor

justbur commented Oct 15, 2015

Some more data: #3333, #1624

I'll update with more next time I look, but these were easy to find

@swsnr
Copy link
Contributor

swsnr commented Oct 15, 2015

@bmag I mean no offense, but

True, but I don't think it will "much harder", only a bit annoyting.

that’s my thing to judge, don't you think?

I can reproduce your case, though, and it’s indeed an incompatibility in a built-in Emacs macro. It’s the first I’ve seen so far, but you do have a point 😊 And then, I might have missed it so far, because I'm typically running older releases with -q which doesn't initialize packages at start, so I do admit that my experience is not particularly helpful.

@justbur I’m sorry, and I mean no offense, but not any issue that is solved by wiping elpa/ is actually related to Emacs‘ version.

#1624 is not, for sure—it was simply a Helm bug (surprisingly, excuse my sarcasm, but it’s not the first of these in Helm), which broke compatibility with 24.3 generally. This change would neither have prevented nor solved it. #3333 might have been anything: There’s no data beyond the backtrace and no investigation either, and it could easily have been a package but too. 3rd party packages move faster and break faster than Emacs upstream.


That said, couldn’t Spacemacs just recompile ~/.emacs.d/elpa/ at startup if it was last started on a different Emacs version?

@justbur
Copy link
Contributor

justbur commented Oct 15, 2015

@justbur I’m sorry, and I mean no offense, but not any issue that is solved by wiping elpa/ is actually related to Emacs‘ version.

True and no offense taken 😄. I was simply providing evidence of the "wipe elpa" phenomenon at which this pull request is aimed. Besides the example given by @bmag, I don't know of a confirmed instance where the problem was caused by switching versions, but I do know that it has been suggested as a potential problem many times, so take that for what it's worth.

That said, couldn’t Spacemacs just recompile ~/.emacs.d/elpa/ at startup if it was last started on a different Emacs version?

I know I suggested this, but I tried it and it actually takes a while, so it's not that great of a solution either. Maybe we could find and target the packages that have the problem and ideally file bug reports with those and get as many fixed as possible? After all, there might only be a few as you suggest @lunaryorn. I hadn't considered looking for weird things in eval-when-compile before, so I'll be on the lookout for issues like this in the future.

I'd like to figure out what's going on and get away from the "wipe elpa" thing, because I think it's bad advice, like telling someone to restart their computer.

@justbur
Copy link
Contributor

justbur commented Oct 15, 2015

It's also worth mentioning that for whatever reason more than once I've had issues with elpa caused by corrupted files. This would be fixed by "nuke elpa" but has nothing to do with versions.

@eggcaker
Copy link

@bmag yes, i was using 25.x before, after delete elpa , reopen emacs and install all packages
,everything works.

@syl20bnr
Copy link
Owner

I do feel that having separate directories is more natural and cleaner. What we fixe on one end (incompatible elpa dir between two versions) we loose on the other end (elpa dirs are not in sync).

I would like to test this a bit on develop branch to get a better feel about it.

What we can do to mitigate this is to have some kind of indicator showing the number of days since last update of packages.

@swsnr
Copy link
Contributor

swsnr commented Oct 19, 2015

I disagree, but YMMV and I'm fine with either, but I'd really appreciate if I was given an option to disable separate ELPA dirs.

@StreakyCobra
Copy link
Contributor

PR #4312 is similar (if one get merged, the other one should be closed)

@emacs18
Copy link
Contributor

emacs18 commented Dec 28, 2015

Let me provide one example of byte compiler incompatibility.
Following is the stack trace that I see if I attempted to launch emacs 24.5 using ELPA files
byte compiled by emacs 25.0.

Debugger entered--Lisp error: (void-function cl-struct-define)
  cl-struct-define(evil-jumper-jump nil cl-structure-object nil nil ((cl-tag-slot) (jumps) (idx -1)) cl-struct-evil-jumper-jump-tags cl-struct-evil-jumper-jump t)
  byte-code("\300\301\302\303#\210\304\305\306\307\306\211\310\311\312\303& \207" [function-put make-evil-jumper-jump side-effect-free t cl-struct-define evil-jumper-jump nil cl-structure-object ((cl-tag-slot) (jumps) (idx -1)) cl-struct-evil-jumper-jump-tags cl-struct-evil-jumper-jump] 10)
  (evil-jumper-mode t)
  (progn (setq evil-jumper-auto-save-interval 600) (evil-jumper-mode t))
  (condition-case err (progn (setq evil-jumper-auto-save-interval 600) (evil-jumper-mode t)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" ":init" (error-message-string err)) :error))))
  (progn (condition-case err (progn (setq evil-jumper-auto-save-interval 600) (evil-jumper-mode t)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" ":init" (error-message-string err)) :error)))) (condition-case err (run-hooks (quote use-package--evil-jumper--post-init-hook)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" "post-:init hook" (error-message-string err)) :error)))))
  (if (condition-case err (run-hook-with-args-until-failure (quote use-package--evil-jumper--pre-init-hook)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" "pre-:init hook" (error-message-string err)) :error)))) (progn (condition-case err (progn (setq evil-jumper-auto-save-interval 600) (evil-jumper-mode t)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" ":init" (error-message-string err)) :error)))) (condition-case err (run-hooks (quote use-package--evil-jumper--post-init-hook)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" "post-:init hook" (error-message-string err)) :error))))))
  (progn (if (condition-case err (run-hook-with-args-until-failure (quote use-package--evil-jumper--pre-init-hook)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" "pre-:init hook" (error-message-string err)) :error)))) (progn (condition-case err (progn (setq evil-jumper-auto-save-interval 600) (evil-jumper-mode t)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" ":init" ...) :error)))) (condition-case err (run-hooks (quote use-package--evil-jumper--post-init-hook)) ((debug error) (ignore (display-warning (quote use-package) (format "%s %s: %s" "evil-jumper" "post-:init hook" ...) :error)))))) (if (not (require (quote evil-jumper) nil (quote noerror))) (ignore (message (format "Could not load %s" (quote evil-jumper))))))
  spacemacs/init-evil-jumper()
  funcall(spacemacs/init-evil-jumper)
  (let* ((pkg-name (eieio-oref pkg (quote :name))) (owner (eieio-oref pkg (quote :owner))) (owner-layer (object-assoc owner :name configuration-layer--layers)) (disabled-for-layers (eieio-oref owner-layer (quote :disabled-for)))) (spacemacs-buffer/message (format "Configuring %S..." pkg-name)) (mapc (function (lambda (layer) (if (memq layer disabled-for-layers) (spacemacs-buffer/message (format "  -> ignored pre-init (%S)..." layer)) (spacemacs-buffer/message (format "  -> pre-init (%S)..." layer)) (condition-case err (funcall (intern ...)) ((quote error) (configuration-layer//set-error) (spacemacs-buffer/append ...)))))) (eieio-oref pkg (quote :pre-layers))) (spacemacs-buffer/message (format "  -> init (%S)..." owner)) (funcall (intern (format "%S/init-%S" owner pkg-name))) (mapc (function (lambda (layer) (if (memq layer disabled-for-layers) (spacemacs-buffer/message (format "  -> ignored post-init (%S)..." layer)) (spacemacs-buffer/message (format "  -> post-init (%S)..." layer)) (condition-case err (funcall (intern ...)) ((quote error) (configuration-layer//set-error) (spacemacs-buffer/append ...)))))) (eieio-oref pkg (quote :post-layers))))
  configuration-layer//configure-package([object cfgl-package "evil-jumper" evil-jumper spacemacs nil (python) elpa nil nil nil])
  (cond ((eq (quote dotfile) (eieio-oref pkg (quote :owner))) (configuration-layer//activate-package pkg-name) (spacemacs-buffer/message (format "%S is configured in the dotfile." pkg-name))) (t (configuration-layer//activate-package pkg-name) (configuration-layer//configure-package pkg)))
  (cond ((and (eieio-oref pkg (quote :excluded)) (not (eieio-oref pkg (quote :protected)))) (spacemacs-buffer/message (format "%S ignored since it has been excluded." pkg-name))) ((null (eieio-oref pkg (quote :owner))) (spacemacs-buffer/message (format "%S ignored since it has no owner layer." pkg-name))) (t (let ((location (eieio-oref pkg (quote :location)))) (cond ((stringp location) (if (file-directory-p location) (setq load-path (cons ... load-path)) (spacemacs-buffer/warning "Location path for package %S does not exists (value: %s)." pkg location))) ((and (eq (quote local) location) (eq (quote dotfile) (eieio-oref pkg ...))) (setq load-path (cons (file-name-as-directory ...) load-path))) ((eq (quote local) location) (let* ((owner ...) (dir ...)) (setq load-path (cons ... load-path)) (setq load-path (cons ... load-path)))))) (cond ((eq (quote dotfile) (eieio-oref pkg (quote :owner))) (configuration-layer//activate-package pkg-name) (spacemacs-buffer/message (format "%S is configured in the dotfile." pkg-name))) (t (configuration-layer//activate-package pkg-name) (configuration-layer//configure-package pkg)))))
  (let ((pkg-name (eieio-oref pkg (quote :name)))) (cond ((and (eieio-oref pkg (quote :excluded)) (not (eieio-oref pkg (quote :protected)))) (spacemacs-buffer/message (format "%S ignored since it has been excluded." pkg-name))) ((null (eieio-oref pkg (quote :owner))) (spacemacs-buffer/message (format "%S ignored since it has no owner layer." pkg-name))) (t (let ((location (eieio-oref pkg (quote :location)))) (cond ((stringp location) (if (file-directory-p location) (setq load-path ...) (spacemacs-buffer/warning "Location path for package %S does not exists (value: %s)." pkg location))) ((and (eq ... location) (eq ... ...)) (setq load-path (cons ... load-path))) ((eq (quote local) location) (let* (... ...) (setq load-path ...) (setq load-path ...))))) (cond ((eq (quote dotfile) (eieio-oref pkg (quote :owner))) (configuration-layer//activate-package pkg-name) (spacemacs-buffer/message (format "%S is configured in the dotfile." pkg-name))) (t (configuration-layer//activate-package pkg-name) (configuration-layer//configure-package pkg))))))
  (while --dolist-tail-- (setq pkg (car --dolist-tail--)) (spacemacs-buffer/loading-animation) (let ((pkg-name (eieio-oref pkg (quote :name)))) (cond ((and (eieio-oref pkg (quote :excluded)) (not (eieio-oref pkg (quote :protected)))) (spacemacs-buffer/message (format "%S ignored since it has been excluded." pkg-name))) ((null (eieio-oref pkg (quote :owner))) (spacemacs-buffer/message (format "%S ignored since it has no owner layer." pkg-name))) (t (let ((location (eieio-oref pkg ...))) (cond ((stringp location) (if ... ... ...)) ((and ... ...) (setq load-path ...)) ((eq ... location) (let* ... ... ...)))) (cond ((eq (quote dotfile) (eieio-oref pkg ...)) (configuration-layer//activate-package pkg-name) (spacemacs-buffer/message (format "%S is configured in the dotfile." pkg-name))) (t (configuration-layer//activate-package pkg-name) (configuration-layer//configure-package pkg)))))) (setq --dolist-tail-- (cdr --dolist-tail--)))
  (let ((--dolist-tail-- packages) pkg) (while --dolist-tail-- (setq pkg (car --dolist-tail--)) (spacemacs-buffer/loading-animation) (let ((pkg-name (eieio-oref pkg (quote :name)))) (cond ((and (eieio-oref pkg (quote :excluded)) (not (eieio-oref pkg ...))) (spacemacs-buffer/message (format "%S ignored since it has been excluded." pkg-name))) ((null (eieio-oref pkg (quote :owner))) (spacemacs-buffer/message (format "%S ignored since it has no owner layer." pkg-name))) (t (let ((location ...)) (cond (... ...) (... ...) (... ...))) (cond ((eq ... ...) (configuration-layer//activate-package pkg-name) (spacemacs-buffer/message ...)) (t (configuration-layer//activate-package pkg-name) (configuration-layer//configure-package pkg)))))) (setq --dolist-tail-- (cdr --dolist-tail--))))
  configuration-layer//configure-packages-2(([object cfgl-package "ac-ispell" ac-ispell auto-completion nil nil elpa nil nil nil] [object cfgl-package "ace-jump-helm-line" ace-jump-helm-line spacemacs nil nil elpa nil nil nil] [object cfgl-package "ace-link" ace-link spacemacs nil nil elpa nil nil nil] [object cfgl-package "ace-window" ace-window spacemacs nil nil elpa nil nil nil] [object cfgl-package "adaptive-wrap" adaptive-wrap spacemacs nil nil elpa nil nil nil] [object cfgl-package "ag" ag dotfile nil nil elpa nil nil nil] [object cfgl-package "aggressive-indent" aggressive-indent spacemacs nil nil elpa nil nil nil] [object cfgl-package "anaconda-mode" anaconda-mode python nil nil elpa nil nil nil] [object cfgl-package "auctex" auctex latex nil nil elpa nil nil nil] [object cfgl-package "auctex-latexmk" auctex-latexmk nil nil nil elpa nil nil nil] [object cfgl-package "auto-compile" auto-compile emacs-lisp nil nil elpa nil nil nil] [object cfgl-package "auto-complete" auto-complete auto-completion nil nil elpa nil nil nil] [object cfgl-package "auto-dictionary" auto-dictionary spell-checking nil nil elpa nil nil nil] [object cfgl-package "auto-highlight-symbol" auto-highlight-symbol spacemacs nil nil elpa nil nil nil] [object cfgl-package "auto-yasnippet" auto-yasnippet auto-completion nil nil elpa nil nil nil] [object cfgl-package "avy" avy spacemacs nil nil elpa nil nil nil] [object cfgl-package "bbdb" bbdb dotfile nil nil elpa nil nil nil] [object cfgl-package "bind-key" bind-key spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "bookmark" bookmark spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "buffer-move" buffer-move spacemacs nil nil elpa nil nil nil] [object cfgl-package "cc-mode" cc-mode c-c++ nil nil elpa nil nil nil] [object cfgl-package "centered-cursor" centered-cursor spacemacs nil nil local nil nil nil] [object cfgl-package "chronos" chronos dotfile nil nil elpa nil nil nil] [object cfgl-package "clang-format" clang-format c-c++ nil nil elpa nil nil nil] [object cfgl-package "clean-aindent-mode" clean-aindent-mode spacemacs nil nil elpa nil nil nil] [object cfgl-package "cmake-mode" cmake-mode c-c++ nil nil elpa nil nil nil] [object cfgl-package "comint" comint shell nil nil built-in nil nil nil] [object cfgl-package "command-log-mode" command-log-mode command-log nil nil elpa nil nil nil] [object cfgl-package "company" company auto-completion (shell) (yaml python org latex emacs-lisp c-c++) elpa nil nil nil] [object cfgl-package "company-anaconda" company-anaconda python nil nil elpa nil nil nil] [object cfgl-package "company-auctex" company-auctex latex nil nil elpa nil nil nil] [object cfgl-package "company-c-headers" company-c-headers c-c++ nil nil elpa nil nil nil] [object cfgl-package "company-emoji" company-emoji nil nil (org) elpa nil nil nil] [object cfgl-package "company-quickhelp" company-quickhelp auto-completion nil nil elpa nil nil nil] [object cfgl-package "company-statistics" company-statistics auto-completion nil nil elpa nil nil nil] [object cfgl-package "company-ycmd" company-ycmd nil nil (c-c++) elpa nil nil nil] [object cfgl-package "cython-mode" cython-mode python nil nil elpa nil nil nil] [object cfgl-package "default-text-scale" default-text-scale dotfile nil nil elpa nil nil nil] [object cfgl-package "define-word" define-word spacemacs nil nil elpa nil nil nil] [object cfgl-package "desktop" desktop spacemacs nil nil elpa nil nil nil] [object cfgl-package "diff-hl" diff-hl version-control nil nil elpa nil nil nil] [object cfgl-package "diff-mode" diff-mode version-control nil nil elpa nil nil nil] [object cfgl-package "diminish" diminish spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "disaster" disaster c-c++ nil nil elpa nil nil nil] [object cfgl-package "doc-view" doc-view spacemacs nil nil elpa nil nil nil] [object cfgl-package "ediff" ediff spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "ein" ein ipython-notebook nil nil elpa nil nil nil] [object cfgl-package "eldoc" eldoc spacemacs-base nil (python emacs-lisp) elpa nil nil nil] [object cfgl-package "electric-indent-mode" electric-indent-mode spacemacs-base nil nil built-in nil nil nil] [object cfgl-package "elisp-slime-nav" elisp-slime-nav emacs-lisp nil nil elpa nil nil nil] ...))
  configuration-layer//configure-packages(([object cfgl-package "ac-ispell" ac-ispell auto-completion nil nil elpa nil nil nil] [object cfgl-package "ace-jump-helm-line" ace-jump-helm-line spacemacs nil nil elpa nil nil nil] [object cfgl-package "ace-link" ace-link spacemacs nil nil elpa nil nil nil] [object cfgl-package "ace-window" ace-window spacemacs nil nil elpa nil nil nil] [object cfgl-package "adaptive-wrap" adaptive-wrap spacemacs nil nil elpa nil nil nil] [object cfgl-package "ag" ag dotfile nil nil elpa nil nil nil] [object cfgl-package "aggressive-indent" aggressive-indent spacemacs nil nil elpa nil nil nil] [object cfgl-package "anaconda-mode" anaconda-mode python nil nil elpa nil nil nil] [object cfgl-package "auctex" auctex latex nil nil elpa nil nil nil] [object cfgl-package "auctex-latexmk" auctex-latexmk nil nil nil elpa nil nil nil] [object cfgl-package "auto-compile" auto-compile emacs-lisp nil nil elpa nil nil nil] [object cfgl-package "auto-complete" auto-complete auto-completion nil nil elpa nil nil nil] [object cfgl-package "auto-dictionary" auto-dictionary spell-checking nil nil elpa nil nil nil] [object cfgl-package "auto-highlight-symbol" auto-highlight-symbol spacemacs nil nil elpa nil nil nil] [object cfgl-package "auto-yasnippet" auto-yasnippet auto-completion nil nil elpa nil nil nil] [object cfgl-package "avy" avy spacemacs nil nil elpa nil nil nil] [object cfgl-package "bbdb" bbdb dotfile nil nil elpa nil nil nil] [object cfgl-package "bind-key" bind-key spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "bind-map" bind-map spacemacs-base nil nil elpa pre nil nil] [object cfgl-package "bookmark" bookmark spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "buffer-move" buffer-move spacemacs nil nil elpa nil nil nil] [object cfgl-package "cc-mode" cc-mode c-c++ nil nil elpa nil nil nil] [object cfgl-package "centered-cursor" centered-cursor spacemacs nil nil local nil nil nil] [object cfgl-package "chronos" chronos dotfile nil nil elpa nil nil nil] [object cfgl-package "clang-format" clang-format c-c++ nil nil elpa nil nil nil] [object cfgl-package "clean-aindent-mode" clean-aindent-mode spacemacs nil nil elpa nil nil nil] [object cfgl-package "cmake-mode" cmake-mode c-c++ nil nil elpa nil nil nil] [object cfgl-package "comint" comint shell nil nil built-in nil nil nil] [object cfgl-package "command-log-mode" command-log-mode command-log nil nil elpa nil nil nil] [object cfgl-package "company" company auto-completion (shell) (yaml python org latex emacs-lisp c-c++) elpa nil nil nil] [object cfgl-package "company-anaconda" company-anaconda python nil nil elpa nil nil nil] [object cfgl-package "company-auctex" company-auctex latex nil nil elpa nil nil nil] [object cfgl-package "company-c-headers" company-c-headers c-c++ nil nil elpa nil nil nil] [object cfgl-package "company-emoji" company-emoji nil nil (org) elpa nil nil nil] [object cfgl-package "company-quickhelp" company-quickhelp auto-completion nil nil elpa nil nil nil] [object cfgl-package "company-statistics" company-statistics auto-completion nil nil elpa nil nil nil] [object cfgl-package "company-ycmd" company-ycmd nil nil (c-c++) elpa nil nil nil] [object cfgl-package "cython-mode" cython-mode python nil nil elpa nil nil nil] [object cfgl-package "default-text-scale" default-text-scale dotfile nil nil elpa nil nil nil] [object cfgl-package "define-word" define-word spacemacs nil nil elpa nil nil nil] [object cfgl-package "desktop" desktop spacemacs nil nil elpa nil nil nil] [object cfgl-package "diff-hl" diff-hl version-control nil nil elpa nil nil nil] [object cfgl-package "diff-mode" diff-mode version-control nil nil elpa nil nil nil] [object cfgl-package "diminish" diminish spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "disaster" disaster c-c++ nil nil elpa nil nil nil] [object cfgl-package "doc-view" doc-view spacemacs nil nil elpa nil nil nil] [object cfgl-package "ediff" ediff spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "ein" ein ipython-notebook nil nil elpa nil nil nil] [object cfgl-package "eldoc" eldoc spacemacs-base nil (python emacs-lisp) elpa nil nil nil] [object cfgl-package "electric-indent-mode" electric-indent-mode spacemacs-base nil nil built-in nil nil nil] ...))
  configuration-layer//load-packages(([object cfgl-package "ac-ispell" ac-ispell auto-completion nil nil elpa nil nil nil] [object cfgl-package "ace-jump-helm-line" ace-jump-helm-line spacemacs nil nil elpa nil nil nil] [object cfgl-package "ace-link" ace-link spacemacs nil nil elpa nil nil nil] [object cfgl-package "ace-window" ace-window spacemacs nil nil elpa nil nil nil] [object cfgl-package "adaptive-wrap" adaptive-wrap spacemacs nil nil elpa nil nil nil] [object cfgl-package "ag" ag dotfile nil nil elpa nil nil nil] [object cfgl-package "aggressive-indent" aggressive-indent spacemacs nil nil elpa nil nil nil] [object cfgl-package "anaconda-mode" anaconda-mode python nil nil elpa nil nil nil] [object cfgl-package "auctex" auctex latex nil nil elpa nil nil nil] [object cfgl-package "auctex-latexmk" auctex-latexmk nil nil nil elpa nil nil nil] [object cfgl-package "auto-compile" auto-compile emacs-lisp nil nil elpa nil nil nil] [object cfgl-package "auto-complete" auto-complete auto-completion nil nil elpa nil nil nil] [object cfgl-package "auto-dictionary" auto-dictionary spell-checking nil nil elpa nil nil nil] [object cfgl-package "auto-highlight-symbol" auto-highlight-symbol spacemacs nil nil elpa nil nil nil] [object cfgl-package "auto-yasnippet" auto-yasnippet auto-completion nil nil elpa nil nil nil] [object cfgl-package "avy" avy spacemacs nil nil elpa nil nil nil] [object cfgl-package "bbdb" bbdb dotfile nil nil elpa nil nil nil] [object cfgl-package "bind-key" bind-key spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "bind-map" bind-map spacemacs-base nil nil elpa pre nil nil] [object cfgl-package "bookmark" bookmark spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "buffer-move" buffer-move spacemacs nil nil elpa nil nil nil] [object cfgl-package "cc-mode" cc-mode c-c++ nil nil elpa nil nil nil] [object cfgl-package "centered-cursor" centered-cursor spacemacs nil nil local nil nil nil] [object cfgl-package "chronos" chronos dotfile nil nil elpa nil nil nil] [object cfgl-package "clang-format" clang-format c-c++ nil nil elpa nil nil nil] [object cfgl-package "clean-aindent-mode" clean-aindent-mode spacemacs nil nil elpa nil nil nil] [object cfgl-package "cmake-mode" cmake-mode c-c++ nil nil elpa nil nil nil] [object cfgl-package "comint" comint shell nil nil built-in nil nil nil] [object cfgl-package "command-log-mode" command-log-mode command-log nil nil elpa nil nil nil] [object cfgl-package "company" company auto-completion (shell) (yaml python org latex emacs-lisp c-c++) elpa nil nil nil] [object cfgl-package "company-anaconda" company-anaconda python nil nil elpa nil nil nil] [object cfgl-package "company-auctex" company-auctex latex nil nil elpa nil nil nil] [object cfgl-package "company-c-headers" company-c-headers c-c++ nil nil elpa nil nil nil] [object cfgl-package "company-emoji" company-emoji nil nil (org) elpa nil nil nil] [object cfgl-package "company-quickhelp" company-quickhelp auto-completion nil nil elpa nil nil nil] [object cfgl-package "company-statistics" company-statistics auto-completion nil nil elpa nil nil nil] [object cfgl-package "company-ycmd" company-ycmd nil nil (c-c++) elpa nil nil nil] [object cfgl-package "cython-mode" cython-mode python nil nil elpa nil nil nil] [object cfgl-package "default-text-scale" default-text-scale dotfile nil nil elpa nil nil nil] [object cfgl-package "define-word" define-word spacemacs nil nil elpa nil nil nil] [object cfgl-package "desktop" desktop spacemacs nil nil elpa nil nil nil] [object cfgl-package "diff-hl" diff-hl version-control nil nil elpa nil nil nil] [object cfgl-package "diff-mode" diff-mode version-control nil nil elpa nil nil nil] [object cfgl-package "diminish" diminish spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "disaster" disaster c-c++ nil nil elpa nil nil nil] [object cfgl-package "doc-view" doc-view spacemacs nil nil elpa nil nil nil] [object cfgl-package "ediff" ediff spacemacs-base nil nil elpa nil nil nil] [object cfgl-package "ein" ein ipython-notebook nil nil elpa nil nil nil] [object cfgl-package "eldoc" eldoc spacemacs-base nil (python emacs-lisp) elpa nil nil nil] [object cfgl-package "electric-indent-mode" electric-indent-mode spacemacs-base nil nil built-in nil nil nil] ...))
  configuration-layer/sync()
  (if (not (version<= spacemacs-emacs-min-version emacs-version)) (message (concat "Your version of Emacs (%s) is too old. " "Spacemacs requires Emacs version %d or above.") emacs-version spacemacs-emacs-min-version) (load-file (concat user-emacs-directory "core/core-load-paths.el")) (if init-file-debug (progn (require (quote core-debug)))) (require (quote core-spacemacs)) (spacemacs/init) (spacemacs/maybe-install-dotfile) (configuration-layer/sync) (spacemacs/setup-startup-hook) (require (quote server)) (if (server-running-p) nil (server-start)))
  eval-buffer(#<buffer  *load*> nil "/u/kimr/Public/spacemacs25/init.el" nil t)  ; Reading at buffer position 1165
  load-with-code-conversion("/u/kimr/Public/spacemacs25/init.el" "/u/kimr/Public/spacemacs25/init.el" nil nil)
  load("/u/kimr/Public/spacemacs25/init.el" nil nil t)
  load-file("/u/kimr/Public/spacemacs25/init.el")
  eval((load-file "/u/kimr/Public/spacemacs25/init.el"))
  command-line-1(("--eval" "(setq debug-on-error t)" "--eval" "(custom-set-variables '(flyspell-auto-correct-binding [(control ?\\')]))" "--eval" "(setq user-emacs-directory \"/u/kimr/Public/spacemacs25/\")" "--eval" "(load-file \"/u/kimr/Public/spacemacs25/init.el\")" "--eval" "(load \"/u/kimr/Private/elisp/init.el\")" "--eval" "(setq debug-on-error nil)"))
  command-line()
  normal-top-level()

@emacs18
Copy link
Contributor

emacs18 commented Dec 28, 2015

As I recall similar byte compile format change occurred within 24.x series.

Going back many years, I've encountered several byte compiler related problems.
Sometimes the symptom is weird and it may be hard to diagnose.
That is why I got into habit of using separate directories for byte compiled files for each emacs version.

It is not necessary to distinguish third or fourth version number, e.g., 24.5.1 or 25.0.50.1.
I think we need to keep at least first two numbers, e.g., 24.5 and 25.0 in the elpa path.
It is very annoying to have to recompile when version changes from 25.0.50.1 to 25.0.50.2
or from 24.5.1 to 24.5.2.

@emacs18
Copy link
Contributor

emacs18 commented Dec 28, 2015

Those who prefer not to use separate directories can easily to do by just using symlinks, e.g.,

cd spacemacs
ln -s elpa elpa-24.5
ln -s elpa elps-25.0
...

@justbur
Copy link
Contributor

justbur commented Dec 28, 2015

Yep, I can reproduce this. cl-struct-define is used in the macro expansion for cl-defstruct in emacs25 but not 24, which explains the issue. I also found the same problem in a few other packages, so it's not just evil-jumper.

@emacs18
Copy link
Contributor

emacs18 commented Dec 28, 2015

When major emacs version changes, it is more likely than not to have
byte compilation compatibility problems. Even when the minor version
number changes, there could be byte compilation compatibility issues.
When one is lucky, the compatibility problem manifests itself
conspicuously as shown above. The key problem IMHO is when the
compatibility problem manifests itself in a subtle way. I know that I
had to suffer this multiple times over the years. On some occasions I
had to spend hours to learn that the source of my problem was
incompatibility in the byte compiler. That is why many years ago I decided
to never to repeat the same mistake again and so started using separate
directories when either major or minor versions changed. This predates
spacemacs, package.el, and many other things.

I think it would be a great service to prevent users from experiencing
subtle byte compatibility issues. Yes it is possible for someone to not
encounter this problem even for years. But when you do encounter it, it
could be a very frustrating experience.

@syl20bnr syl20bnr changed the title core: different elpa dir per emacs version Fixes #3379 - core: different elpa dir per emacs version Mar 5, 2016
For emacs 24.5 packages will be installed in .emacs.d/elpa/24.5, for
emacs 24.4 packages will be installed in .emacs.d/elpa/24.4, etc.
For a user that uses several emacs versions with the same config, the
packages for version X will be in .emacs.d/elpa/X and the packages for
version Y will be in .emacs.d/elpa/Y.  This is instead of using the same
.emacs.d/elpa and possibly having copmiled elisp packages the are
incompatible with one of the emacs versions in use.

Rollback directories are also separated by version:
.cache/.rollback/24.5, .cache/.rollback/24.4, etc.
@bmag
Copy link
Collaborator Author

bmag commented Jul 13, 2016

I've rebased the PR and made the feature optional. It is turned off by default, and controlled by a new dotspacemacs variable dotspacemacs-enable-multiple-emacs-version. Note that Emacs has to be restarted for changes to take effect (SPC f e R is not enough).

@syl20bnr should I add any documentation or tests?

@d12frosted
Copy link
Collaborator

Once it's in, I can remove following snippet from my init.el:

;; setup package-user-dir to allow seamless switch between emacs versions
(setq package-user-dir (file-name-as-directory
                        (concat d12-path/spacemacs-home "elpa/" emacs-version)))

Though it's a good thing to use minor version as well!

@syl20bnr
Copy link
Owner

@bmag that's ok, we have very few functional tests so don't bother with it for now. No need for additional doc.

I don't think a minor version is required but given the frequency of Emacs releases we could include it as well by default to be safe.

@TheBB
Copy link
Collaborator

TheBB commented Aug 13, 2016

Thanks! Cherry-picked in develop. You can safely delete your branch.

Note some changes made in 36f3b63 after discussing with @syl20bnr.

@TheBB TheBB closed this Aug 13, 2016
@bmag bmag deleted the multiple-elpa-dirs branch August 13, 2016 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants