make a Makefile
http://kvik.sh.cvut.cz/~fidlej/cecko/makefile/referat.html
Upozornění:
Popisuji GNU verzi make.
Úlohou utility make je rozpoznat jaká část projektu potřebuje
překompilovat a provést potřebné kroky k překompilování.
"make" bez parametrů hledá v aktuálním adresáři soubor GNUMakefile,
makefile nebo Makefile.
Bude se snažit provést první pravidlo tvaru:
cíl: předpoklady
<tab>příkazy
Cíl musí být rekompilován jestliže neexistuje, nebo je starší než
předpoklady.
Ukázka Makefile:
------------------------------------------------------------------------
# vse za '#' je komentar
CFLAGS = -Wall
program: main.o net.o gui.o
$(CC) $(CFLAGS) -o $@ main.o net.o gui.o
main.o: main.c net.h gui.h
net.o: net.c net.h
gui.o: gui.c gui.h
clean:
rm -f program main.o net.o gui.o
------------------------------------------------------------------------
ukazka.tar.gz
adresář s ukázkou
Vysvětlení
- nastavení proměnné CFLAGS.
- na čem je závislý 'program', souborech main.o, net.o a guio.
Následující řádek je příkaz, který se provede pokud bude některý
soubor novějšího data než 'program'. Musí byt odsazen tabulatorem!
$(CC) znamená obsah proměnné CC, defaultně nastavené CC=cc
$@ se rozvine jako text před dvojtečkou.
Takže:
cc -Wall -o program main.o net.o gui.o
Pro každou řádku příkazů se spustí nový shell.
Pokud chceme, aby se příkazy ovlivňovaly napíšeme je za sebou.
./mimo/zde:
cd mimo; touch zde
Další řádky definují závislosti jednotlivých .o souborů.
Pokud zkusíme "make", uvidíme
cc -Wall -c -o main.o main.c
cc -Wall -c -o net.o net.c
cc -Wall -c -o gui.o gui.c
cc -Wall -o program main.o net.o gui.o
Pokud nyní změníme soubor net.c, "make" provede již jen
cc -Wall -c -o net.o net.c
cc -Wall -o program main.o net.o gui.o
Možná se divíte, jak přišel make na příkazy pro vytvoření main.o, net.o
a gui.o.
Použije totiž implicitní pravidlo
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
$< se rozvine ve jméno prvního předpokladu
CFLAGS a CPPFLAGS jsou defaultně prázdné,
my jsme si však CFLAGS nastavili na '-Wall'
Poslední pravidlo v našem Makefile, pravidlo 'clean',
poslouží k odstranění vzniklých souborů.
"make" nám při ponechání zdrojáků jen vypíše hlášení:
make: `program' is up to date.
make clean
však vytvořené soubory smaže,
a můžeme si znovu prohlédnout kompilaci.
Make není jen pro programátory v jazyce C.
Stejně dobře pomůže Javě, TeXu, ...
------------------------------------------------------------------------
Manuál
------------------------------------------------------------------------
Proměnné
Doporučeno z písmenek, číslic a '_'.
Rozlišuje se velikost písmen (case-sensitive).
pomocí $(foo) dostaneme obsah proměnné foo
$$ je dolar
přiřazení:
foo = hodnota
foo = $(CC) -g
$(CC) se však expanduje až později
foo = $(foo) -neco
nelze, vzniká rekurze
foo := $(foo) -neco
funguje, použije se hodnota $(foo) definovaná na řádcích výše
------------------------------------------------------------------------
Automatické proměnné
$@ jméno cíle
$< jméno prvního předpokladu
$? jména předpokladů jenž jsou novější než cíl
$^ jména všech předpokladů, oddělená mezerami
------------------------------------------------------------------------
Jak prochází make Makefile
1. fáze:
projde všechny i vložené makefile, čte proměnné, implicitní
a explicitní pravidla a sestaví graf závisloti cílů na jejich
předpokladech.
2. fáze:
použije tyto strukturu k určení jaké cíle je nutné překompilovat
Co se kdy expanduje
hned = později
hned := hned
hned : hned
později
------------------------------------------------------------------------
Užitečné přepínače
-f soubor
použije se `soubor` namísto Makefile
-n
nevykonává, jen vypisuje průběh
-p
současně vypíše kompletní nastavení proměnných,
implicitních pravidel, ...
------------------------------------------------------------------------
Funkce pro zpracování textu
Volají se podobně jako proměnné
$(funkce argumenty)
$(subst from,to,text) substituce
$(patsubst pattern,replacement,text)
% v pattern představuje lib. posloupnost znaků
% v replacement odpovídá této množině
př.: $(patsubst %.c,%.o,main.c bar.c)
$(var:pattern=replacement)
je ekvivalentní
$(patsubst pattern,replacement,$(var))
př.: CLASSES = $(SOURCES:.java=.class)
$(wildcard pattern)
názvy souborů odpovídají pattern, jako v shellu
př.: SOURCES = $(wildcard *.java)
------------------------------------------------------------------------
Nakonec předkládám můj oblíbený Makefile.
# Univerzalni Makefile pro jednoduche projekty
# Zkompiluje vsechny *.cpp do jedne binarky.
# Our program name
PROGRAMS = ourprogram
# C++ compiler
CC = g++
CFLAGS = -g # -pg -O2 # -I/usr/X11R6/include
# The linker flags
LDFLAGS = # -L/usr/X11R6/lib
# Added library
LOADLIBES = # -lm -lGL -lGLU
# Warning flags for C programs
WARNCFLAGS = -Wall -Wshadow -Wpointer-arith \
-Wcast-qual -Wcast-align -Wmissing-prototypes \
-Woverloaded-virtual # -W
# Warning for linker
WARNLD = -Wbad-function-cast -Wstrict-prototypes -Wmissing-declarations
# All the .cpp files
SOURCES = $(wildcard *.cpp)
# And the corresponding .o files
OBJECTS = $(SOURCES:.cpp=.o)
# The first target in the makefile is the default target. It's usually called
# "all".
all: $(PROGRAMS)
# We assume we have one program (`ourprogram') to build, from all the object
# files derived from .cpp files in the current directory.
$(PROGRAMS): $(OBJECTS)
$(CC) $(WARNCFLAGS) $(WARNLD) $(CFLAGS) $(LDFLAGS) -o $(PROGRAMS) $(OBJECTS) $(LOADLIBES)
# Include known dependecies from -MMD
-include $(OBJECTS:.o=.d)
# How to make *.o files
%.o: %.cpp
$(CC) -MMD $(WARNCFLAGS) $(CFLAGS) -c $<
# "clean" removes files not needed after a build.
clean:
rm -f $(OBJECTS) *.d tags gmon.out
Napsal:
Ivo Danihelka
Zdroj informaci:
GNU Make Manual