makefile Samouczek
Pierwsze kroki z makefile
Szukaj…
Uwagi
Makefile to plik tekstowy, który kontroluje działanie programu make
. Program make
jest zwykle używany do zarządzania tworzeniem programów z ich plików źródłowych, ale może być bardziej ogólnie używany do obsługi dowolnego procesu, w którym pliki (lub cele ) muszą zostać zregenerowane po zmodyfikowaniu innych plików (lub wymagań wstępnych ). Plik makefile opisuje związek między celami i wymaganiami wstępnymi, a także określa polecenia potrzebne do zaktualizowania celu, gdy co najmniej jeden z wymagań wstępnych ulegnie zmianie. Jedynym sposobem, że make
określa „nieaktualne-ności” jest przez porównanie czasu modyfikacji plików docelowych i ich warunków.
Pliki makefile są nieco unikatowe na kilka sposobów, co może początkowo wprowadzać w błąd.
Po pierwsze, plik makefile składa się z dwóch całkowicie różnych języków programowania w tym samym pliku. Większość plików jest napisana w zrozumiałym języku, który make
zrozumienie: zapewnia to zmienne przypisywanie i rozszerzanie, niektóre funkcje preprocesora (w tym inne pliki, warunkowe analizowanie sekcji pliku itp.), A także definicję obiektów docelowych i ich warunki wstępne. Ponadto do każdego celu można przypisać przepis , który określa, które polecenia należy wywołać, aby zaktualizować ten cel. Przepis jest napisany jako skrypt powłoki (domyślnie sh POSIX). Program make
nie analizuje tego skryptu: uruchamia powłokę i przekazuje skrypt do powłoki, która ma zostać uruchomiona. Fakt, że przepisy nie są przetwarzane przez make
, ale zamiast obsługiwane przez oddzielny proces powłoki, jest kluczowa dla zrozumienia makefile.
Po drugie, makefile nie jest językiem proceduralnym jak skryptu: jak make
analizuje makefile konstruuje graf skierowany wewnętrznie gdzie cele są węzły grafu oraz wstępnych relacje są krawędzie. Dopiero po wszystkie makefile zostały gruntownie analizowany i wykres jest pełna będzie make
wyboru jednego węzła (tarcza) i próba dostosowania go do tej pory. Aby upewnić się, że cel jest aktualny, musi najpierw upewnić się, że każdy z wymagań wstępnych tego celu jest aktualny i tak dalej, rekurencyjnie.
Wersje
Nazwa | Znany również jako | Początkowa wersja | Wersja | Data wydania |
---|---|---|---|---|
Marka POSIX | 1992 | IEEE Std 1003.1-2008, edycja 2016 | 30.09.2016 | |
Marka NetBSD | bmake | 1988 | 20160926 | 26.09.2016 |
Marka GNU | gmake | 1988 | 4.2.1 | 2016-06-10 |
Marka SunPro | dmake | 2006 | 2015-07-13 | |
MSVS nmake | 2003 | 2015p3 | 27.06.2016 |
Podstawowy plik Makefile
Zastanów się nad napisaniem „witaj świecie!” program w c. Powiedzmy, że nasz kod źródłowy znajduje się w pliku o nazwie source.c. Teraz, aby uruchomić nasz program, musimy go skompilować, zwykle na Linuksie (używając gcc), musielibyśmy wpisać $> gcc source.c -o output
gdzie wyjście to nazwa pliku wykonywalnego, który ma zostać wygenerowany. W przypadku programu podstawowego działa to dobrze, ale gdy programy stają się bardziej złożone, nasze polecenie kompilacji może również stać się bardziej złożone. W tym miejscu pojawia się plik Makefile. Pliki makefile pozwalają nam napisać dość złożony zestaw reguł kompilowania programu, a następnie po prostu skompilować go, wpisując make w wierszu poleceń. Na przykład tutaj jest możliwy przykład Makefile dla powyższego przykładu hello wold.
Podstawowy plik Makefile
Zróbmy podstawowy plik Makefile i zapisz go w naszym systemie w tym samym katalogu, co nasz kod źródłowy o nazwie Makefile . Pamiętaj, że ten plik musi mieć nazwę Makefile, jednak kapitol M jest opcjonalny. To powiedziawszy, to stosunkowo standardowe użycie kapitolu M.
output: source.c
gcc source.c -o output
Zauważ, że przed poleceniem gcc w drugim wierszu znajduje się dokładnie jedna karta (jest to ważne w plikach makefiles). Gdy ten plik Makefile zostanie zapisany za każdym razem, gdy typy użytkowników make (w tym samym katalogu co Makefile) make sprawdzą, czy plik source.c został zmodyfikowany (sprawdza znacznik czasu), czy został zmodyfikowany później niż wyjście, uruchomi się reguła kompilacji w następującym wierszu.
Zmienne w Makefiles
W zależności od projektu możesz chcieć wprowadzić pewne zmienne do swojego pliku make. Oto przykład Makefile z obecnymi zmiennymi.
CFLAGS = -g -Wall
output: source.c
gcc $< $(CFLAGS) -o $@
Teraz zbadajmy, co się tutaj wydarzyło. W pierwszym wierszu zadeklarowaliśmy zmienną o nazwie CFLAGS, która zawiera kilka typowych flag, które możesz chcieć przekazać do kompilatora, zwróć uwagę, że w tej zmiennej możesz przechowywać tyle flag, ile chcesz. Następnie mamy ten sam wiersz, co przed poleceniem make, aby sprawdzić source.c, aby zobaczyć, czy został zmieniony później niż wyjście, jeśli tak, to uruchamia regułę kompilacji. Nasza zasada kompilacji jest w większości taka sama jak poprzednio, ale została skrócona przy użyciu zmiennych, zmienna $<
jest wbudowana w make (określana jako zmienna automatyczna patrz https://www.gnu.org/software/make/manual/ html_node / Automatic-Variables.html ) i zawsze oznacza źródło, więc w tym przypadku source.c . $(CFLAGS)
to nasza zmienna, którą zdefiniowaliśmy wcześniej, ale należy pamiętać, że musieliśmy umieścić zmienną w nawiasie z $ $ na początku, takim jak ten $(someVariable)
. To jest składnia mówienia Makeowi, aby rozwinął zmienną do tego, co wpisałeś wcześniej. Wreszcie mamy symbol $ @, po raz kolejny jest to zmienna wbudowana w make, i po prostu oznacza cel kroku kompilacji, więc w tym przypadku oznacza wyjście .
Czysty
Czyść to kolejna przydatna koncepcja na temat tworzenia plików. Pozwala modyfikować plik Makefile z góry
CFLAGS = -g -Wall
TARGETS = output
output: source.c
gcc $< $(CFLAGS) -o $@
clean:
rm $(TARGETS)
Jak widać, po prostu dodaliśmy jeszcze jedną regułę do naszego Makefile i jedną dodatkową zmienną, która zawiera wszystkie nasze cele. Jest to dość powszechna zasada w plikach makefile, ponieważ pozwala szybko usunąć wszystkie utworzone pliki binarne, po prostu wpisując $> make clean
. Wpisując make clean, każesz programowi make uruchomić regułę clean, a następnie make uruchomi polecenie rm, aby usunąć wszystkie cele.
Mam nadzieję, że ten krótki przegląd używania make pomaga przyspieszyć przepływ pracy, Makefile mogą stać się bardzo złożone, ale dzięki tym pomysłom powinieneś być w stanie zacząć korzystać z make i lepiej zrozumieć, co dzieje się u innych programistów Makefiles . Aby uzyskać więcej informacji na temat korzystania z make a great Resource, odwiedź https://www.gnu.org/software/make/manual/ .
Definiowanie reguł
Szybki start
Reguła opisuje, kiedy i jak tworzone są określone pliki ( cele reguły). Może również służyć do aktualizacji pliku docelowego, jeśli którykolwiek z plików wymaganych do jego utworzenia ( warunki wstępne celu ) są nowsze niż cel.
Reguły są zgodne z poniższą składnią: (Zauważ, że polecenia następujące po regule są wcięte przez tabulator )
targets: prerequisites
<commands>
gdzie cele i warunki wstępne to nazwy plików lub specjalne zastrzeżone nazwy i polecenia (jeśli są obecne) są wykonywane przez powłokę w celu budowania / przebudowywania celów, które są nieaktualne.
Aby wykonać regułę, wystarczy uruchomić komendę make
w terminalu z tego samego katalogu, w którym znajduje się plik Makefile . Uruchomienie make
bez określenia celu spowoduje wykonanie pierwszej reguły zdefiniowanej w pliku Makefile . Zgodnie z konwencją pierwsza reguła w pliku Makefile jest często nazywana wszystkim lub domyślną , zwykle wymieniając wszystkie prawidłowe cele kompilacji jako warunki wstępne.
make
wykonuje regułę tylko wtedy, gdy cel jest nieaktualny, co oznacza, że nie istnieje lub jego czas modyfikacji jest starszy niż którykolwiek z jego wymagań wstępnych. Jeśli lista wymagań wstępnych jest pusta, reguła zostanie wykonana tylko przy pierwszym wywołaniu w celu zbudowania celów. Jednak jeśli reguła nie tworzy pliku, a celem jest zmienna fikcyjna, reguła będzie zawsze wykonywana.
Reguły wzorców
Reguły wzorców służą do określania wielu obiektów docelowych i konstruowania nazw wymagań wstępnych na podstawie nazw obiektów docelowych. Są bardziej ogólne i potężniejsze niż zwykłe reguły, ponieważ każdy cel może mieć swoje własne wymagania wstępne. W regułach wzorców relacja między celem a warunkiem wstępnym jest budowana na podstawie prefiksów, w tym nazw ścieżek i sufiksów, lub obu tych elementów.
Wyobraź sobie, że chcemy budować cele foo.o
i bar.o
, kompilując odpowiednio skrypty C, foo.c
i bar.c
Można to zrobić za pomocą poniższych zwykłych zasad:
foo.o: foo.c
cc -c $< -o $@
bar.o: bar.c
cc -c $< -o $@
gdzie zmienna automatyczna $<
to nazwa pierwszego wymagania wstępnego, a $@
to nazwa celu (pełna lista zmiennych automatycznych znajduje się tutaj ).
Ponieważ jednak cele mają ten sam sufiks, powyższe dwie reguły można teraz zastąpić następującą regułą:
%.o: %.c
cc -c $< -o $@
Zasady niejawne
Niejawne reguły powiedzieć make
jak używać zwyczajowych sposobów budowania pewnych typów plików docelowych, które są używane bardzo często. make
używa nazwy pliku docelowego do ustalenia, która reguła niejawna ma zostać wywołana.
Przykład reguły wzorca, który widzieliśmy w poprzedniej sekcji, w rzeczywistości nie musi być deklarowany w pliku Makefile, ponieważ make
ma domyślną regułę dla kompilacji C. Zatem w poniższej regule wymagania wstępne foo.o
i bar.o
zostaną zbudowane przy użyciu domyślnej reguły kompilacji w C przed zbudowaniem foo
.
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Katalog ukrytych reguł i używanych przez nie zmiennych można znaleźć tutaj .
ogólna reguła gzip pliku
jeśli katalog zawiera 2 pliki:
$ ls
makefile
example.txt
i makefile
zawierają następujący tekst
%.gz: %
gzip $<
następnie możesz uzyskać example.txt.gz
, wpisując powłokę
$ make -f makefile example.txt.gz
makefile składać się z tylko jednej reguły, które instruują make jak stworzyć plik, którego nazwa koniec z .gz, czy istnieje plik o tej samej nazwie, ale z przyrostkiem .gz.
makefile Hello World
C: \ makefile:
helloWorld :
[TAB]echo hello world
uruchom wyniki:
C:\>make
echo hello world
hello world
Uwaga: [TAB] należy zastąpić rzeczywistą tabulacją, przepływ stosu zastępuje tabulatory spacjami, a spacje nie są używane tak samo jak tabulatory w pliku makefile.