\documentclass[aspectratio=169]{beamer} \usetheme{metropolis} \usepackage{lmodern} \usepackage[czech]{babel} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{graphicx} \usepackage{wrapfig} \usepackage{color} \usepackage{mathtools} \usepackage{hyperref} \usepackage{amsmath} \usepackage{minted} \usepackage{tikz} \usetikzlibrary{positioning} \hypersetup{ colorlinks, citecolor=black, filecolor=black, linkcolor=black, urlcolor=black } \title{Makefile od základu až po pokročilé} \author{Karel Kočí} \date{14.10.2018} \begin{document} \frame{\titlepage} \begin{frame}[fragile] \frametitle{Co je Makefile?} \begin{itemize} \item Předpis pro program make \item Sada skriptů popisujících vznik souborů \item Sada závislostí mezi soubory \item A vše ostatní ... \end{itemize} Pozor: gmake vs make! \end{frame} \begin{frame}[fragile] \frametitle{Jednoduchý Makefile} \begin{minted}[frame=lines]{make} FILE=pres $(FILE).pdf: $(FILE).tex $(patsubst %.svg,%.pdf,$(wildcard *.svg)) pdflatex -shell-escape $< %.pdf: %.svg inkscape -D -z --file=$< --export-pdf=$@ --export-latex clean: ls | grep -v -E "($(FILE).tex|makefile|scheme|svg|png|eps)$$" \ | xargs rm -rf \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Základní syntaxe} \begin{minted}[frame=lines]{make} .PHONY: all all: foo ; foo: utils.o foo.o foo: cc -o $@ $^ foo.o utils.o: %.o: %.c cc -c -o $@ $< \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Závislosti a rebuild} \begin{figure}[!h] \centering \begin{tikzpicture} \node[color=red] (all) {all}; \node (foo) [below = 1cm of all] {foo}; \node (fooo) [below left = 1cm and 1cm of foo] {foo.o}; \node (utilso) [below right = 1cm and 1cm of foo] {utils.o}; \node[color=gray] (fooc) [below = 1cm of fooo] {foo.c}; \node[color=gray] (utilsc) [below = 1cm of utilso] {utils.c}; \path [->] (all) edge node {} (foo); \path [->] (foo) edge node {} (fooo); \path [->] (foo) edge node {} (utilso); \path [->] (fooo) edge node {} (fooc); \path [->] (utilso) edge node {} (utilsc); \end{tikzpicture} \end{figure} \end{frame} \begin{frame}[fragile] \frametitle{Automatické proměnné} \begin{minted}[frame=lines]{make} foo: main.o foo: foo.o utils.o cc -o $@ $^ \end{minted} \begin{itemize} \item \begin{verbatim}$@\end{verbatim} foo \item \begin{verbatim}$<\end{verbatim} foo.o \item \begin{verbatim}$^\end{verbatim} utils.o foo.o main.o \end{itemize} \url{www.gnu.org/software/make/manual/html_node/Automatic-Variables.html} \end{frame} \begin{frame}[fragile] \frametitle{Proměnné} \begin{minted}[frame=lines]{make} SRC := main.c foo.c OBJ = $(patsubst %.c,%.o,$(SRC)) SRC += utils.c \end{minted} \begin{itemize} \item FOO = přiřazení ale doplnění až při použití \item FOO := přiřazení a okamžité doplnění \item FOO += přidání obsahu do proměnné \item FOO ?= přiřaď pokud proměnná neexistuje \end{itemize} \end{frame} \begin{frame}[fragile] \frametitle{Generická pravidla} \begin{minted}[frame=lines]{make} %.h: %.bin xxd -i $< > $@ goo.h: %.h: %.bin sed 's/foo/goo/g' $< | xxd -i - > $@ conf.h: conf.h.m4 m4 $< > $@ \end{minted} \begin{minted}[frame=lines]{shell} $ make foo.h $ make goo.h $ make conf.h \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Podmínky} \begin{minted}[frame=lines]{make} ifeq ($(DEBUG),y) CFLAGS += -ggdb endif ifdef DEBUG CFLAGS += -ggdb endif \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Funkce} \begin{minted}[frame=lines]{make} SRC := $(wildcard *.c) OBJ := $(patsubst %.c,%.o,foo.c bar.c) \end{minted} \url{www.gnu.org/software/make/manual/html\_node/Functions.html#Functions} \end{frame} \begin{frame}[fragile] \frametitle{define, call a eval} \begin{minted}[frame=lines]{make} define PROJECT $(1): $(1)_SRC cc $$($(1)_LDFLAGS) -o $@ $^ $(1)_SRC: %.o: %.c cc $$($(1)_CFLAGS) -c -o $@ $< endef foo_SRC := foo.c utils.c foo_LDFLAGS := -lm foo_CFLAGS := -Iinclude $(eval $(call PROJECT,foo)) \end{minted} \end{frame} \section[Doporučení a tipy]{} \begin{frame}[fragile] \frametitle{MAKEFLAGS a deaktivace vestavěných pravidel} \begin{minted}[frame=lines]{make} MAKEFLAGS += --no-builtin-rules --no-builtin-variables \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Q a skrývání příkazů} \begin{minted}[frame=lines]{make} Q ?= @ clean: @echo " CLEAN build" $(Q)$(RM) -r build \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{O a výstupní složka} \begin{minted}[frame=lines]{make} O ?= . $(O)/foo: foo.c @mkdir -p $(@D) cc -o $@ $^ \end{minted} \begin{minted}[frame=lines]{make} FOO_PATH = "../foo-project" MAKEARGS := -C "$(FOO_PATH)" O="$(shell pwd)" --no-print-directory Q ?= @ .PHONY: all $(MAKECMDGOALS) all $(MAKECMDGOALS): $(Q)$(MAKE) $(MAKEARGS) $@ \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Generované závislosti} \begin{minted}[frame=lines]{make} DEP := $(patsubst %.c,$(O)/%.d,$(SRC)) ifeq (,$(filter clean,$(MAKECMDGOALS))) -include $(DEP) $(DEP): $(O)/%.d: src/%.c @mkdir -p "$(@D)" @echo " DEP $@" $(Q)$(CC) -MM -MG -MT '$*.o $@' $(CFLAGS) $< -MF $@ endif \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Přepisovatelné nástroje} \begin{minted}[frame=lines]{make} PREFIX ?= avr- CC ?= $(PREFIX)gcc LD ?= $(PREFIX)ld \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{HOST vs TARGET} \begin{minted}[frame=lines]{make} HOST ?= TARGET ?= avr HOST_CC ?= $(HOST)gcc TARGET_CC ?= $(TARGET)gcc \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Automatické odstranění mezi-souborů!} \begin{minted}[frame=lines]{make} pres.pdf: pres.tex $(patsubst %.svg,%.pdf,$(wildcard *.svg)) pdflatex -shell-escape $< %.pdf: %.svg inkscape -D -z --file=$< --export-pdf=$@ --export-latex %.svg: %.dot dot -Tsvg $< > $@ \end{minted} \end{frame} \begin{frame}[fragile] \frametitle{Pár bodů na závěr} \begin{itemize} \item Implementujte help target \item Vyvarujte se definici targetů v define \item Nikdy nepředpokládejte pořadí provádění \item Počátejte s cross-kompilací \item A pokud má jazyk který používáte již existující build systém tak použijte ten \end{itemize} \end{frame} \begin{frame} \Large Děkuji za pozornost. \vspace{2cm} \url{www.gnu.org/software/make/manual/make.html} \end{frame} \end{document}