TI/Włączanie kodu w innych językach/makefile

Z Brain-wiki

Krótkie wprowadzenie do makefile'a

Manual

Make jest programem komputerowym automatyzującym proces kompilacji programów, na które składa się wiele zależnych od siebie plików.

Program przetwarza plik reguł Makefile i na tej podstawie stwierdza, które pliki źródłowe wymagają kompilacji. Oszczędza to wiele czasu przy tworzeniu programu, ponieważ w wyniku zmiany pliku źródłowego kompilowane są tylko te pliki, które są zależne od tego pliku. Dzięki temu nie ma potrzeby kompilacji całego projektu.

Make nadaje się również do innych prac, które wymagają przetwarzania wielu plików zależnych od siebie.

Program został pierwotnie stworzony przez dr. Stuarta I. Feldmana w 1977 roku, który pracował w owym czasie w Bell Labs.

Istnieje kilka wersji make jak np.:

  • BSD make
  • GNU make
  • Microsoft make
  • Borland make

W make # zamienia tekst w komentarze.

Typowa reguła programu make

składnia

cel:składniki

komenda

Uwaga: wcięcia robimy tabulatorem (inaczej się nie uda). Na końcu makefile'a musi być znak przejścia do nowej linii.

Przykładowa reguła:

hello: hello.cc pisz.cc
	g++ hello.cc pisz.cc -o hello

Reguła ta określa sposób tworzenia pliku wykonywalnego hello z plików hello.cc i pisz.cc.

Więcej reguł:

hellobis: hellobis.o pisz.o
	gcc hellobis.o pisz.o -o hellobis

hellobis.o: hellobis.cc
	gcc -c hellobis.cc -o hellobis.o

pisz.o: pisz.c
	gcc -c pisz.cc -o pisz.o

W tym wypadku głównym plikiem docelowym jest plik hellobis. Jego składniki to pliki hellobis.o i pisz.o. Make szuka tych plików w katalogu bieżącym, jeśli jednak ich nie znajdzie to szuka reguł, które podają sposób w jaki te pliki utworzyć. W powyższym przykładzie są to dwie kolejne reguły. Make korzysta z nich, żeby utworzyć składniki reguły głównej i dopiero wtedy może utworzyć główny plik docelowy hellobis

Zmienne w pliku Makefile

W pliku Makefile można definiować zmienne, tak jak w poniższym przykładzie:

OBJS=hellobis.o pisz.o

hellobis: $(OBJS)
	g++ $(OBJS) -o hellobis

hellobis.o: hellobis.cc
	g++ -c hellobis.cc -o hellobis.o

pisz.o: pisz.cc
	g++ -c pisz.cc -o pisz.o

W tym przykładzie zdefiniowana została zmienna o nazwie OBJS i nadana jej została wartość 'hellobis.o pisz.o'. Odwołanie do zdefiniowanej zmiennej odbywa się przy pomocy znaku dolara i nawiasów okrągłych. W tym przypadku raz zdefiniowana zmienna została użyta dwukrotnie. Jeśli będziemy chcieli dodać coś do listy składników pliku hellobis to dzięki użyciu zmiennej wystarczy to zrobić raz - w definicji zmiennej OBJS.

Zmienne standardowe

W Makefile można używać wielu zmiennych zdefiniowanych standardowo. Najczęściej używane zmienne standardowe:

  1. CC — nazwa kompilatora języka C
  2. CXX — nazwa kompilatora języka C++
  3. CFLAGS — opcje kompilatora języka C
  4. CXXFLAGS — opcje kompilatora języka C
  5. LFLAGS — opcje dla linkera

Zmienne standardowe mają pewną predefiniowaną wartość (np. zmienna CC ma predefiniowaną wartość 'cc'), którą jednak można zmieniać. Oto przykład:

CXX=g++
CXXFLAGS=-g
OBJS=hellobis.o pisz.o

hellobis: $(OBJS)
	$(CXX) $(LFLAGS) $(OBJS) -o hellobis

