Wyszukiwanie w witrynie

Krótkie wprowadzenie do „plików Makefile” w tworzeniu oprogramowania typu open source za pomocą GNU Make


GNU Make to narzędzie programistyczne, które określa części określonej bazy kodu, które mają zostać ponownie skompilowane i może wydawać polecenia umożliwiające wykonanie tych operacji na bazie kodu. Tego konkretnego narzędzia make można używać z dowolnym językiem programowania, pod warunkiem, że ich kompilacja może zostać przeprowadzona z poziomu powłoki za pomocą poleceń.

Aby używać GNU Make, musimy mieć jakiś zestaw reguł definiujących relacje pomiędzy różnymi plikami w naszym programie oraz polecenia aktualizacji każdego pliku. Są one zapisywane w specjalnym pliku o nazwie „makefile”. Polecenie „make” wykorzystuje bazę danych „makefile” i czasy ostatniej modyfikacji plików w celu podjęcia decyzji w którym wszystkie pliki mają zostać ponownie skompilowane.

Zawartość pliku Makefile

Ogólnie „pliki makefile” zawierają 5 rodzajów rzeczy, a mianowicie: reguły ukryte, reguły jawne, definicje zmiennych , wytyczne i komentarze.

  1. Jawna reguła określa, jak utworzyć/przerobić jeden lub więcej plików (zwanych obiektami docelowymi, zostanie to wyjaśnione później) i kiedy to zrobić.
  2. Ukryta reguła określa, jak utworzyć/przerobić jeden lub więcej plików na podstawie ich nazw. Opisuje, w jaki sposób nazwa pliku docelowego jest powiązana z jednym plikiem o nazwie podobnej do nazwy docelowej.
  3. Definicja zmiennej to linia określająca wartość ciągu znaków dla zmiennej, która ma zostać później zastąpiona.
  4. Dyrektywa to instrukcja dla make, aby podczas czytania pliku makefile zrobił coś specjalnego.
  5. Symbol „#” oznacza początek komentarza w plikach makefile . Linia rozpoczynająca się od „#” jest po prostu ignorowana.

Struktura plików Makefile

Informacje, które mówią make, jak przekompilować system, pochodzą z odczytu bazy danych zwanej makefile. Prosty makefile będzie składał się z reguł o następującej składni:

target ... : prerequisites ... 
	recipe 
... 
...

cel definiuje się jako plik wyjściowy wygenerowany przez program. Mogą to być także fałszywe cele, co zostanie wyjaśnione poniżej. Przykładami plików docelowych są pliki wykonywalne, pliki obiektowe lub fałszywe cele, takie jak czyste, zainstaluj, odinstaluj itp.

Warunkiem jest plik używany jako dane wejściowe do tworzenia plików docelowych.

Przepis to akcja wykonywana przez make w celu utworzenia pliku docelowego w oparciu o wymagania wstępne. Przed każdym przepisem w makefiles konieczne jest wstawienie znaku tabulacji, chyba że określimy zmienną „.RECIPEPREFIX” w celu zdefiniowania innego znaku jako przedrostka do przepisu.

Przykładowy plik Makefile

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f main.o end.o inter.o start.o

W powyższym przykładzie użyliśmy plików źródłowych 4 C i dwóch plików nagłówkowych do stworzenia pliku wykonywalnego final. Tutaj każdy plik „.o” jest zarówno celem, jak i warunkiem wstępnym w makefile. Teraz spójrz na ostatnią nazwę docelową clean. Jest to po prostu akcja, a nie plik docelowy.

Ponieważ zwykle nie potrzebujemy tego podczas kompilacji, nie jest to zapisane jako warunek wstępny w żadnych innych regułach. Cele, które nie odnoszą się do plików, ale są po prostu działaniami, nazywane są fałszywymi celami. Nie będą miały żadnych wymagań wstępnych, jak inne pliki docelowe.

Jak GNU Make przetwarza plik Makefile

Domyślnie make zaczyna się od pierwszego celu w „makefile” i nosi nazwę „domyślny cel”. Biorąc pod uwagę nasz przykład, naszym pierwszym celem jest ostateczny. Ponieważ jego wymagania wstępne obejmują inne pliki obiektowe, należy je zaktualizować przed utworzeniem wersji final. Każdy z tych warunków wstępnych jest przetwarzany według własnych zasad.

Ponowna kompilacja ma miejsce, jeśli w plikach źródłowych lub plikach nagłówkowych zostaną wprowadzone modyfikacje lub jeśli plik obiektowy w ogóle nie istnieje. Po ponownej kompilacji niezbędnych plików obiektowych, make decyduje, czy ponownie połączyć final , czy nie. Należy to zrobić, jeśli plik final nie istnieje lub jeśli którykolwiek z plików obiektowych jest od niego nowszy.

Zatem jeśli zmienimy plik inter.c, to po uruchomieniu make przekompiluje on plik źródłowy w celu aktualizacji plik obiektowy inter.o, a następnie link final.

Używanie zmiennych w plikach Makefile

W naszym przykładzie musieliśmy dwukrotnie wyświetlić wszystkie pliki obiektowe w regule końcowej, jak pokazano poniżej.

final: main.o end.o inter.o start.o
	gcc -o final main.o end.o inter.o start.o

Aby uniknąć takich duplikacji, możemy wprowadzić zmienne przechowujące listę plików obiektowych używanych w makefile. Używając zmiennej OBJ możemy przepisać przykładowy plik makefile na podobny, pokazany poniżej.

OBJ = main.o end.o inter.o start.o
final: $(OBJ)
	gcc -o final $(OBJ)
main.o: main.c global.h
	gcc -c main.c
end.o: end.c local.h global.h
	gcc -c end.c
inter.o: inter.c global.h
	gcc -c inter.c
start.o: start.c global.h
	gcc -c start.c
clean:
	rm -f $(OBJ)

Zasady czyszczenia katalogu źródłowego

Jak widzieliśmy w przykładzie makefile, możemy zdefiniować reguły oczyszczania katalogu źródłowego poprzez usuwanie niechcianych plików obiektowych po kompilacji. Załóżmy, że mamy plik docelowy o nazwie czysty. Jak sprawić rozróżnienie powyższych dwóch sytuacji? Tutaj pojawia się koncepcja fałszywych celów.

fałszywy cel to taki, który w rzeczywistości nie jest nazwą pliku, a raczej nazwą przepisu, który ma zostać wykonany za każdym razem, gdy zostanie wysłane wyraźne żądanie z pliku make<. Jednym z głównych powodów używaniafałszywego celu jest uniknięcie konfliktu z plikiem o tej samej nazwie. Innym powodem jest poprawa wydajności.

Aby to wyjaśnić, ujawnię jeden nieoczekiwany zwrot akcji. Przepis na clean nie zostanie domyślnie wykonany po uruchomieniu make. Zamiast tego należy wywołać to samo, wydając polecenie make clean.

.PHONY: clean
clean:
	rm -f $(OBJ)

Teraz spróbuj utworzyć pliki make dla własnej bazy kodu. Zachęcamy do komentowania tutaj ze swoimi wątpliwościami.