Strona 1 z 1

C++ - własny plik makefile

: 26 lutego 2010, 20:25
autor: kubika
Witam.
Jestem początkującym, programistą, który dopiero zaczyna swoją przygodę. Mam następujący problem, muszę napisać plik Makefile, który będzie operował na takiej strukturze danych:

Kod: Zaznacz cały

NazwaProjektu/src/*.cpp
             /inc/*.h
             /obj/*.o
             /Makefile
             /PlikWykonywalny_lub_biblioteka
Mój projekt składa się z 2 plików main.cpp oraz modul.cpp oraz modul.h umieszczonych w odpowiednich folderach.
Napisałem coś takiego:

Kod: Zaznacz cały

dzialania.out: main.o modul.o
	g++ -o dzialania.out main.o modul.o

modul.o: modul.cpp
	g++ -c src/modul.cpp

main.o: main.cpp 
	g++ -c src/main.cpp
Niestety polecenie ,,make'' wyrzuca mi błąd informując iż nie wie gdzie jest plik main.cpp. Zupełnie natomiast nie wiem jak spowodować by obiekty, które tworzy lądowały do odpowiedniego katalogu. Z góry dziękuję za pomoc.

: 26 lutego 2010, 20:41
autor: grum
Ja korzystam z http://www.gnu.org/software/make/manual/
tam masz wszystko napisane, co i jak z przykładami

: 26 lutego 2010, 21:05
autor: kubika
Oczywiści przeglądałem podręczni systemowy ale nie umiałem wyłowić tego co mi potrzebne. Na dodatek zupełnie nie pojmuję basha.

: 26 lutego 2010, 21:31
autor: grum
Przeczytaj to :
http://pl.wikibooks.org/wiki/C/Wi%C4%99 ... mpilowaniu
Dokumentacje proponuje jednak poczytać trochę, może nie od deski do deski, ale wyrywkowo. Samo przeglądanie nic Ci nie da ...

: 26 lutego 2010, 21:42
autor: kubika
W tym tekście na wiki jest tylko przykład gdy wszystkie pliki są w jednym katalogu a przecież nie o to mi chodzi.

: 10 marca 2010, 23:39
autor: danadam
Skoro masz wszystko w różnych katalogach, to w Makefile'u musisz podać te ścieżki do plików. Można poprawić twój przykład na pałę:

Kod: Zaznacz cały

dzialania.out: obj/main.o obj/modul.o
	g++ -o dzialania.out obj/main.o obj/modul.o

obj/modul.o: src/modul.cpp
	g++ -c -o obj/modul.o src/modul.cpp

obj/main.o: src/main.cpp 
	g++ -c -o obj/main.o src/main.cpp
Można go trochę "ucywilizować":

Kod: Zaznacz cały

dzialania.out: obj/main.o obj/modul.o
	g++ -o $@ $^

obj/modul.o: src/modul.cpp
	g++ -c -o $@ $<

obj/main.o: src/main.cpp 
	g++ -c -o $@ $<
(nie sprawdzałem czy te dwa powyższe zadziałają). Można też zrobić tak:

Kod: Zaznacz cały

FILES = main.cpp modul.cpp

OBJS := $(patsubst %.cpp,%.o,$(FILES))
OBJS := $(addprefix obj/,$(OBJS))

CPPFLAGS += -Iinc/

dzialania.out: $(OBJS)
        $(CXX) -o $@ $^

obj/%.o: src/%.cpp
        $(CC) -c $(CPPFLAGS) -o $@ $<
(ten działa, sprawdzałem). Dzięki temu dodanie nowego pliku źródłowego to będzie modyfikacja jednej linijki (FILES = ...). Wadą powyższych rozwiązań jest to, że pliki źródłowe (cpp) nie mają wyszczególnionych zależności od plików nagłówkowych (h). make nie zauważy jeśli zmodyfikujemy tylko plik nagłówkowy i nic więcej. Nie przekompiluje projektu. Takie coś:

Kod: Zaznacz cały

# $(call make-depend, source-file, object-file, depend-file)
define make-depend
$(CC) -MM -MF $(3) -MP -MT $(2) $(CPPFLAGS) $(1)
endef


FILES = main.cpp modul.cpp

OBJS := $(patsubst %.cpp,%.o,$(FILES))
OBJS := $(addprefix obj/,$(OBJS))

CPPFLAGS += -Iinc/

dzialania.out: $(OBJS)
        $(info $@ $^)
        $(CXX) -o $@ $^

obj/%.o: src/%.cpp
        $(call make-depend, $<, $@, $(subst .o,.d,$@))
        $(CC) -c $(CPPFLAGS) -o $@ $<

-include $(subst .o,.d,$(OBJS))
rozwiązuje ten problem. Funkcja make-depend generuje pliki *.d w katalogu obj/, które zawierają zależności dla plików źródłowych. Na końcu Makefile'a dołączamy te pliki (include), dzięki czemu make ma pełne informacje o zależnościach.