Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoking makefile in the project root directory from subdirectory from Emacs

Tags:

emacs

makefile

I have a makefile in the project root directory. If I am editing a file in a subdirectory, how do I invoke make from EMACS? M-x compile make will not work as it looks for the makefile in the current directory. But I have the makefile in the project root directory.

Any thoughts?

Edit

As suggested, make -f fullpath_to_makefile did the trick. But I have some includes in the makefile like include "tests/module.mk" which failed. It is looking for "tests" directory in the subdirectory. This can be solved by specifying fully qualified path in the makefile. But I don't think that is a good solution. Any better approaches?

like image 652
Navaneeth K N Avatar asked Nov 03 '09 17:11

Navaneeth K N


4 Answers

The M-x compile function looks up the compile-command-variable which you can override on the promt -- so just replace it with something like

(cd ../.. && make && cd -)

and let that run.

I also often use a file header (in line 1) such as

// -*- compile-command: "g++ -o myprog myprog.ccc -lfoo -lbar && ./myprog"; -*-

which you can generalize at will with different options. After reloading the file, M-x compile will execute your custom compile command which I find quite useful.

like image 95
Dirk Eddelbuettel Avatar answered Nov 02 '22 13:11

Dirk Eddelbuettel


(I use scons, but the principle is the same. Change SConstruct to Makefile and scons to make...)

I've customized by .emacs so that it always compiles the project containing the current buffer's file, however deeply nested; it searches upwards for the first SConstruct and uses that as it's project root directory.

Here's a couple of functions which search up the directory hierarchy looking for SConstruct.

;; inspired by jds-find-tags-file in http://www.emacswiki.org/emacs/EmacsTags
(defun find-sconstruct ()
"recursively searches upwards from buffer's current dir for file named SConstruct and returns that dir. Or nil if not found or if buffer is not visiting a file"
  (labels
      ((find-sconstruct-r (path)
                          (let* ((parent (file-name-directory path))    
                                 (possible-file (concat parent "SConstruct")))
                            (cond
                             ((file-exists-p possible-file)
                              (throw 'found-it possible-file))
                             ((string= "/SConstruct" possible-file)
                              (error "No SConstruct found"))
                             (t (find-sconstruct-r (directory-file-name parent)))))))
    (if (buffer-file-name)
        (catch 'found-it
          (find-sconstruct-r (buffer-file-name)))
      (error "Buffer is not visiting a file"))))


(defun project-root ()    
  (file-name-directory (find-sconstruct)))

You can then change your compile-command to use project-root e.g.

(concat "cd " (project-root) " && scons")
like image 24
gravenimage Avatar answered Nov 02 '22 13:11

gravenimage


I use EDE (from CEDET) to define projects, and store compilation commands in the project definition. Look to my config for examples: lines 105-133 -- examples of projects, lines 135-165 -- code, that defines compilation functions, and lines 168-189 -- functions for different kinds of projects -- standard (compile from root directory), and cmake (compilation in separate directory)

like image 2
Alex Ott Avatar answered Nov 02 '22 14:11

Alex Ott


Another alternative is to set the variable compilation-process-setup-function which is documented as:

Function to call to customize the compilation process. This function is called immediately before the compilation process is started. It can be used to set any variables or functions that are used while processing the output of the compilation process. The function is called with variables compilation-buffer' andcompilation-window' bound to the compilation buffer and window, respectively.

I use Maven alot and wrote this library to support your issue for a Maven context. In the following, change the value of the variable compile-search-file as appropriate:

;;; Support for Maven 2

(require 'compile)

(setq compile-search-file "pom.xml")

(defun find-search-file ()
  ;; Search for the pom file traversing up the directory tree.
  (setq dir (expand-file-name default-directory))
  (let ((parent (file-name-directory (directory-file-name dir))))
    (while (and (not (file-readable-p (concat dir compile-search-file)))
        (not (string= parent dir)))
      (setq dir parent
        parent (file-name-directory (directory-file-name dir))))
    (if (string= dir parent)
    (error "Search file %s is missing" compile-search-file)
      (with-current-buffer compilation-last-buffer
    (message "Test %s %s." compilation-buffer compilation-window)
    (setq default-directory dir)))))

;; Add the following to support Emacs' compile mode:
(add-to-list
 'compilation-error-regexp-alist-alist
 '(mvn "^\\(.*\\):\\[\\([0-9]*\\),\\([0-9]*\\)\\]" 1 2 3))
(add-to-list 'compilation-error-regexp-alist 'mvn)

(setq compilation-process-setup-function 'find-search-file)

(provide 'maven-support)
like image 2
pajato0 Avatar answered Nov 02 '22 12:11

pajato0