2009-11-03 2 views
5

Ich habe ein Makefile im Projektstammverzeichnis. Wenn ich eine Datei in einem Unterverzeichnis bearbeite, wie rufe ich make von EMACS auf? M-x kompilieren make wird nicht funktionieren, da es nach dem Makefile im aktuellen Verzeichnis sucht. Aber ich habe das Makefile im Projektstammverzeichnis.Aufruf von Makefile im Projektstammverzeichnis aus Unterverzeichnis von Emacs

Irgendwelche Gedanken?

bearbeiten

Als vorgeschlagen, make -f fullpath_to_makefile der Trick. Aber ich habe einige Includes in der Makefile wie "Tests/module.mk", die fehlgeschlagen sind. Es sucht nach "Tests" Verzeichnis im Unterverzeichnis. Dies kann durch Angabe eines vollständig qualifizierten Pfads im Makefile gelöst werden. Aber ich denke nicht, dass das eine gute Lösung ist. Irgendwelche besseren Ansätze?

Antwort

5

Die M-x compile Funktion sucht die compile-command-variable die Sie auf der promt außer Kraft setzen kann - so ersetzen Sie es nur mit so etwas wie

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

und dass die freien Lauf lassen.

Ich benutze auch oft eine Datei-Header (in Zeile 1) wie

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

, die Sie nach Belieben mit verschiedenen Optionen verallgemeinern können. Nach dem Neuladen der Datei führt M-x compile Ihren benutzerdefinierten Kompilierbefehl aus, den ich für sehr nützlich halte.

+0

Großartig. Ich habe das zum Laufen gebracht. Hinzugefügt "(setq compile-command" (cd ~/fullpath_to_project_root/&& make && cd -) ")" in die .emacs-Datei. Sieht so aus, als müsste ich vielleicht EDE ausprobieren und projektspezifische Befehle setzen. Aber das ist genug für jetzt. Danke noch einmal. –

+0

Eigentlich bevorzuge ich in jeder Quelldatei den Kompilierbefehl. Auf diese Weise werden sie beim Laden geladen - perfekt in einem Verzeichnis wie ~/cpp/misc/wo ich Boost für Testdateien, Qt für andere usw. brauchen kann. Pp. Aber wenn Sie immer den gleichen Kompilierbefehl benötigen wie die ~/.emacs gilt auch. –

1

Wenn ich Emacs verwende, um den Minibuffer zu kompilieren, sieht ungefähr so ​​aus;

machen -k

und ich fügen Sie einfach einen beliebigen Text ich, wie -f ../../root/Makefile mögen. Dies könnte für Sie funktionieren.

Mark

+0

Der -f-Schalter hat den Trick gemacht. Aber im Makefile habe ich einige Includes wie "include tests/module.mk" und es beschwert sich, dass es das Verzeichnis "tests" nicht finden kann. Es sucht nach "Tests" im Unterverzeichnis. Sieht so aus, als müsste ich überall einen voll qualifizierten Pfad verwenden. Danke für die Antwort. –

1

ich nicht viel von einem Emacs-Benutzer bin, aber könnten Sie -C machen passieren ../ oder wie viele Verzeichnisse nach oben müssen Sie gehen?

+0

Dadurch wird make im Stammverzeichnis ausgeführt. Appu möchte make im lokalen Verzeichnis ausführen, wobei das Makefile im Stammverzeichnis verwendet wird. – Beta

+0

Ich vermute stark, dass das nicht das ist, was Appu wirklich will, da ein Makefile, das nur funktioniert, wenn * nicht * aus seinem eigenen Verzeichnis läuft, grenzwertig verrückt ist. Dies ist die richtige Technik zum Ausführen von Makefiles von "woanders". –

+0

1) Niemand (vor Ihnen) hat ein Makefile vorgeschlagen, das nur funktioniert, wenn * nicht * aus einem eigenen Verzeichnis läuft. 2) Dies ist nicht die Art, Makefiles von woanders zu starten-- VERSUCH ES. – Beta

2

Ich verwende EDE (von CEDET), um Projekte zu definieren und Kompilierungsbefehle in der Projektdefinition zu speichern. Schauen Sie sich die Beispiele my config an: Zeilen 105-133 - Beispiele für Projekte, Zeilen 135-165 - Code, der Kompilierungsfunktionen definiert, und Zeilen 168-189 - Funktionen für verschiedene Arten von Projekten - Standard (Kompilieren aus dem Stammverzeichnis) und cmake (compilation in separaten Verzeichnis)

+0

Danke. Leider arbeitet EDE nicht an meinem Ende. Ich kann das Projektmenü nicht sehen. Ich habe Ihren Artikel bereits verfolgt, aber EDE hat nicht geholfen. –

0

Dies sollte es tun:

 
make -f path_to_rootdir/Makefile -I path_to_rootdir/tests 

die -f es sagt, was Make-Datei zu verwenden, sagt die -I es, wo nach Dateien suchen in einbezogen werden das Makefile (das nicht im lokalen Verzeichnis ist).

+0

