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

emacs: disable trampoline generation when installing packages #109370

Closed
wants to merge 1 commit into from

Conversation

collares
Copy link
Member

@collares collares commented Jan 14, 2021

In gccemacs, installing packages using elpa2nix-install-package sometimes causes trampolines to be compiled even if we are not running batch-native-compile. This happens, for example, when a package does a toplevel add-advice. Since we do not have EMACSNATIVELOADPATH set up when installing packages (and I believe we do not want to have it set up because native compilation is supposed to be a separate step), there won't be an output directory for the compiled trampoline. This is blocking emacsGcc in the overlay, see nix-community/emacs-overlay#74 (comment).

  • Built on platform(s)
    • NixOS

@collares
Copy link
Member Author

cc @tadfisher

@tadfisher
Copy link
Contributor

I guess I'm confused; if package-native-compile is nil, shouldn't comp-enable-subr-trampolines be set to nil during package-unpack? I wouldn't expect us to have to set that explicitly.

@collares
Copy link
Member Author

collares commented Jan 15, 2021

package-native-compile is a package.el option that defaults to nil, while comp-enable-subr-trampolines is a native-comp option that defaults to t. If you have a file containing (advice-add 'top-level :before 'identity), merely loading that file anywhere will trigger a trampoline compilation in gccemacs (even in batch mode!) unless you explicitly disable it. I will probably ask the maintainer soon if comp-enable-subr-trampolines should default to nil in non-interactive mode, but I wanted to space out my emails to bug-gnu-emacs :)

To be clear, the present PR is just a workaround. Failing to compile a trampoline didn't previously result in package installation failing (as evidenced by the fact that trampolines have always failed to compile during package installation in the gccemacs Nix setup). But in current gccemacs, any error during package installation (including demoted errors that wouldn't normally result in non-zero exit codes) triggers a bug related to autoloads in gccemacs, and this one causes another error that results in a non-zero exit code when compiling git-commit recent changes in package.el caused such an error to interrupt package installation. I asked about the trampoline compilation behaviour.

@collares
Copy link
Member Author

collares commented Feb 1, 2021

Update: Changes in package.el (emacs-mirror/emacs@9973019 and emacs-mirror/emacs@7d7bfbf) made it so that certain errors (related to advices and autoloads) at package install time interrupt the installation, both in master and in feature/native-comp (I previously thought this was native-comp-specific due to a mistake in bisecting the change). The emacs-git-commit bug only manifests in emacsGcc solely because of the trampoline compilation error is native-comp-specific.

The gccemacs maintainer argues that failure to compile trampolines should be an error because it could change behaviour, and I think I agree. So for Nix I see two options:

  • Disable trampoline compilation when installing packages, thus disabling the ability to advice some primitive functions at package install time. This is what this PR implements. This in theory could change package behaviour, but very likely won't.
  • Have EMACSNATIVELOADPATH be set up before package installation, so compiling trampolines does not error out. This makes Nix compilation match the async compilation behaviour, but is a bit annoying because if package A adds an advice and package B requires package A, then the trampoline will (sometimes?) be compiled when installing package B. Therefore, is a package that uses advices is required by many others, we could have several copies of the compiled trampoline.

@tadfisher
Copy link
Contributor

tadfisher commented Feb 4, 2021

if package A adds an advice and package B requires package A, then the trampoline will (sometimes?) be compiled when installing package B.

This could be solved by appending package A's native-lisp directory after package B's in comp-eln-load-path, as the first writable directory is chosen from that list for .eln output, but all entries should be searched for .eln input. I'll give it a shot and see if that fixes the issue.

@tadfisher
Copy link
Contributor

Ah, I think I see the problem now. An alternative approach could be to exercise trampoline generation by loading the package after installing it, which I would hope would generate trampolines to all advised functions called at require-time.

@acowley
Copy link
Contributor

acowley commented Feb 15, 2021

I was running this patch for a while, but just determined that it was causing me some trouble. The actual issue I was experiencing was that company-complete wasn't working specifically on dot characters with lsp-mode as the completion backend with Rust code and rust-analyzer as the LSP server. Completion worked in other situations, and could be made to work again by using (setq load-no-native t), but no completions were offered with a dot (or colon) character. I eventually found that if I ran eval-buffer on lsp-completion.el, then completion on the dot character would work again without needing to explicitly disable loading of native code.

There were no errors or warnings obviously pointing to missing requires when compiling lsp-mode, but in staring at all the implicated code I noticed that lsp-mode.el itself has a few top-level advice-add forms. This reminded me of pulling in this patch several weeks ago, so I just tried backing it out and no longer see the problem where completions are not being offered on a dot character. I do not know how to reliably determine if native libraries are being used, so this may well be covering up some other problem.

@collares
Copy link
Member Author

collares commented Feb 15, 2021

@acowley This is very interesting, thanks for the investigation! So if this PR causes problems, I think setting up EMACSNATIVELOADPATH at package install time is the only option. I think doing so is a good option even if it duplicates trampolines, and we can always try to remove duplication later with @tadfisher's idea.

@collares collares closed this Feb 15, 2021
@collares
Copy link
Member Author

collares commented Feb 15, 2021

One idea to reduce duplication would be to try this workaround Andrea suggested in an earlier bug: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=44238#8

@flatwhatson From the above bug, I assume you were doing the trampoline precompilation for Guix packaging reasons. From your experience, are we missing a solution here? We are having trouble with packages that require other packages with top-level advices, causing trampoline compilations at package install time (the infrastructure currently expects eln files to be generated only when batch-native-compileing).

@collares
Copy link
Member Author

@acowley By the way, do you disable deferred compilation in your init file?

@acowley
Copy link
Contributor

acowley commented Feb 17, 2021

@collares I've tried it both ways several times in trying to debug things. It is disabled at this moment, but I ran with it enabled yesterday. I'm happy to try variations!

I admit I don't really understand its exact impact, so whenever I notice an issue I try it both ways with a few emacs restarts each way, and keep an eye on whether or not there's an Async compilation buffer and what it's doing.

@collares collares deleted the no-trampoline-comp branch February 19, 2021 18:14
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.

None yet

3 participants