I have subDirA with source code foo.rs. To compile code in bash I need:

$ cd subDirA
$ some-compile-command

But problem is that compiler invoked via some-compile-command prints errors in such format: subDirA/foo.rs:26:57 instead of foo.rs:26:57 and emacs always ask where to find foo.rs, which is very unproductive.

I suppose I can solve my problem with bash script that run in ../subDirA, but invoke some-compile-command in subDirA. But may be it is possible to solve problem on emacs level?

Does something like (set compilation-mode-src-root-directory exits?

I'm using Emacs 25.

  • If you call M-x cd and then set the default-directory of the buffer you are in to the directory you want and then call your compile command, or call M-x eval-expression RET (setq default-directory "/your/desired/path/") RET and then call your compile command, does that give you the desired result (abliet the current buffer has the wrong default-directory)?
    – lawlist
    Jan 27 '18 at 1:11
  • Sounds like the first thing to fix is your compiler, which is referring to files in an unusual way.
    – Ruy
    Jan 27 '18 at 1:13

At first I give a recipe for reproduction of your problem (hopefully I understood it right). Afterwards I will present a solution.

Recipe for problem reproduction

  1. Put the following C++ source code into ~/tmp/subDirA/test.cc. (The file local variable compilation-post-dir is a preparation for the solution.)
#include <iostream>

int main() {
    std::cout << "Hello world.\n";
    return 0;

  Local Variables:
  compile-command: "make all"
  compilation-post-dir: ".."
  1. Put the following source code into the file ~/tmp/subDirA/Makefile.

.phony: all
    cd ..; g++ subDirA/test.cc
  1. Switch to buffer test.cc and run M-x compile. Accept the default input make all with RET.

  2. The compilation gives you the following output in buffer *compilation*:

-*- mode: compilation; default-directory: "~/tmp/subDirA/" -*-
Compilation started at Sat Jan 27 02:25:26

make all
cd ..; g++ subDirA/test.cc
subDirA/test.cc: In function 'int main()':
subDirA/test.cc:5:18: error: 'unknown_command' was not declared in this scope
Makefile:5: recipe for target 'all' failed
make: *** [all] Error 1

Compilation exited abnormally with code 2 at Sat Jan 27 02:25:26
  1. Clicking on subDirA/test.cc:5:18: error: ... in the compilation buffer asks you for the location of subDirA/test.cc. That is what you don't want.

Possible solution

There are some restrictions for the solution.

  1. The default directory of the compilation buffer at the time point when the compilation process starts must be the same as that one for the source file. Otherwise the Makefile would be searched for in a wrong directory.
  2. After the compilation process has been started the default directory must be changed to the one which is given by the cd-command in the Makefile. I name that directory compilation-post-dir.

The required compilation-post-dir can result from very complicated constructions in the Makefile. I don't try to generate it automatically it must be given by the user. SHe can set it through the file-local variable compilation-post-dir as demonstrated in the above example.

The following lisp code manages the change of directory after the start of the compilation process in the compilation buffer.

(require 'compile)
(defvar-local compilation-post-dir nil
  "Directory becoming the new default-directory after `compilation-start'
if non-nil.")

(defun compilation-post-dir (&rest _args)
  "Setting `default-directory' after `compilation-start'.
Can be an advice for `compilation-start'."
  (when (and (stringp compilation-post-dir)
         (buffer-live-p compilation-last-buffer))
    (let ((post-dir compilation-post-dir))
      (with-current-buffer compilation-last-buffer
    (cd post-dir)))))

(advice-add 'compilation-start :after #'compilation-post-dir)

With that code installed emacs finds the buffer test.cc when you click on subDirA/test.cc:5:18: error: ... in the compilation buffer.

You can install the code in your init file if you like it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.