Make

Makefile 组成
TARGETS: PREREQUESTS [Tab]COMMAND ...

或者

TARGETS: PREREQUESTS; COMMAND [Tab]COMMAND ...

objects=main.o kid.o really.o \ insert.o uitls.o edit: $(objects) [Tab]cc -o edit $(ojbects) ...
 * '\' ，用来分割超长的行


 * $ 是特殊字符，一般表示变量，$(aa) 等同 ${aa}, 如果需要字符 $ ，用 “$$” 表示


 * 一个完整的 Makefile 包含了5个东西：显示规则，隐式规则，变量定义，指示符，注释

.PHONY (伪目标)
.PHONY: clean clean: [Tab]-rm edit $(objects)


 * 通过 .PHONY 将 clean 声明为 伪target, 防止磁盘上有一个名为 "clean" 的文件时，目标无法执行.
 * -rm 忽略命令 rm 的执行错误. (如果不忽略，rm 的错误会停止 make 的继续执行)

# (注释)

 * # 后的内容会当做注释，如果需要字符 # ，用 (\#) 实现.

Makefile
>make -f fileName targetName
 * make 命令默认需找目录下名为 Makefile 的文件，GNU make 默认文件名寻找顺序：GNUmakefile, makefile, Makefile
 * 通过 -f 或 --file 来指定 file name

include
include FILENAMES...
 * "include" 指示符告诉 make 暂停读取当前 Makefile, 转而读取 “include” 指定的一个，多个文件.
 * "-include FILENAME" 当所包含的文件不存在时，忽略错误，不会退出，只有目标规则不存在才会退出.

"*" "." "?" [...] 通配符

 * Makefile 中的通配符与 BShell 中的相同，例如， *.c 表示当前工作目录下所有 ".c" 结尾的文件.
 * 但是通配符并不可以用在任何地方，Makefile 中通配符可以出现在以下两种场合:
 * 可以用在规则的目标，依赖中，此时 make 会自动将其展开
 * 可以出现在规则命令中，其展开是在 shell 执行此命令时
 * 除以上两种之外其他上下文中，不能直接用通配符，需要用函数 $(wildcard) 来实现.

objects=$(wildcard *.o)
 * ~ 表示当前用户的 home dir, ~john/bin 表示 user john 的 home/bin dir
 * 变量定义中的通配符不会自动展开，需要 $(wildcard)

$(strip)

 * Removes leading and trailing whitespace from string and replaces each internal sequence of one or more whitespace characters with a single space. Thus, `$(strip a b c )' results in `a b c'.
 * http://sunsite.ualberta.ca/Documentation/Gnu/make-3.79/html_chapter/make_8.html#SEC77

$(subst from,to,text)
$(subst ee,EE,feet on the street)
 * Performs a textual replacement on the text text: each occurrence of from is replaced by to. The result is substituted for the function call. For example
 * 1) result, substitutes the string ‘fEEt on the strEEt’.

$(if condition,then-part[,else-part])

 * The first argument, condition, first has all preceding and trailing whitespace stripped, then is expanded. If it expands to any non-empty string, then the condition is considered to be true. If it expands to an empty string, the condition is considered to be false.


 * If the condition is true then the second argument, then-part, is evaluated and this is used as the result of the evaluation of the entire if function.


 * If the condition is false then the third argument, else-part, is evaluated and this is the result of the if function. If there is no third argument, the if function evaluates to nothing (the empty string).


 * Note that only one of the then-part or the else-part will be evaluated, never both. Thus, either can contain side-effects (such as shell function calls, etc.)

$(foreach var,list,text)

 * The first two arguments, var and list, are expanded before anything else is done; note that the last argument, text, is not expanded at the same time. Then for each word of the expanded value of list, the variable named by the expanded value of var is set to that word, and text is expanded. Presumably text contains references to that variable, so its expansion will be different each time.


 * The result is that text is expanded as many times as there are whitespace-separated words in list. The multiple expansions of text are concatenated, with spaces between them, to make the result of foreach.


 * This simple example sets the variable ‘files’ to the list of all files in the directories in the list ‘dirs’:

dirs := a b c d    files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))

?
FOO ?= bar 其含义是，如果FOO没有被定义过，那么变量FOO的值就是“bar”，如果FOO先前被定义过，那么这条语将什么也不做

difference between '=' and ':='

 * In short, variables defined with := are expanded once, but variables defined with = are expanded whenever they are used.

http://www.gnu.org/software/make/manual/html_node/Flavors.html - two flavors of variable

+= （追加符）
a+=b

$(wildcard)
$(wildcard pattern...)
 * Wildcard expansion happens automatically in rules. But wildcard expansion does not normally take place when a variable is set, or inside the arguments of a function. If you want to do wildcard expansion in such places, you need to use the wildcard function.


 * This string, used anywhere in a makefile, is replaced by a space-separated list of names of existing files that match one of the given file name patterns. If no existing file name matches a pattern, then that pattern is omitted from the output of the wildcard function.

$(filter)
$(filter pattern...,text)
 * Returns all whitespace-separated words in text that do match any of the pattern words, removing any words that do not match. The patterns are written using `%', just like the patterns used in the patsubst function above. The filter function can be used to separate out different types of strings (such as file names) in a variable. For example:

sources := foo.c bar.c baz.s ugh.h         foo: $(sources) cc $(filter %.c %.s,$(sources)) -o foo

$(filter-out)
$(filter-out pattern...,text) For example, given: objects=main1.o foo.o main2.o bar.o         mains=main1.o main2.o the following generates a list which contains all the object files not in ‘mains’: $(filter-out $(mains),$(objects))
 * Returns all whitespace-separated words in text that do not match any of the pattern words, removing the words that do match one or more. This is the exact opposite of the filter function.


 * https://www.gnu.org/software/make/manual/html_node/Text-Functions.html

debug make rules

 * make -n can help show what would be done without actually doing it.
 * echo 'print: ; @echo "$(VAR)"' | make -f Makefile -f - print can be handy to examine the expanded value of variables.
 * http://www.gnu.org/software/automake/manual/html_node/Debugging-Make-Rules.html
 * http://oreilly.com/catalog/make3/book/ch12.pdf
 * http://oreilly.com/catalog/make3/book/index.csp