\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}