hellobis.o: hellobis.cc
	$(CXX) $(CXXFLAGS) -c hellobis.cc -o hellobis.o

pisz.o: pisz.cc
	$(CXX) $(CXXFLAGS) -c pisz.cc -o pisz.o

Zmienne automatyczne

Zmienne automatyczne są to specjalne zmienne, które przechowują wartości zmieniające się dynamicznie w trakcie wykonywania Makefile'a, np. nazwa pliku docelowego aktualnie przetwarzanej reguły. Najczęściej używane zmienne automatyczne:

  1. < — aktualnie przetwarzany plik z listy składników (patrz przykład)
  2. @ — nazwa pliku docelowego
  3. ^ — składniki
CXX=g++
CXXFLAGS=-g
OBJS=hellobis.o pisz.o

hellobis: $(OBJS)
	$(CXX) $(LFLAGS) $^ -o $@

hellobis.o: hellobis.cc
	$(CXX) $(CXXFLAGS) -c $< -o $@

pisz.o: pisz.cc
	$(CXX) $(CXXFLAGS) -c $< -o $@

Więcej o regułach

Reguły z wzorcem

CXX=g++
CXXFLAGS=-g
OBJS=hellobis.o pisz.o

hellobis: $(OBJS)
	$(CXX) $(LFLAGS) $^ -o $@

$(OBJS):%.o:%.cc
	$(CXX) -c $(CXXFLAGS) $< -o $@

Reguły domyślne

Make posiada pewne standardowe reguły do tworzenia pewnych typów plików. W poniższym przykładzie pominięto regułę tworzenia plików '.o' z plików '.c'. Make posiada jednak standardowe, domyślne reguły tworzenia plików .o. W tym przypadku make odnajdzie w katalogu bieżącym pliki '.c', z których utworzy pliki '.o' przy pomocy polecenia '$(CXX) -c'.]

CXX=g++
CXXFLAGS=-g
OBJS=hellobis.o pisz.o

hellobis: $(OBJS)
	$(CXX) $(LFLAGS) $^ -o $@

Reguła clean

Każdy dobry plik makefile powinien posiadać regułę, która usuwa pliki pośrednie, tymczasowe, etc. powstałe podczas kompilacji. W powyższych przykładach plikami pośrednimi są pliki '.o'. Powszechnie przyjęło się, że taka reguła ma nazwę 'clean'. Oto przykład:

CXX=g++
CXXFLAGS=-g
OBJS=hellobis.o pisz.o

hellobis: $(OBJS)
	$(CXX) $(LFLAGS) $^ -o $@

clean:
	rm -f *.o

Zauważmy, że reguła clean ma pustą listę składników. Aby wywołać regułę clean używamy polecenia make clean.

Więcej plików wynikowych

CXX=g++

all: prog1 prog2

prog1: prog1.c
	$(CXX) $(CXXFLAGS) $(LFLAGS) prog1.cc -o prog1
	
prog2: prog2.c
	$(CXX) $(CXXFLAGS) $(LFLAGS) prog2.cc -o prog2

clean:
	rm -f prog1.o prog2.o

Reguła .PHONY

Reguły clean i all są regułami specjalnymi w tym sensie, że clean i all nie są nazwami plików. Gdyby jednak zdarzyło się, że w katalogu bieżącym istnieje plik o nazwie all lub clean to reguły te mogłyby nie działać! Aby temu zapobiec trzeba by poinstruować make'a, że all i clean nie są nazwami plików. Do tego celu służy specjalna reguła o nazwie .PHONY.

CXX=g++

all: prog1 prog2

prog1: prog1.c
	$(CXX) $(CXXFLAGS) $(LFLAGS) prog1.cc -o prog1
	
prog2: prog2.c
	$(CXX) $(CXXFLAGS) $(LFLAGS) prog2.cc -o prog2

clean:
	rm -f prog1.o prog2.o

.PHONY: all clean