2009-11-03 8 views
5

Ho un makefile nella directory root del progetto. Se sto modificando un file in una sottodirectory, come faccio a invocare rendere da EMACS? M-x compile make non funzionerà come si cerca il makefile nella directory corrente. Ma ho il makefile nella directory root del progetto.Invocazione di makefile nella directory radice del progetto dalla sottodirectory da Emacs

Qualche idea?

Modifica

Come suggerito, make -f fullpath_to_makefile ha fatto il trucco. Ma ho alcuni include nel makefile come "test/module.mk" che non è riuscito. Sta cercando la directory "test" nella sottodirectory. Questo può essere risolto specificando il percorso completo nel makefile. Ma non penso che sia una buona soluzione. Qualche approccio migliore?

risposta

5

La funzione M-x compile guarda la compile-command-variable che è possibile ignorare sul promt - quindi basta sostituirlo con qualcosa di simile a

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

e lasciare che corrono.

ho spesso anche utilizzare un file di intestazione (in linea 1), come

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

che si può generalizzare a piacimento con diverse opzioni. Dopo aver ricaricato il file, M-x compile eseguirà il comando di compilazione personalizzato che trovo molto utile.

+0

Grande. L'ho fatto funzionare. Aggiunto "(setq compile-command" (cd ~/fullpath_to_project_root/&& make && cd -) ")" nel file .emacs. Sembra che potrebbe essere necessario provare EDE e impostare comandi specifici del progetto. Ma questo è abbastanza per ora. Grazie ancora. –

+0

In realtà, preferisco compile-command in ogni file sorgente. In questo modo vengono impostati quando caricati - perfetti in una directory come ~/cpp/misc/dove potrei aver bisogno di Boost per i file di test, Qt per gli altri ecc. Pp. Ma se hai sempre bisogno dello stesso comando di compilazione ~/.emacs è valido pure. –

1

Quando uso Emacs per compilare il minibuffer sembra qualcosa del genere;

fanno -k

e ho appena aggiungere qualsiasi testo che mi piace, come ad esempio -f ../../root/Makefile. Questo potrebbe funzionare per te.

Mark

+0

L'opzione -f ha funzionato. Ma nel makefile, ho alcuni include come "include tests/module.mk" e lamenta che non riesce a trovare la directory "tests". Sta cercando "test" nella sottodirectory. Quindi sembra che ho bisogno di usare il percorso completo ovunque. Grazie per la risposta. –

1

io non sono molto di un utente emacs, ma si potrebbe passare make -C ../ o comunque molte directory fino è necessario andare?

+0

Questo verrà eseguito make nella directory principale. Appu vuole eseguire make nella directory locale, usando il makefile nella directory root. – Beta

+0

Sospetto fortemente che non sia ciò che Appu vuole davvero, in quanto un Makefile che funziona solo quando * non * viene eseguito dalla propria directory è borderline folle. Questa è la tecnica corretta per eseguire makefile da "altrove". –

+0

1) Nessuno (prima di te) ha suggerito un Makefile che funziona solo quando * non * viene eseguito dalla propria directory. 2) Questo non è il modo di eseguire Makefile da qualche altra parte-- PROVALO. – Beta

2

Uso EDE (da CEDET) per definire i progetti e memorizzare i comandi di compilazione nella definizione del progetto. Guardare a my config per esempi: righe 105-133 - esempi di progetti, linee 135-165 - codice, che definisce funzioni di compilazione e linee 168-189 - funzioni per diversi tipi di progetti - standard (compilare dalla directory principale), e cmake (compilazione in directory separata)

+0

Grazie. Sfortunatamente, EDE non funziona alla mia fine. Non riesco a vedere il menu del progetto. Ho già seguito il tuo articolo ma non è stato utile per EDE. –

0

Questo dovrebbe farlo:

 
make -f path_to_rootdir/Makefile -I path_to_rootdir/tests 

il -f dice che cosa makefile da utilizzare, il -I gli dice dove cercare i file da includere nel il makefile (che non si trova nella directory locale).

+0

