Subject: Re: bug#77430: compilation-start should remember shell-file-name

From: Eli Zaretskii <[email-masked]>
Date: Tue, 01 Apr 2025 18:57:06 +0300

> Cc: [email-masked]
> Date: Tue, 01 Apr 2025 18:50:36 +0300
> From: Eli Zaretskii <[email-masked]>
> 
> > From: Siyuan Chen <[email-masked]>
> > Date: Tue, 1 Apr 2025 23:13:46 +0800
> > Cc: [email-masked]
> > 
> > >  Why cannot your my/compile function do this:
> > >  
> > >  (setq-local shell-file-name "C:/msys64/usr/bin/bash")
> > >  
> > > instead of let-binding it?
> > 
> > This is only for the current file buffer. 
> > 
> > For example, if you focus on a project file buffer (e.g. test.hs) and M-x my/compile, it only sets
> > `shell-file-name' for that file buffer. However, the `compile` actually using the `shell-file-name' belongs to the
> > *compilation* buffer.
> > 
> > ```
> > (defun compilation-start (command &optional mode name-function highlight-regexp
> >                                   continue)
> >   ...
> >   (with-current-buffer outbuf ; <--- The `outbuf' is the *compilation* buffer 
> >     ...
> >     (comint-exec
> >      outbuf (compilation--downcase-mode-name mode-name)
> >      shell-file-name ; <--- use the buffer local variable shell-file-name in the *compilation* buffer 
> >      nil `(,shell-command-switch ,command))
> >     ...
> >     )
> > ...
> > )
> > ```
> > 
> > So the following code doesn't work:
> > 
> > ```
> > (defun my/compile ()
> >   (interactive)
> >   (let (
> >         (compilation-environment
> > "PATH=/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/c/Windows/System32:/c/Windows:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0/:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl")
> > 
> >         )
> >     (setq-local shell-file-name "C:/msys64/usr/bin/bash")
> >     (compile "ls")
> >     ))
> > ```
> > 
> > M-x my/compile
> > 
> > Compilation exited abnormally. 
> 
> Sorry, I don't understand: are you saying that you cannot arrange for
> the buffer-local value of shell-file-name to point to Bash and stay
> that way for the subsequent commands?  If you need to use
> with-current-buffer or something similar, it should be easy no?

Alternatively, how about making a Windows batch file, which would
invoke the compilation command via Bash.  So you compile command would
look like this:

  M-x compile RET mycomp ls RET

where mycomp.bat is a batch file which does

  @echo off
  C:\msys64\usr\bin\bash --login -c %*

I think this is the cleanest solution for problems like this on
Windows, since you don't really want to override shell-file-name, you
just want to invoke the commands via Bash.