28.3 Subshells for Compilation

This section includes various techniques and advice for using a shell and its features in compilation buffers. This material is specific to local compilations, and will most probably not work in (or be irrelevant to) compilation buffers whose default directory is on remote hosts.

The M-x compile command uses a shell to run the compilation command, but specifies the option for a noninteractive shell. This means, in particular, that the shell should start with no prompt. If you find your usual shell prompt making an unsightly appearance in the *compilation* buffer, it means you have made a mistake in your shell’s init file by setting the prompt unconditionally. (This init file may be named .bashrc, .profile, .cshrc, .shrc, etc., depending on what shell you use.) The shell init file should set the prompt only if there already is a prompt. Here’s how to do it in bash:

if [ "${PS1+set}" = set ]
then PS1=…
fi

And here’s how to do it in csh:

if ($?prompt) set prompt = …

If you want to customize the value of the TERM environment variable passed to the compilation subshell, customize the variable comint-terminfo-terminal (see Shell Mode Options).

Emacs does not expect a compiler process to launch asynchronous subprocesses; if it does, and they keep running after the main compiler process has terminated, Emacs may kill them or their output may not arrive in Emacs. To avoid this problem, make the main compilation process wait for its subprocesses to finish. In a shell script, you can do this using ‘$!’ and ‘wait’, like this:

(sleep 10; echo 2nd)& pid=$!  # Record pid of subprocess
echo first message
wait $pid                     # Wait for subprocess

If the background process does not output to the compilation buffer, so you only need to prevent it from being killed when the main compilation process terminates, this is sufficient:

nohup command; sleep 1

On MS-DOS, asynchronous subprocesses are not supported, so M-x compile runs the compilation command synchronously (i.e., you must wait until the command finishes before you can do anything else in Emacs). See Emacs and MS-DOS.