Potrebbe funzionare, ma tutti gli strumenti di produzione avranno la loro directory di lavoro impostata in un punto diverso dal previsto. La tecnica corretta è l'opzione -C, come i dettagli opello di seguito. O mettere un comando cd nel comando di compilazione M-x stesso, come spiegato in precedenza da Dirk. –

+0

Hai sbagliato, signor Ross, su tutti e tre i punti. – Beta

+0

Argomento senza prove. Basta controllare la pagina man se non mi credi; l'argomento -f specifica il makefile, non cambia la directory di lavoro. L'opzione -I è un trucco per aggirare il problema per ** farsi da solo **, ma non da nessuno dei processi che genera. Se hanno dipendenze da cwd (la maggior parte fanno), non funzioneranno correttamente. –

0

Inizia con M-x compile RET. Quando richiede un comando, inserisci cd /path/to/root && make e premi Invio. Questo comando funziona per tutte le varianti di make e gestisce il problema "incluso makefile" senza alcun flag aggiuntivo.

La prossima volta che si digita M-x compile RET, questa nuova stringa verrà presentata come predefinita, quindi è sufficiente premere Invio. Se hai la possibilità di compilare più progetti all'interno di emacs, puoi utilizzare M-p e M-n per spostarti avanti e indietro nella cronologia dei domini di compilazione.

+0

Grazie. L'ho aggiunto al file di inizializzazione di emacs e tutto funziona ora. –

+0

Il mio punto era che non è necessario fare personalizzazioni .emacs. Tuttavia, ci sono più soluzioni per ogni problema di emacs, quindi se hai trovato qualcosa che funziona, è abbastanza buono. –

1

Dopo un po 'di diversi tentativi per rendere EDE lavorare nel modo che volevo, sono andato per .dir-locals.el:

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

l'ho trovato un po' meglio per me che avere un // -*- -*- in un colpo di testa di ogni file, e molto meglio di specificare nel mio init.el (o in qualsiasi altra configurazione) quelli ede-cpp-root-project con percorsi completi ai progetti, che creo troppo spesso o si spostano all'improvviso :)

Una bella aggiunta allo schema è stata cmake che rende gli errori di compilazione "corretti correttamente" poiché utilizza percorsi completi nei makefile generati.

3

(io uso scons, ma il principio è lo stesso. Cambiare SConstruct al Makefile e scons per fare ...)

Ho personalizzato da Emacs in modo che compila sempre il progetto che contiene il buffer corrente file, comunque profondamente annidato; cerca verso l'alto per il primo SConstruct e lo usa come directory principale del progetto.

Ecco un paio di funzioni che cercano la gerarchia di directory in cerca di 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))) 

È quindi possibile modificare la compile-command da usare per esempio project-root

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

Grazie! Uso Scon al lavoro, ma faccio l'elis e questo funziona magnificamente per me. – user511493

2

Un'altra alternativa è quella di fissare la compilazione -process-setup-funzione variabile documentata come:

funzione da chiamare per personalizzare il processo di compilazione. Questa funzione viene richiamata immediatamente prima dell'avvio del processo di compilazione. È possibile utilizzare per impostare qualsiasi variabile o funzione utilizzata mentre elabora l'output del processo di compilazione. La funzione è chiamata con le variabili compilation-window ' associata rispettivamente al buffer di compilazione e alla finestra.

Io uso Maven molto e ho scritto questa libreria per supportare il tuo problema per un contesto Maven. Nel seguito, modificare il valore della compilazione ricerca di file variabile a seconda dei casi:

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

È grandioso, grazie! –

1

Ho appena iniziato a lavorare su un più generico, estensibile e robusto ma ancora ragionevolmente veloce-e-sporco soluzione che ho appena creato. È un po 'basato sull'esempio Maven sopra, ma preferisco non andare in giro con le variabili globali, quindi uso le forme speciali let o let * molto di più. E ovviamente usa make.

Al momento supporta solo i Makefile ma è possibile aggiungere una clausola al (cond) modulo speciale nella funzione `my-compilation-process-setup-function 'se si desidera supportare uno o più sistemi di compilazione aggiuntivi.

Ha anche stringhe doc!

Lo vedrete allo my Github alla fine.