project-compile not applying env when switching projects
TxGVNN opened this issue · 8 comments
Hello,
I am currently experiencing an issue with project-compile
. I usually switch to a project by call project-compile
directly.
This is my configuration:
(require 'envrc)
(setq envrc-debug t)
(envrc-global-mode)
em -Q --load config.el
When I call M-x project-compile
and select another project that has a .envrc
file, the environment does not get applied.
I have tried to debug the issue, but was unable to identify the root cause.
Thank you.
Hmmm, that case is actually tricky to address: there's no buffer in the destination ("other") project in which envrc-mode
could be activated before the process is started.
You can work around it by doing this:
(defun my/ensure-current-project (fn &rest args)
(let ((default-directory (project-root (project-current t))))
(with-temp-buffer
(envrc-mode 1)
(apply fn args))))
(advice-add 'project-compile :around #'my/ensure-current-project)
for now, but I'll have a think about how to address this more thoroughly.
One tricky thing here is that users might not have envrc-mode
enabled in every buffer — it's technically possible to decide to enable it only in certain modes or projects. But the above solution assumes that if envrc-mode
is enabled in the calling project, you would want it enabled in the destination/other project — that's not really a valid assumption in all cases, even if most users would just enable envrc-global-mode
.
Note also that project-async-shell-command
and project-shell-command
are probably also broken in the same way: you could add further advice-add
lines for them, as above.
It works. Thank you very much.
Hmmm, that case is actually tricky to address: there's no buffer in the destination ("other") project in which
envrc-mode
could be activated before the process is started.
But a question, I check *envrc-debug*
and see the env is loaded, why do we still need trick with new temp buffer?
Yes, I think you're saying that envrc-mode
is active in the resulting compilation buffer, and that's true, but it looks like compile
actually has some code which propagates the calling buffer's local environment to the compilation buffer and wipes out the changes applied there by envrc
!
The sequence in compile
is this:
- The caller's local env and path are noted
- A compilation buffer is created
- The compilation mode is initialised in that buffer, which causes
envrc-mode
to read and apply the local env for that directory compile
copies the caller's local env and path into the buffer- The compilation process is started
So it's all a bit unfortunate, because the compile
author was trying to do the right thing, but ends up subverting it for your use case. In fact, if you followed the rule that when you call a process-starting command, you always want to use the caller's environment, we could say this is the correct behaviour. However, project-compile
and friends have different (somewhat unusual) semantics, hence the mismatch.
Thank you for taking time to explain to me. I understood more.
Me too — until you asked, I didn't actually realise that envrc-mode
was enabled in the resulting buffer, so figuring out what was happening was useful to me.