Das mag funktionieren, aber bei allen von make ausgeführten Tools wird das Arbeitsverzeichnis anderswo als erwartet eingestellt. Die richtige Technik ist die Option -C, wie unten beschrieben. Oder einen cd-Befehl in den M-x-Kompilierbefehl selbst eingeben, wie Dirk oben erklärt. –

+0

Sie irren sich, Mr. Ross, in allen drei Punkten. – Beta

+0

Argument ohne Beweise. Schau einfach auf die Manpage, wenn du mir nicht glaubst; Das Argument -f gibt das Makefile an, es ändert nicht das Arbeitsverzeichnis. Die Option -I ist ein Hack, um dieses Problem für ** sich selbst ** zu umgehen, aber nicht für die Prozesse, die es hervorbringt. Wenn sie Abhängigkeiten von cwd haben (die meisten tun), werden sie nicht richtig funktionieren. –

0

Beginnen Sie mit M-x compile RET. Wenn Sie nach einem Befehl gefragt werden, geben Sie einfach cd /path/to/root && make ein und drücken Sie die Eingabetaste. Dieser Befehl funktioniert für alle Varianten von make und behandelt das "included makefile" -Problem ohne zusätzliche Flags.

Das nächste Mal, wenn Sie M-x compile RET eingeben, wird diese neue Zeichenfolge als Standard angezeigt, sodass Sie nur return drücken müssen. Auf der vagen Hoffnung, dass Sie mehrere Projekte innerhalb Emacs aktiv kompilieren sind, können Sie verwenden M-p und M-n nach rückwärts und vorwärts durch die Geschichte der Kompilierung comamnds zu bewegen.

+0

Danke. Ich habe das zur emacs Initialisierungsdatei hinzugefügt und alles funktioniert jetzt. –

+0

Mein Punkt war, dass Sie keine .emacs Anpassungen vornehmen müssen. Es gibt jedoch mehrere Lösungen für jedes Emacs-Problem. Wenn Sie also etwas gefunden haben, das funktioniert, ist das gut genug. –

1

Nach einer Weile verschiedenen Versuche, EDE die Art und Weise funktioniert Ich wollte, ging ich für .dir-locals.el:

((c++-mode . ((compile-command . "make -C ../build -j2 whatever"))))

Ich fand es für mich etwas besser als ein // -*- -*- in einem Kopf mit Jede Datei, und eine ganze Menge besser als die Angabe in meiner init.el (oder einer anderen Konfig) diese ede-cpp-root-project mit vollen Pfaden zu Projekten, die ich entweder zu oft erstellen oder plötzlich bewegen :)

Schöne Ergänzung zu dem Schema war cmake, die Kompilierungsfehler zu "ordnungsgemäß Jumpable" macht, da es vollständige Pfade in generierten Makefiles verwendet.

3

(ich benutze scons, aber das Prinzip ist das gleiche. SConstruct Wechseln Sie in Makefile und scons zu machen ...)

Ich habe von .emacs angepasst, so dass es immer das Projekt kompiliert ist der aktuelle Puffer, der Datei, jedoch tief verschachtelt; Es sucht nach dem ersten SConstruct und verwendet es als Projektstammverzeichnis.

Hier ein paar Funktionen, die die Verzeichnishierarchie für SConstruct suchen suchen Sie nach oben.

;; 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))) 

Sie können dann Ihre compile-commandproject-root zu verwenden, ändern z.B.

(concat "cd " (project-root) " && scons") 
+0

Danke! Ich benutze Scons bei der Arbeit, aber ich lutsche bei elisp, und das funktioniert wunderbar für mich. – user511493

2

Eine weitere Alternative ist die Variable Kompilierung-Prozess-Setup-Funktion, die dokumentiert ist gesetzt als:

Funktion des Übersetzungsvorgangs anpassen zu nennen. Diese Funktion wird unmittelbar vor dem Start des Übersetzungsvorgangs aufgerufen. Es können alle Variablen oder Funktionen eingestellt werden, die verwendet werden, während die Ausgabe des Prozesses compilation Verarbeitung. Die Funktion wird genannt mit Variablen compilation-buffer' and Compilation-Fenster‘ die Zusammenstellung Puffer und Fenster gebunden ist.

Ich benutze Maven viel und schrieb diese Bibliothek, um Ihr Problem für einen Maven-Kontext zu unterstützen. Im Folgenden ändern Sie den Wert der Variablen Kompilierung-search-Datei entsprechend:

;;; 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) 
+0

Das ist großartig, danke! –

1

Ich habe gerade angefangen auf eine allgemeinere, erweiterbare Arbeits und robuste, aber dennoch ziemlich schnell und unsaubere Lösung, die ich gerade erstellt habe. Es basiert etwas auf dem obigen Maven-Beispiel, aber ich bevorzuge es, nicht mit globalen Variablen herumzualbern, deshalb benutze ich die Sonderformen let oder let * viel mehr. Und natürlich nutzt es make.

Derzeit unterstützt es nur Makefiles, aber Sie können dem (cond) speziellen Formular in der Funktion `my-compilation-process-setup-function 'eine Klausel hinzufügen, wenn Sie ein oder mehrere zusätzliche verschiedene Build-Systeme unterstützen wollen.

Es hat sogar Doc-Strings!

Sie werden es schließlich unter my Github sehen.