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
- 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";
unknown_command();
return 0;
}
/*
Local Variables:
compile-command: "make all"
compilation-post-dir: ".."
End:
*/
- Put the following source code into the file
~/tmp/subDirA/Makefile
.
#!/bin/bash
.phony: all
all:
cd ..; g++ subDirA/test.cc
Switch to buffer test.cc
and run M-x compile
. Accept the default input make all
with RET.
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
unknown_command();
^
Makefile:5: recipe for target 'all' failed
make: *** [all] Error 1
Compilation exited abnormally with code 2 at Sat Jan 27 02:25:26
- 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.
- 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.
- 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.
M-x cd
and then set thedefault-directory
of the buffer you are in to the directory you want and then call your compile command, or callM-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)?