2009-12-30 6 views
6

Sono nuovo di Makefiles e g ++ e sono colpito da un problema durante la generazione di dipendenze dei file di progetto usando -MM flag. Sto postando il Makefile che sto usando per la tua considerazione. Per favore dai un'occhiata.Problema nella generazione delle dipendenze nel Makefile usando -MM

OUTPUT_ROOT := output/ 
SOURCE_ROOT := source/ 

TITLE_NAME := TestProj 

SOURCES := \ 
MyFile.cpp \ 
stdAfx.cpp \ 
Main.cpp \ 

OUT_DIR := $(OUTPUT_ROOT) 

OUT_O_DIR := $(OUT_DIR) 

OBJS = $(SOURCES:%.cpp=$(OUT_O_DIR)%.o) 
DEPS = $(OBJS:%.o=%.d) 
DIRS = $(subst /,/,$(sort $(dir $(OBJS)))) 
SOURCE_TARGET = $(SOURCES:%.cpp=$(SOURCE_ROOT)%.cpp) 
OUTPUT_TARGET = $(OUT_DIR)$(TITLE_NAME) 

#--------------------------------------------------------------------- 
# executables 
#--------------------------------------------------------------------- 
MD := mkdir -p 
RM := rm 
CC := g++ 

#--------------------------------------------------------------------- 
# rules 
#--------------------------------------------------------------------- 
.PHONY: clean directories objects title 

all: directories objects title 

directories: 
@$(MD) $(DIRS) 

clean: 
$(RM) -rf $(OUT_DIR) 

$(OBJS): $(SOURCE_TARGET) 
@$(CC) -c $< -o [email protected] 

$(DEPS): $(SOURCE_TARGET) 
@$(CC) -c -MM $< > $(DEPS) 

-include $(DEPS) 

objects:$(OBJS) $(DEPS) 

title: $(OBJS) 
@$(CC) $< -o [email protected] 

Ho provato diverse opzioni e mooolto molte volte. Ho cercato su Google la soluzione, ma non ho trovato nulla.

Sta usando il flag "-MM" per generare dipendenze l'opzione giusta ?? In caso contrario, suggeriscimi il modo giusto per generare le dipendenze. Volevo generare automaticamente le dipendenze perché il mio progetto ha tantissimi file. Ho pensato che fosse l'opzione migliore rispetto a scrivere manualmente la dipendenza evey.

Questi sono gli errori sto ottenendo

g++: stdAfx.d: No such file or directory 
g++: Main.d: No such file or directory 
make: *** No rule to make target `stdAfx.d', needed by `objects'. Stop. 

Grazie in anticipo.

+0

Che cosa si intende fare "DEPS = $ (OBJS:%. O =%. D)"? E perché a volte usi ': =' e qualche volta '='? –

+0

Sta creando DEPS con i nomi degli oggetti nella directory degli oggetti. Sto solo testando con entrambe le opzioni '=' e ': =', ma non so la differenza esatta con loro – Jabez

risposta

8

Sembra che si stia tentando di generare un file di dipendenza (chiamato * .d, dalle regole del makefile) per ogni file .cpp. Questa non è la mia comprensione di come viene utilizzato un file delle dipendenze.

Utilizzare l'opzione -M per generare un singolo file di dipendenze per il progetto e quindi includere il file delle dipendenze.

DEPS = $(OUR_DIR)/make.dep 

$(DEPS): $(SOURCE_TARGET) 
    @$(CC) -M $(SOURCE_TARGET) > $(DEPS) 

include $(DEPS) 

modificare vostro file di dipendenza dovrebbe dipendere anche le intestazioni

$(DEPS): $(SOURCE_TARGET) $(HEADER_TARGET) 
    @$(CC) -M $(SOURCE_TARGET) > $(DEPS) 

dove HEADER_TARGET è definito lo stesso come SOURCE_TARGET. In questo modo, quando viene modificato un file di intestazione, il file di dipendenza viene ricostruito.

+1

Grazie mcdave, questo è un trucco molto buono. Penso che generare un singolo file sia meglio che generare molto ... Grazie ancora – Jabez

+1

Voglio solo precisare che '-MM' esclude le intestazioni di sistema (più o meno) che possono rendere la compilazione più veloce dato che ci sono meno file da 1) controllare 2) processo per creare l'elenco delle dipendenze. esempio, crea foo.cpp con alcuni stl include ed esegui 'g ++ -M foo.cpp' per vederlo sputare un elenco di circa 100 dipendenze, nessuna delle quali cambia mai, ognuna delle quali dovrà verificare su ogni build. –

+0

@Robert: Grazie per il suggerimento - non lo sapevo e aggiornerò i miei makefile per renderli più efficienti! – mcdave

3

Per un principiante, stai facendo qualcosa di esotico. Dovresti iniziare a utilizzare il codice nel tuo Makefile in modo semplice e comprensibile al 100%. Anche su un grande progetto con centinaia di file non passerai molto tempo a mantenere il Makefile.

Le variabili assegnate con: = vengono immediatamente espanse - tutti i valori $ (VAR) vengono sostituiti nel valore della variabile durante l'assegnazione. Le variabili assegnate con = vengono espanse quando vengono utilizzate, in modo che possano fare cose come fare riferimento a variabili che non sono ancora state definite.

Il flag -MM per g ++ genererà una linea di dipendenza Makefile, ad es. foo.o: foo.cc foo.hh, ma non l'ho mai trovato utile. Ho avuto un obiettivo "dipendenza" fasullo che ha generato un singolo file di dipendenza. La tua idea di creare un sacco di file * .d con quelle dipendenze su una riga potrebbe funzionare, ma ti ritroverai con un sacco di quei file.

L'errore che si ottiene è da g ++, non da make. È perché stai usando $ (DEPS) come se fosse un singolo file quando è l'intero elenco di file * .d. Quello che succede è questa linea:

@$(CC) -c -MM $< > $(DEPS) 

viene espanso a:

g++ -c -MM MyFile.cpp > MyFile.d stdAfx.d Main.cpp 

mcdave appena postato il codice che ho usato per generare un file di dipendenza.È possibile cambiare lo stile singolo file di dipendenza, o cambiare il vostro comando -MM a questo:

@$(CC) -MM $< > [email protected] 

Si può anche essere necessario correggere la dichiarazione -include perché io non credo che supporta un elenco di file di includere.

+0

Grazie Ken, sto usando un singolo file ora invece di tanti file multipli. Grazie a dire il diff b/w '=' e ': =', questo sicuramente mi aiuta molto. – Jabez

Problemi correlati