2012-12-03 11 views
6

Mam następującą strukturę katalogów w moim projekcie:Dobre praktyki Makefile

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

Folder include/ zawiera *.hpp 's podczas *.cpp' s są w src/. Chciałbym skompilować wszystkie źródła do bin/, a następnie połączyć je razem do dist/. Wydaje mi się całkiem sensowne życzenie.

Chciałbym poznać najlepsze praktyki dla pliku Makefile dla tej sprawy. Wszystko, co mogę znaleźć, to cel %.o: %.cpp, ale to nie działa, z powodu innego źródła i folderu binarnego.

starałem się używać mniej więcej tak:

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

Cel ten nie działa, ponieważ $(F_OBJ) ścieżki zacząć bin/, natomiast foreach kompiluje źródeł do bieżącego katalogu roboczego. Mogę go skompilować do bin/, ale stanie się tak tylko z kilkoma dodatkowymi wyrażeniami sed i jest wystarczająco brzydki, jak jest.

To chyba dla mnie takie trudne, ponieważ nie znam dobrze tego, make, ale nie mogę być jedynym z tym projektem. Moim zdaniem musi to być dość powszechna. Wiem, że mogę napisać Makefile dla każdego modułu osobno, ale czy to naprawdę najlepszy wybór?

EDYCJA: Zastanawiam się teraz, co chciałbym osiągnąć dzięki kilku plikom Makefile. Jeśli jedna była u podstaw, a inna w src/module_a, to w jaki sposób ta ostatnia wiedziała o bin/? Jeśli zrobiłbyś to z make -f src/module_a/Makefile, to byłby taki sam, jak wykonanie z katalogu głównego, ponieważ jego katalogiem roboczym będzie root. Innym sposobem, jak sądzę, byłoby zmienić katalog przed jego wykonaniem, tak jak: make -C include/module_a, ale w takim przypadku, jak by to było znaleźć bin/? Nie chciałbym mieć czegoś takiego jak D_BIN = ../../bin w pliku Makefile.

+0

Zaktualizowałem moją odpowiedź ... –

Odpowiedz

6

Co zwykle zrobić, to mieć Makefile w katalogu src (które mogą być wywoływane z najwyższego poziomu Makefile jeśli chcesz), a następnie użyć reguły tak:

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

Można również eksperymentować z właśnie makefile w katalogu najwyższego poziomu i zasady użytkowania, które wyglądają tak:

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

ale nie zostały wykorzystane takie zasady, więc nie wiem/minusy plusy vs drodze normalnie zrobić. Sposób, w jaki normalnie działa dobrze, mam nawet przepisy, które budować zależy tak:

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

i zasady łącza byłoby jak:

../dist/outexe: $(F_OBJ) 

Korzystanie z foreach jest zwykle mile widziana, ponieważ to nie korzysta ze wszystkich funkcji wbudowanych w normalne reguły makefile (tzn. nie ma zależnych od siebie czeków na podstawie pliku, albo budujesz wszystko albo nic), a jako takie foreach powinno być używane tylko w ostateczności, ale w tym Sprawa będzie mogła sprawić, że będzie działała bez foreach.

Oprócz tego istnieje wiele łatwiejszych sposobów na tworzenie list plików, nie trzeba używać powłoki lub sed.

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

Aktualizacja: To jest jak ja normalnie wydać rekurencyjnych marki:

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

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

Wtedy rzeczywiście w submake, trzeba by użyć ../bin na przykład.

Jednak z projektem tak prostego jak ty, może być lepiej tylko o jeden makefile na poziomie korzenia i stosując reguły tak:

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

rekurencyjne makefile są ok (ok, ale nie wielki), jeśli masz naprawdę skomplikowaną strukturę katalogów, w której z czasem będziesz dodawać/usuwać/modyfikować nowe drzewa katalogów. Ale dla prostego projektu, w którym chcesz mieć oddzielne katalogi dla kodu i objs, prawdopodobnie jest to przesada.

+0

To wygląda jak wszystko, czego szukałem. Nie mogę tego teraz przetestować, ale z tego co wiem, to zadziała. Dziękuję Ci bardzo. –

Powiązane problemy