2012-01-27 11 views
15

Sto codificando OCaml sotto Emacs, ne ho uno makefile nella cartella di lavoro e varie sottocartelle contenenti i file .ml. Se io lancio M-x compile e make funziona bene su un buffer di makefile, ma non funziona su un buffer di un file .ml, mi dà un errore:Come impostare la directory predefinita della compilation in Emacs?

-*- mode: compilation; default-directory: "..." -*- 
Compilation started at Fri Jan 27 18:51:35 

make -k 
make: *** No targets specified and no makefile found. Stop. 

Compilation exited abnormally with code 2 at Fri Jan 27 18:51:35 

E 'comprensibile perché il default-directory è sub- cartella che non contiene makefile. Qualcuno sa come impostare la cartella di makefile sempre come directory di compilazione predefinita?

risposta

1

Matthias Puech ha un solution che coinvolge un file .dir-local nella directory principale del progetto:

((nil . ((eval . (setq default-directory 
        (locate-dominating-file buffer-file-name 
        ".dir-locals.el") 
))))) 

E 'presumibilmente anche possibile usa qualcosa come: (shell-command-to-string "git rev-parse --show-toplevel") come quella punta più interna.

+0

No no no:/Questo interromperà tutto, incluso' find-file'. –

15

È possibile chiamare make con gli argomenti giusti:

make -C .. -k 

dove .. è il percorso del Makefile

+0

[whoa] (http://i.memeful.com/media/post/PM0aaRL_700wa_0.gif) – vagoberto

+0

Hah, cercava in giro questa domanda, e la tua risposta è la più odiosa con il senno di poi, preferirei di gran lunga sopra alla risposta _define-your-own-custom-function-with-a-hook-and-change-it-when-you-need-a-different-path_. Grazie! – agam

4

io uso uno script come questo che mi permette di correre fare da qualsiasi sub-directory (supponendo che tu sia in un ambiente simile a una posix). basta mettere questo script nella vostra PATH come qualcosa di simile "sub_make.sh" e richiamare lo stesso modo in cui si invocare make:

#!/bin/bash 

# search for project base 
INIT_DIR=`pwd` 
while [ "$PWD" != "/" ] ; do 
    if [ -e "makefile" ] ; then 
    break 
    fi 

    cd .. 
done 

if [ ! -e "makefile" ] ; then 
    echo "Couldn't find 'makefile'!" 
    exit 1 
fi 

# indicate where we are now 
echo "cd "`pwd` 
echo make "[email protected]" 

# now run make for real 
exec make "[email protected]" 
+1

è possibile modificare questo come segue: 'if [-e" makefile "] || [-e "Makefile"] || [-e "GNUmakefile"]; quindi per consentire i nomi di makefile standard ther –

8

È possibile controllare questo dall'interno di Emacs scrivendo una funzione che (temporaneamente) imposta default-directory e chiama compile.

(defun compile-in-parent-directory() 
    (interactive) 
    (let ((default-directory 
      (if (string= (file-name-extension buffer-file-name) "ml") 
       (concat default-directory "..") 
      default-directory)))) 
    (call-interactively #'compile)) 

Quando si utilizza compile-in-parent-directory tutti ml i file verranno compilati nella directory principale di dove sono. Ovviamente se sono nidificati più in profondità puoi cambiare la logica per riflettere questo. Infatti c'è uno version on the EmacsWiki che cerca le directory madri finché non trova un makefile. L'ho trovato dopo aver scritto questa risposta, altrimenti ti avrei solo indicato lì. sospiro. La cosa positiva del mio metodo è che non è specifico per make in modo da poter utilizzare lo stesso "trucco" per altri comandi.

È anche possibile modificare la chiamata da compilare in modo non interattivo se si conosce esattamente il comando desiderato. Ciò funzionerebbe particolarmente bene se è associato a una chiave nel hook della modalità appropriata.

+0

Grazie per la tua risposta ... Ho aggiunto il tuo codice a '.emacs', ma dopo 'Mx', non riesce a trovare' compile-in-parent-directory' – SoftTimur

+0

Ho messo il codice su EmacsWiki su '.emacs', premendo' F5' mi dà un errore: 'Definizione della funzione del simbolo è vuoto: loop'. – SoftTimur

+0

Per rendere la funzione disponibile per chiamate interattive con M-x, è necessario aggiungere (interattivo) come prima istruzione alla propria funzione. –

4

Questo è quello che ho in alcuni dei miei file di configurazione :)

(defun* get-closest-pathname (&optional (max-level 3) (file "Makefile")) 
    (let* ((root (expand-file-name "/")) 
     (level 0) 
     (dir (loop 
       for d = default-directory then (expand-file-name ".." d) 
       do (setq level (+ level 1)) 
       if (file-exists-p (expand-file-name file d)) 
       return d 
       if (> level max-level) 
       return nil 
       if (equal d root) 
       return nil))) 
    (if dir 
     (expand-file-name file dir) 
     nil))) 

(add-hook 'c-mode-hook 
      (lambda() 
      (unless (file-exists-p "Makefile") 
       (set (make-local-variable 'compile-command) 
        (let ((file (file-name-nondirectory buffer-file-name)) 
         (mkfile (get-closest-pathname))) 
        (if mkfile 
         (progn (format "cd %s; make -f %s" 
          (file-name-directory mkfile) mkfile)) 
         (format "%s -c -o %s.o %s %s %s" 
           (or (getenv "CC") "gcc") 
           (file-name-sans-extension file) 
           (or (getenv "CPPFLAGS") "-DDEBUG=9") 
           (or (getenv "CFLAGS") "-ansi -pedantic -Wall -g") 
           file))))))) 
+0

Grazie per la tua risposta ... Ho aggiunto il tuo codice a '.emacs', ma dopo aver lanciato emacs, mi dà un avvertimento' Avviso (inizializzazione): Si è verificato un errore durante il caricamento di '~/.emacs': Definizione della funzione del simbolo è vuoto: defun * ' – SoftTimur

+2

hm ... prova ad aggiungere (richiedere 'cl) prima di questa funzione. –

+0

Grazie Bad_ptr. Ho usato il tuo codice per avere un comando che eseguisse il comando make nella directory principale in qualsiasi modalità, non solo C, anche se il buffer era in una modalità directory. Mi piacerebbe che non facesse nulla se non trovasse la directory principale di Makefile. La mia funzione sfortunatamente esegue comunque la marca a prescindere. Potresti consigliarti? (global-set-key [F1] \t \t (lambda() \t \t (interattivo) \t \t (compilare (let ((mkfile (get-vicina-percorso))) \t \t (se mkfile \t \t (formato "cd% s; make" \t \t \t \t (file-name-directory (get-vicina-percorso)))) \t \t \t \t)))) – SFbay007

Problemi correlati