tutorials: make_tutorial: add a GNU make $(error) example

20 views
Skip to first unread message

it...@itrs.tw

unread,
Dec 1, 2012, 8:25:17 PM12/1/12
to it...@googlegroups.com
details: http://www.itrs.tw/hg/tutorials/rev/c6f18b0e5690
changeset: 18:c6f18b0e5690
user: Scott Tsai <scot...@gmail.com>
date: Sun Dec 02 09:24:43 2012 +0800
description:
make_tutorial: add a GNU make $(error) example

diffstat:

make_tutorial.tex | 141 ++++++++++++++++++++++++++++++----------------
1 files changed, 91 insertions(+), 50 deletions(-)

diffs (286 lines):

diff -r 0eece79b94f7 -r c6f18b0e5690 make_tutorial.tex
--- a/make_tutorial.tex Sun Dec 02 02:52:53 2012 +0800
+++ b/make_tutorial.tex Sun Dec 02 09:24:43 2012 +0800
@@ -105,7 +105,7 @@
b: b.c
\end{mycommand}
則打 \code{make a} 時會建立 \code{a} , 打 \code{make b}會建立 \code{b}。
-å ªæ‰“ \code{make} 時會建立什麼呢?
+å ªæ‰“ \code{make} 時會建立什麼呢?
å˜—è©¦å¾Œç™¼ç ¾å ªå»ºç«‹ \code{a}ï¼Œå ³å ªå»ºç«‹ç¬¬ä¸€å€‹ç›®æ¨™ï¼ˆé  è¨­ç›®æ¨™ï¼‰ã€‚

è‹¥è¦ å Œæ™‚å šå‡º \code{a} å’Œ \code{b} 兩個檔案,有一個常見用法:
@@ -150,8 +150,8 @@
æ ç¤ºï¼šæ ¹è™Ÿçš„å‡½å¼ æ˜¯ sqrt() ,在 math.h 裡。

\bigbreak
-{sqrttest.c}
\begin{mycode}
+/* sqrttest.c */
#include <math.h>
#include <stdio.h>

@@ -164,10 +164,10 @@
}
\end{mycode}

-Makefile
-\begin{mycode}
-sqrttest: sqrttest.o
-\end{mycode}
+\begin{mycommand}
+# Makefile
+sqrttest: sqrttest.c
+\end{mycommand}

執行 make ï¼Œç™¼ç ¾ é€£çµ æ™‚æœŸå‡ºéŒ¯
\begin{mycommand}
@@ -189,8 +189,9 @@

修正後的 Makefile
\begin{mycommand}
+# Makefile
LDFLAGS=-lm
-sqrttest: sqrttest.o
+sqrttest: sqrttest.c
\end{mycommand}

make 輸出:
@@ -218,20 +219,22 @@

