Makefile – HowTo

Makefile jest plikiem tekstowym, który został stworzony do ułatwienia kompilacji programów. Każdy kto kompilował paczkę z oprogramowaniem pod linuksem nieraz wydawał polecenie „make„. Dziś pokażę jak stworzyć taki plik oraz przedstawię prosty przykład do czego możemy użyć plików makefile.

Jak wspomniałem budowa plików makefile jest bardzo prosta. Reguły mają następujący wzorzec budowy:

CEL: SKLADNIKI
	POLECENIA

„CEL” – oznacza nasz cel, nazwę reguły.

SKLADNIKI – oznacza z czego zbudujemy nasz cel.

„POLECENIA” –  określa nam w jaki sposób zbudujemy cel ze składników.

Reguły podstawowe

Pierwszą regułą jest reguła „all” wykonuje się ona po wydania polecenia bez parametru.

Reguła wypisująca prosty tekst:

all:
    @echo "Nasz"

Jeżeli chcemy wykonać kilka reguł wpisujemy nazwy reguł do listy składników.

all: first second
    @echo "drugi tekst"

first:
    @echo "To jest "

second:
    @echo "nasz"

Kompilacja aplikacji pozostawia masę śmiecia do wyczyszczenia folderu możemy użyć reguły „clean„.

#
# Reguła czyści nam strukturę z katalogów używanych przy kompilowaniu.
#
clean:
    rm -rf docs/
    rm -rf runtime/
    rm -rf build/

Aby reguła clean zadziałała poprawnie nie może być katalogu o nazwie reguły.

Dyrektywa .PHONY

W folderze gdzie znajduje się nasz plik Makefile, nie może być katalogów ani plików o nazwach reguł. Aby uniknąć takich problemów możemy dodać kłopotliwą nazwę do reguły .PHONY. Reguła ta mówi co ma być traktowane jak reguła.

.PHONY: clean all docs

Zmienne

Zmienne definiujemy jak w poniższym przykładzie. Make posiada swoje predefiniowane zmienne. Jednak w tym przykładzie pominiemy je.

CC=gcc

hellomake: hellomake.o hellofunc.o
    $(CC) -o hellomake hellomake.o hellofunc.o -I.

Dynamiczne zmienne

Zmienne dynamiczne / automatyczne – są zmiennymi które zmieniają się w trakcie wykonywania reguły.

CC=gcc
CFLAGS=-g
OBJS=hello.o aux.o

hello: $(OBJS)
	$(CC) $(LFLAGS) $^ -o $@

hello.o: hello.c
	$(CC) $(CFLAGS) -c $< -o $@

aux.o: aux.c
	$(CC) $(CFLAGS) -c $< -o $@

<  – Aktualny plik z listy składników

@ – Nazwa pliku docelowego

^ – Wkleja listę składników

Powyższy przykład możemy skrócić używając zmiennych dynamicznych z wzorcem:

$(OBJS): %.o: %.c
	$(CC) -c $(CFLAGS) $< -o $@

Kolejne dodanie obiektu do kompilowania naszego programu sprowadza się do dopisania nazwy naszego pliku do zmiennej OBJS

Przykład

Makefile możemy używać np. do prostej automatyzacji wysyłania plików na serwer. W poniższym przykładzie usunąłem zbędne dane, aby nie zaśmiecać niepotrzebnie naszego skryptu.

SRC_DIR=src
DIST_DIR=dist
UPLOAD_DIR=/home/example/public_html/download

all: get_dependency configure compile run

get_dependency:
    sudo apt-get install libxml libjpeg1.0.0
    pip install -r requirements.txt

configure:
    python ./ansible_dynamic_inventory.py > $(DIST_DIR)/config.json

compile:
    pyinstaller $(SRC_DIR)/main.py

run:
    ./$(DIST_DIR)/main

build_pkg:
 make_pkgs.sh

upload:
 scp $(DIST_DIR)/debian_pkgs/*.deb upload@download.example.org:$(UPLOAD_DIR)

clean:
        rm -rf docs/_build
        rm -rf runtime
        rm -rf cermp/cermp/__pycache__

.PHONY: clean all docs

Wydając polecenie „make” uruchamiamy kolejno:

  1. pobieranie i instalowanie zależności
  2. Konfigurowanie aplikacji
  3. Kompilację kodu
  4. Uruchamiamy

Jeżeli nasza aplikacja działa – musimy ją przygotować do publikacji:

$ make build_pkg

Kopiowanie paczek na nasz serwer rozpocznie się po wydaniu polecenia

$ make upload

W razie pytań – służę pomocą

Comments

comments

Comments

Leave a Reply

You must be logged in to post a comment.