2012-12-03 16 views
6

ho una struttura di directory seguente nel mio progetto:buone pratiche di Makefile

bin/ 
dist/ 
include/ 
├── module_a/ 
└── module_b/ 
Makefile 
src/ 
├── module_a/ 
└── module_b/ 

cartella include/ contiene *.hpp 's mentre *.cpp' s sono in src/. Vorrei compilare tutte le fonti a bin/ e quindi collegarle insieme a dist/. Sembra un desiderio abbastanza ragionevole per me.

Mi piacerebbe conoscere le migliori pratiche per un Makefile per questo caso. Tutto quello che posso trovare è il target %.o: %.cpp, ma questo non funziona, a causa della diversa cartella sorgente e binaria.

stavo cercando di usare qualcosa di simile:

D_SRC = src 
D_BIN=bin 

F_CPP := $(shell find $(D_SRC) -iname '*.cpp' -type f) 
F_OBJ := $(shell echo $(F_CPP) | sed s:\ :\\n:g | sed s:$(D_SRC):$(D_BIN): | sed 's:^\(.*\)\.cpp$$:\1\.o:') 

$(F_OBJ): $(F_SRC)                 
    $(foreach file, $(F_SRC), \              
     $(GXX) $(CXXFLAGS) -c $(file)\            
    ) 

Questo obiettivo non funziona, perché $(F_OBJ) percorsi iniziano con bin/, mentre foreach compila fonti al corrente dir lavorare. Potrei farlo compilare a bin/, ma ciò accadrebbe solo con alcune altre espressioni sed ed è abbastanza brutto com'è.

Probabilmente è così difficile per me, perché non conosco lo make tutto bene, ma non posso essere l'unico con questa configurazione di progetto. Secondo me, deve essere piuttosto comune. So che posso scrivere uno Makefile separatamente per ogni modulo, ma è davvero la scelta migliore qui?

EDIT: Ora mi chiedevo cosa avrei ottenuto con diversi Makefile. Se uno era alla radice e un altro in src/module_a, come avrebbe saputo quest'ultimo sullo bin/? Se lo si eseguisse con make -f src/module_a/Makefile, sarebbe come eseguirlo dalla directory principale, perché la directory di lavoro sarebbe root. Un altro modo, immagino, sarebbe quello di cambiare directory prima di eseguirlo, in questo modo: make -C include/module_a, ma in tal caso, come troverà bin/? Non vorrei avere qualcosa come D_BIN = ../../bin in un Makefile.

+0

Aggiornato la mia risposta ... –

risposta

6

Cosa faccio di solito è avere un Makefile nella directory src (che può essere richiamato dal livello superiore Makefile se vi piace) e poi utilizzare le regole in questo modo:

D_BIN = ../bin 
$(D_BIN)/%.o: %.cpp 

Si potrebbe anche sperimentare con solo un makefile nella directory di livello superiore, e le regole di utilizzo che assomigliano a questo:

D_BIN = bin 
D_SRC = src 
$(D_BIN)/%.o: $(D_SRC)/%.cpp 

ma non ho usato queste regole, in modo da non conoscere i pro/contro vs il modo in cui io di solito faccio. Il modo in cui faccio di solito funziona bene, ho anche regole che costruire dipende in questo modo:

$(D_BIN)/%.d: %.cpp 

e dello Stato collegamento sarebbe come:

../dist/outexe: $(F_OBJ) 

Utilizzando un foreach di solito è visto di buon occhio perché non fa uso di tutte le funzionalità incorporate nelle normali regole del makefile (cioè non esiste un controllo dipendente per file, o si costruisce tutto o niente), e come tale foreach dovrebbe essere usato solo come ultima risorsa, ma in questo caso caso sarai in grado di farlo funzionare senza il foreach.

Oltre a questo ci sono modi molto più semplici per compilare gli elenchi di file, non è necessario utilizzare la shell o sed.

F_CPP = $(wildcard *.cpp) 
F_OBJ = $(F_CPP:.cpp=.o) 

Aggiornamento: Ecco come ho normalmente controversa prevede ricorsive:

SUBDIRS = src 
.PHONY: $(SUBDIRS) 
all: $(SUBDIRS) 

$(SUBDIRS): 
    @echo "Building [email protected]" 
    $(MAKE) -C [email protected] $(MFLAGS) 

Poi in effetti nel vostro submake, si avrebbe bisogno di utilizzare ../bin per esempio.

Tuttavia, con un progetto semplice come la vostra, si potrebbe essere meglio solo avere uno makefile al livello principale e utilizzando le regole in questo modo:

D_BIN = bin 
D_SRC = src 
$(D_BIN)/%.o: $(D_SRC)/%.cpp 

makefiles ricorsive sono ok (ok ma non eccezionale) se si ha una struttura di directory molto complessa, dove si aggiungerà/rimuoverà/modificherà nuove dir alberi con il passare del tempo. Ma per un semplice progetto in cui si desidera solo avere directory separate per codice e objs, è probabilmente eccessivo.

+0

Questo sembra tutto quello che stavo cercando. Non posso testarlo adesso, ma per quanto posso dire, funzionerà. Grazie mille. –

Problemi correlati