修改 Makefile,指定 CFLAGS 變數為 "-Wall":
\begin{mycommand}
+# Makefile
LDFLAGS=-lm
CFLAGS=-Wall # -Wall 是打開全部警告(Warn Allï¼‰çš„æ„ æ€
-sqrttest: sqrttest.o
+sqrttest: sqrttest.c
\end{mycommand}
å† åŸ·è¡Œ make:
\begin{mycommand}
+$ make
make: `sqrttest' is up to date.
\end{mycommand}
make 從 sqrttest 與 sqrttest.c çš„æœ€å¾Œæ›´æ–°æ™‚é–“åˆ¤æ–·ä¸ å¿…é‡ æ–°ç·¨è­¯ sqrttest,所以新加入的 "-Wall" CFLAGS 沒有作用。

æ›´æ–° sqrttest.c çš„æœ€å¾Œä¿®æ”¹æ—¥æœŸå† åŸ·è¡Œ make:
\begin{mycommand}
-touch sqrttest.c
-make
+$ touch sqrttest.c
+$ make
cc -Wall -lm sqrttest.c -o sqrttest
sqrttest.c: In function ‘main’:
sqrttest.c:7: warning: format ‘%d’ expects type ‘int *’,
@@ -242,6 +245,7 @@
從編譯器的警告,看出是 \code{scanf}, \code{printf} æ ¼å¼ å­—ä¸²çš„å• é¡Œï¼Œä¿®æ­£ sqrttest.c
{ ("\code{\%lf}" 是 \code{double} çš„æ ¼å¼ ç¬¦è™Ÿ)}
\begin{mycode}
+/* sqrttest.c */
#include <math.h>
#include <stdio.h>

@@ -259,63 +263,81 @@

\section{ä½¿ç”¨åˆ¥äººå¯«å¥½çš„å‡½å¼ åº«}
\subsection{以 allegro為例}
-allegroæ˜¯ä¸€å€‹é Šæˆ²å‡½å¼ åº«ï¼Œå®ƒæ ä¾›è ²éŸ³ï¼Œå½±åƒ ï¼Œé µç›¤è¼¸å…¥ç­‰åŠŸèƒ½ã€‚
-在 Fedora 或 其他系統 下使用allegroçš„å‡½å¼ å¿…é ˆå®‰è£ ï¼Œå› ç‚ºè¼‰å…¥çš„å‡½å¼ æ”¾ç½®åœ¨å…¬å…±çš„åœ°æ–¹ã€‚
-在 Fedoraæˆ‘å€‘åœ¨å‘½ä»¤åˆ—æ‰“å…¥ä»¥å®‰è£ (devel 是 開發(development))。
+allegroæ˜¯ä¸€å€‹é Šæˆ²å‡½å¼ åº«ï¼Œå®ƒæ ä¾›è ²éŸ³ï¼Œå½±åƒ ï¼Œé µç›¤è¼¸å…¥ç­‰åŠŸèƒ½ã€‚åœ¨ Fedora ä¸‹è¦ å®‰è£ åœ¨å‘½ä»¤åˆ—æ‰“
\begin{mycommand}
-sudo yum -y install allegro-devel
+$ sudo yum -y install allegro-devel
\end{mycommand}

-ç¨‹å¼ æ¯ ç”¨ä¸€å€‹å‡½å¼ åº«ï¼Œå®ƒçš„ Makefile çš„ \code{CLFAGS}, \code{LDFLAGS} å°±è¦ å¤šåŠ ä¸€äº›å€¼ã€‚
-allegro æ ä¾› allegro-config ç¨‹å¼ å¹«åŠ©æˆ‘å€‘è¨­å®š Makefile。
+è‹¥å‡½å¼ åº«å « \emph{X},在 Fedora ä¸‹ç”¨å®ƒä¾†é–‹ç™¼ç¨‹å¼ æ™‚è¦ å®‰è£ çš„å¥—ä»¶å ç¨±é€šå¸¸å « \emph{X}-devel。 "devel" 是 development 的縮寫。
\bigbreak
-{è®“æˆ‘å€‘å¯¦é©—ä¸€ä¸‹å §ã€‚}

-在命令列打入 allegro-config --cflags,allegro-config --libs,
+ç¨‹å¼ æ¯ ç”¨ä¸€å€‹å‡½å¼ åº«ï¼Œå®ƒçš„ Makefile çš„ \code{CLFAGS}, \code{LDFLAGS} å°±è¦ å¤šåŠ ä¸€äº›å€¼ã€‚allegro æ ä¾› allegro-config ç¨‹å¼ å¹«åŠ©æˆ‘å€‘è¨­å®š Makefile。
+\bigbreak

-å¾—åˆ°çš„å­—ä¸²å°±æ˜¯æˆ‘å€‘è¦ æ”¾å…¥CFLAGS, LDFLAGS çš„å­—ä¸²ï¼Œä½†é€™æ¨£å šæœªå… å¤ªéº»ç…©ã€‚
+在命令列打入 \code{allegro-config --cflags,allegro-config --libs}ï¼Œå¾—åˆ°çš„å­—ä¸²å°±æ˜¯æˆ‘å€‘è¦ æ”¾å…¥CFLAGS, LDFLAGS çš„å­—ä¸²ï¼Œä½†é€™æ¨£å šæœªå… å¤ªéº»ç…©ã€‚
å ¯ä»¥åœ¨ Makefile 中加入
\bigbreak
-Makefile

\begin{mycommand}
+# Makefile
CFLAGS= -g -Os -Wall $(shell allegro-config --cflags)
LDFLAGS= -lm $(shell allegro-config --libs)
-main: main.o
+allegro-program: allegro-program.c
\end{mycommand}

-\code{\$shell} æ˜¯å€‹ç‰¹æ®Šçš„å‡½å¼ ï¼Œå ¯ä»¥åŸ·è¡Œå®Œç¨‹å¼ å¾Œå›žå‚³å…¶å€¼ï¼Œè€Œ \code{\$} ä»£è¡¨è®Šæ•¸çš„æ„ æ€ ã€‚
-
-整個就是回傳 \code{allegro-config} 執行後的值
-
-
-é€™æ¨£å°±å®Œæˆ å¼•å…¥å¤–éƒ¨å‡½å¼ åº«å•¦ã€‚
+\code{shell} 是 make çš„å…§å»ºå‡½å¼ ï¼Œå ¯ä»¥åŸ·è¡Œå®Œç¨‹å¼ å¾Œå›žå‚³å…¶å€¼ã€‚æ­¤è™•ç”¨ä¾†å¾—åˆ° \code{allegro-config} 執行後的值,加在 CFLAGS å¾Œé ¢ã€‚

\subsection{以 gtk為例}
å®‰è£ åœ¨å‘½ä»¤åˆ—æ‰“å…¥
\begin{mycommand}
-sudo yum -y install gtk2-devel
+$ sudo yum -y install gtk2-devel
+\end{mycommand}
+
+pkg-config 類似 allegro-configï¼Œä½†é€šç”¨æ–¼å¾ˆå¤šå‡½å¼ åº«
+\begin{mycommand}
+$ pkg-config gtk+-2.0 --cflags
+-pthread -I/usr/include/gtk-2.0 <...>
\end{mycommand}

修改 Makefile
-
-Makefile
\begin{mycommand}
-CFLAGS = -g -Os -Wall $(shell pkg-config gtk+-2.0 --cflags)
-LDFLAGS = -lm $(shell pkg-config gtk+-2.0 --libs)
-main: main.o
+# Makefile
+CFLAGS = -g -Os -Wall $(shell pkg-config gtk+-2.0 --cflags)
+LDFLAGS = -lm $(shell pkg-config gtk+-2.0 --libs)
+gtk-program: gtk-program.c
\end{mycommand}

-æ¯”è¼ƒæ–°çš„å‡½å¼ åº«éƒ½æ”¹ç”¨ {pkg-config} çµ±ä¸€ç®¡ç †ï¼Œæ‰€ä»¥è¦ è¨˜å¾—åŠ ä¸Šå‡½å¼ åº«çš„å 字如上。
+æ–°çš„å‡½å¼ åº«å¤šä½¿ç”¨ pkg-config,見 \code{pkg-config --list-all}。
+
\section{Posix make}
-Posix make çš„è¦ å‰‡é™¤äº†ç›®æ¨™è¦ å‰‡(Target Rules)å¤–ï¼Œé‚„æœ‰æŽ¨ç †è¦ å‰‡ (Inference Rules),
+Posix make çš„è¦ å‰‡é™¤äº†ç›®æ¨™è¦ å‰‡ (Target Rules)å¤–ï¼Œé‚„æœ‰æŽ¨ç †è¦ å‰‡ (Inference Rules),
或稱附檔å è¦ å‰‡ (Suffix Rules)ï¼›
\begin{enumerate}
-\item{ ç›®æ¨™è¦ å‰‡(Target Rules)} è¡¨é ”ä¾ è³´æ€§ï¼Œæª¢æŸ¥å ¦æ›´æ–°(up-to-date),
-ç•¶ç·¨è­¯å¾Œçš„æª”æ¡ˆæ¯”ç·¨è­¯å‰ çš„æª”æ¡ˆé‚„è¦ æ–°æ™‚ï¼Œå°±ä¸ æœƒé€²è¡Œè©²é …ç·¨è­¯ã€‚
-\item{æŽ¨ç †è¦ å‰‡(Inference Rules)}
-如果 test.c 引入 a.h , a.h å ˆå¼•å…¥ b.h〠c.h〠d.h ,
-ç„¶è€Œé€™ä¸‰å€‹æª”æ¡ˆå ˆåˆ†åˆ¥å¼•å…¥å…¶ä»–æª”æ¡ˆï¼Œè¦ æ€Žéº¼è™•ç †ï¼Ÿmakeæœƒåˆ©ç”¨æ­¤åŽŸå‰‡ï¼Œåˆ°æœ€åº•å±¤å¹«ä½ å „è‡ªç·¨è­¯ã€‚
+\item{ç›®æ¨™è¦ å‰‡}:
+\begin{mycommand}
+# Makefile
+A: B
+ SOME ACTION THAT BUILDS 'A' FROM 'B'
+\end{mycommand}
+
+è¡¨é ” A ä¾ è³´ B。make 執行時會檢查檔案的更新時間,å ªæœ‰ç•¶åŽŸå§‹æª”æ¯”ç›®æ¨™æª”æ–°æ™‚ï¼Œæ‰ æœƒåŸ·è¡Œå° æ‡‰å‹•ä½œã€‚
+\item{æŽ¨ç †è¦ å‰‡}ï¼šé¡žä¼¼ç›®æ¨™è¦ å‰‡ï¼Œä½†æ˜¯æœƒä½œç”¨æ–¼å…¨éƒ¨å‰¯æª”å ç¬¦å ˆçš„æª”æ¡ˆã€‚
+\begin{mycommand}
+# Makefile
+.SUFFIXES: .x .y .z
+.x.y:
+ touch $@
+.y.z:
+ touch $@
+t.z: t.x
+\end{mycommand}
+
+\begin{mycommand}
+$ make
+touch t.y
+touch t.z
+rm t.y
+\end{mycommand}
\end{enumerate}

Posix make 的完整語法:
@@ -327,11 +349,30 @@
\section{GNU make}

\subsection{範例一}
+目標:觀察 GNU make å…§å»ºå‡½å¼ çš„è¼¸å‡ºã€‚å°‡æ­¤æª”æ¡ˆå –å å «GNUmakefile,
+è®“è®€è€…æ˜Žç¢ºçŸ¥é “æˆ‘å€‘è¦ ä½¿ç”¨GNU make的擴充語法。
+
+\begin{mycommand}
+# GNUmakefile
+$(error $(wildcard *.c))
+\end{mycommand}
+
+\begin{mycommand}
+$ touch {0,1,2}.c # 建立 0.c 1.c 2.c 三個檔案
+$ make
+GNUmakefile:1: *** 1.c 2.c 0.c. Stop.
+\end{mycommand}
+
+\begin{enumerate}
+\item \code{error} æœƒåœ¨å °å‡ºå ƒæ•¸å¾Œçµ æ Ÿ make 的執行。常用來除錯 Makefile。
+\item \code{wildcard} 用跟 shell 下一樣的語法列出檔å
+\end{enumerate}
+
+\subsection{範例二}
ç›®æ¨™ï¼šåœ¨ä¸€ç›®éŒ„ä¸‹æ“ æœ‰è¨±å¤šç ¨ç«‹çš„.c檔,希望藉由makefileå¹«åŠ©ä¸‹ç”¢ç”Ÿç ¨ç«‹çš„å ¯åŸ·è¡Œæª”,
且若於目錄下新增了其他.c檔,å ¯ä¸ å¿…ä¿®æ”¹makefileäº¦èƒ½å®Œæˆ å»ºç«‹ç ¨ç«‹å ¯åŸ·è¡Œæª”ã€‚
-å°‡æ­¤æª”æ¡ˆå –å å «GNUmakefile,è®“è®€è€…æ˜Žç¢ºçŸ¥é “æˆ‘å€‘è¦ ä½¿ç”¨GNU make的擴充語法。

-\begin{mycode}
+\begin{mycommand}
# GNUmakefile
EXECUTABLES := $(patsubst %.c,%,$(wildcard *.c))

@@ -339,7 +380,7 @@
clean:
rm -f $(EXECUTABLES)
.PHONY: all clean
-\end{mycode}
+\end{mycommand}
\begin{enumerate}
\item æ­¤ makefile å‘¼å «äº†å…©å€‹GNU makeçš„å…§å»ºå‡½å¼ ,\code{wildcard} 與 \code{patsubst}。
指定 \code{EXECUTABLES} 變數時, 先用 \code{\$(wilcard *.c)} 將目錄下的所有.c檔列出來。
@@ -348,11 +389,11 @@
\url{http://www.gnu.org/software/automake/manual/make/Quick-Reference.html#Quick-Reference}。
\end{enumerate}

-\subsection{範例二}
+\subsection{範例三}
目標: é µå…¥ \code{make XXX-static} æœƒç”¢ç”Ÿé œæ…‹é€£çµ çš„ \code{XXX} çš„å ¯åŸ·è¡Œæª”ã€‚
-\begin{mycode}
+\begin{mycommand}
# GNUmakefile
-EXECUTABLES := $(patsubst %.c,%,$(wildcard *.c))
+EXECUTABLES := $(patsubst %.c,%,$(wildcard *.c))
STATIC_EXECUTABLES := $(addsuffix -static,$(EXECUTABLES))
all: $(EXECUTABLES)
%-static: %.c
@@ -361,7 +402,7 @@
clean:
rm -f $(EXECUTABLES) $(STATIC\_EXECUTABLES)
.PHONY: all clean
-\end{mycode}
+\end{mycommand}
\begin{enumerate}
\item 指定 \code{STATIC\_EXECUTABLES} 變數時,使用 \code{addsuffix} å°‡ \code{EXECUTABLES} è®Šæ•¸ä¸­çš„å­—ä¸²å¾Œé ¢å…¨éƒ¨åŠ ä¸Š "\code{-static}"。
\item "\code{\%-static: \%.c}" æ˜¯ä¸€å€‹ã€Œæª”å æ¨£å¼ è¦ å‰‡ã€ ,宣告 \code{XXX-static} ä¾ è³´ \code{XXX.c}。
@@ -435,7 +476,7 @@
\end{tabularx}
\end{table}

-\subsection{範例三}
+\subsection{範例四}
ç‰¹åˆ¥å¯«çµ¦åˆ å­¸è€…æŠ„çš„ GNU Makefile, 功能:
\begin{enumerate}
\item æ‰“é–‹ç·¨è­¯å™¨çš„è­¦å‘Šèˆ‡è¨˜æ†¶é«”æ“ ä½œæª¢æŸ¥ (CFLAGS)
@@ -443,7 +484,7 @@
\item é€£çµ æ•¸å­¸å‡½å¼ åº« (LDFLAGS)
\end{enumerate}

-\begin{mycode}
+\begin{mycommand}
# GNUmakefile
CFLAGS := -Wall -g -Os -Wp,-D_FORTIFY_SOURCE=2
CFLAGS += -fexceptions -fstack-protector --param=ssp-buffer-size=4
@@ -455,6 +496,6 @@
clean:
rm -f $(EXECUTABLES) core.*
.PHONY: all clean
-\end{mycode}
+\end{mycommand}

\end{document}
Reply all
Reply to author
Forward
0 new messages