Makefileの関数

自分用にずっとまとめようと思って、下書き保存して温めていたMakefile関連です。
C++用のビルドからAndroid用のビルドまでMakefileを大活用しているが、
使う機会が少ないのでMakefileの関数はどうも慣れない＆上手く活用できない。
そして毎回調べる。

ということで、
実用的なものから、今後使うことはないだろう的なものまで、
リファクタをする時のために調べた結果をまとめておきたい。

英語が読めない自分が英語のドキュメントを読んだりして、
自分なりの解釈でまとめたので誤りがありましたらごめんなさい。
一応、ドキュメントを見ながら全部載せしたつもり。
http://www.gnu.org/software/make/manual/

ちなみに、makeのバージョンは、

```
$ make --version
GNU Make 3.81
```

4.x系もリリースされているんですね...

# 文字列関連の関数

## filter

TEXT内からPATTERNの文字列に一致する要素を取得する。
.cppファイルのみを取得したいときなどに使える。

**使い方**

```basemake
$(filter PATTERN...,TEXT)
```

**実行例**

```basemake
VAR := hoge.h hoge.cpp hogera.h hogera.cpp

.PHONY: all
all:
	@echo "$(filter %.cpp,$(VAR))"
```

**結果**

```
$ make
hoge.cpp hogera.cpp
```

## filter-out

TEXT内からPATTERNの文字列に一致しない要素を取得する。
filterの逆バージョン。

**使い方**

```basemake
$(filter-out PATTERN...,TEXT)
```

**実行例**

```basemake
VAR := hoge.h hoge.cpp hogera.h hogera.cpp

.PHONY: all
all:
	@echo "$(filter-out %.cpp,$(VAR))"
```

**結果**

```
$ make
hoge.h hogera.h
```

## findstring

IN内にFINDの文字列があるかどうかを確認する

**使い方**

```basemake
$(findstring FIND,IN)
```

**実行例**

```basemake
VAR := abc def ghi

.PHONY: all
all:
	@echo "$(findstring bc,$(VAR))"
```

**結果**

```
$ make
bc
```

## firstword

NAMES内の最初の要素を取得する。

**使い方**

```basemake
$(firstword NAMES...)
```

**実行例**

```basemake
VAR := abc def ghi

.PHONY: all
all:
	@echo "$(firstword $(VAR))"
```

**結果**

```
$ make
abc
```

## lastword

NAMES内の最後の要素を取得する。

**使い方**

```basemake
$(lastword NAMES...)
```

**実行例**

```basemake
VAR := abc def ghi

.PHONY: all
all:
	@echo "$(lastword $(VAR))"
```

**結果**

```
$ make
ghi
```

## patsubst

TEXT内からPATTERNにマッチしたものをREPLACEMENTに置き換える。
※substのPATTERNが使えるバージョン。

**使い方**

```basemake
$(patsubst PATTERN,REPLACEMENT,TEXT)
```

**実行例**

```basemake
VAR := hoge.cpp hogera.cpp

.PHONY: all
all:
	@echo "$(patsubst %.cpp,%.o,$(VAR))"
```

**結果**

```
$ make
hoge.o hogera.o
```

## sort

LISTの各要素をソートする。

**使い方**

```basemake
$(sort LIST)
```

**実行例**

```basemake
VAR := hoge foo hogera fuga

.PHONY: all
all:
	@echo "$(sort $(VAR))"
```

**結果**

```
$ make
foo fuga hoge hogera
```

## strip

STRINGの無駄な空白を取り除く。

**使い方**

```basemake
$(strip STRING)
```

**実行例**

```basemake
VAR := a b    c    d

.PHONY: all
all:
	@echo "$(strip $(VAR))"
```

**結果**

```
$ make
a b c d
```

## subst

TEXT内のFROMをTOに置き換える。
※patsubstのPATTERNが使えないバージョン。

**使い方**

```basemake
$(subst FROM,TO,TEXT)
```

**実行例**

```basemake
VAR := hoge.cpp hogera.cpp

.PHONY: all
all:
	@echo "$(subst .cpp,.o,$(VAR))"
```

**結果**

```
$ make
hoge.o hogera.o
```

## word

TEXT内のN番目の要素を取得する。
※ 0 < N

**使い方**

```basemake
$(word N,TEXT)
```

**実行例**

```basemake
VAR := abc def ghi

.PHONY: all
all:
	@echo "$(word 1,$(VAR))"
```

**結果**

```
$ make
abc
```

## wordlist

TEXT内のSからEまでの要素を取得する。
※wordのlistバージョン。

**使い方**

```basemake
$(wordlist S,E,TEXT)
```

**実行例**

```basemake
VAR := abc def ghi

.PHONY: all
all:
	@echo "$(wordlist 1,2,$(VAR))"
```

**結果**

```
$ make
abc def
```

## words

TEXTの要素数を取得する

**使い方**

```basemake
$(words TEXT)
```

**実行例**

```basemake
VAR := abc def ghi

.PHONY: all
all:
	@echo "$(words $(VAR))"
```

**結果**

```
3
```

# ファイル名関連の関数

## abspath

NAMESの各要素の絶対パスを取得する。
※ファイルやディレクトリが存在するかどうかはチェックしない。

**使い方**

```basemake
$(abspath NAMES...)
```

**実行例**

```basemake
VAR := ../ ./ ./dir Makefile

.PHONY: all
all:
	@echo "$(abspath $(VAR))"
```

**結果**

```
$ make
/home/chibi /home/chibi/tmp /home/chibi/tmp/dir /home/chibi/tmp/Makefile
```

## addprefix

NAMESの各要素の接頭辞としてPREFIXを追加する。
※-Iとかを付けるときなどに使える。

**使い方**

```basemake
$(addprefix PREFIX,NAMES...)
```

**実行例**

```basemake
VAR := ./include ./dir/include

.PHONY: all
all:
	@echo "$(addprefix -I,$(VAR))"
```

**結果**

```
$ make
-I./include -I./dir/include
```

## addsuffix

NAMESの各要素の接尾辞としてSUFFIXを追加する。
※addprefixの接尾バージョン。
※今のところ使う機会がない。

**使い方**

```basemake
$(addsuffix SUFFIX,NAMES...)
```

**実行例**

```basemake
VAR := hoge.cpp hogera.cpp

.PHONY: all
all:
	@echo "$(addsuffix .bak,$(VAR))"
```

**結果**

```
$ make
hoge.cpp.bak hogera.cpp.bak
```

## basename

NAMESの各要素のファイル名を取得する。
(拡張子を排除する)

**使い方**

```basemake
$(basename NAMES...)
```

**実行例**

```basemake
VAR := hoge.txt ./dir/hogera.txt

.PHONY: all
all:
	@echo "$(basename $(VAR))"
```

**結果**

```
$ make
hoge ./dir/hogera
```

## dir

NAMESの各要素のディレクトリ名を取得する。

**使い方**

```basemake
$(dir NAMES...)
```

**実行例**

```basemake
VAR := hoge.txt ./dir/hogera.txt

.PHONY: all
all:
	@echo "$(dir $(VAR))"
```

**結果**

```
$ make
./ ./dir/
```

## join

LIST1とLIST2の先頭から突合せ結合を行う。
LIST1とLIST2のサイズが異なる場合は、
「空文字列+LIST2」や「LIST1+空文字列」といった形で結合される。

**使い方**

```basemake
$(join LIST1,LIST2)
```

**実行例**

```basemake
VAR1 := a b c d
VAR2 := 1 2 3 4 5

.PHONY: all
all:
	@echo "$(join $(VAR1),$(VAR2))"
```

**結果**

```
$ make
a1 b2 c3 d4 5
```

## notdir

NAMESの各要素のファイル名を取得する。

**使い方**

```basemake
$(notdir NAMES...)
```

**実行例**

```basemake
VAR := hoge.txt ./dir/hogera.txt

.PHONY: all
all:
	@echo "$(notdir $(VAR))"
```

**結果**

```
$ make
hoge.txt hogera.txt
```

## realpath

NAMESの各要素の絶対パスを取得する。
abspathとは異なり、ファイルやディレクトリが存在するもののみ取得する

**使い方**

```basemake
$(realpath NAMES...)
```

**実行例**

```basemake
VAR := ../ ./ ./dir Makefile

.PHONY: all
all:
	@echo "$(realpath $(VAR))"
```

**結果**

```
$ make
/home/chibi /home/chibi/tmp /home/chibi/tmp/Makefile
```

## suffix

NAMESの各要素の拡張子を取得する。
※basenameの拡張子バージョン。

**使い方**

```basemake
$(suffix NAMES...)
```

**実行例**

```basemake
VAR := hoge.txt ./dir/hogera.txt

.PHONY: all
all:
	@echo "$(suffix $(VAR))"
```

**結果**

```
.txt .txt
```

## wildcard

ワイルドカードを使って実在するファイルを取得する。
PATTERNは複数個書くこともできる。

**使い方**

```basemake
$(wildcard PATTERN)
```

**実行例**

```basemake
VAR := ./tmp/*.cpp ./tmp/*.md

.PHONY: all
all:
	@echo "$(wildcard $(VAR))"
```

**結果**

```
$ make
./tmp/foo.cpp ./tmp/hoge.cpp ./tmp/README.md
```

# 条件関連の関数

## and

全てのCONDITIONが空でないかどうかを取得する(?)
全てのCONDITIONが空ではない場合に最後のCONDITIONが返ってくる。1つでも空があると結果は空。
※こんな関数があったんだ...使う機会なさそう...

**使い方**

```basemake
$(and CONDITION1[,CONDITION2[,CONDITION...]])
```

**実行例**

```basemake
VAR1 := abc
VAR2 := def
VAR3 := ghi

.PHONY: all
all:
	@echo "$(and $(VAR1),$(VAR2),$(VAR3))"
	@echo "$(and $(VAR1),$(EMPTY),$(VAR3))"
	@echo "$(and $(VAR3),$(VAR2),$(VAR1))"
```

**結果**

```
$ make
ghi

abc
```

## if

CONDITIONが空文字列だったらELSE_PARTを
空文字列じゃない場合はTHEN_PARTを取得する。(なのかな？)
※and と or の流れから行くと合ってる気はするのだが...
※条件分岐系は挙動の理解に時間かかった...

**使い方**

```basemake
$(if CONDITION,THEN_PART[,ELSE_PART])
```

**実行例**

```basemake
VAR1 := abc
VAR2 := def
VAR3 := ghi

.PHONY: all
all:
	@echo "$(if $(VAR1),$(VAR2),$(VAR3))"
	@echo "$(if $(EMPTY),$(VAR2),$(VAR3))"
```

**結果**

```
$ make
def
ghi
```

## or

CONDITION全てが空文字列の場合は空を返す。
1つでも値がある場合はCONDITION1が返る。
※andを実行してからorをやったからなんとなく挙動の予想がついてた！
※が...どっちにしろ使わなそう...

**使い方**

```basemake
$(or CONDITION1[,CONDITION2[,CONDITION...]])
```

**実行例**

```basemake
VAR1 := abc
VAR2 := def
VAR3 := ghi

.PHONY: all
all:
	@echo "$(or $(VAR1),$(VAR2),$(VAR3))"
	@echo "$(or $(VAR1),$(EMPTY),$(VAR3))"
	@echo "$(or $(EMPTY),$(EMPTY),$(EMPTY))"
	@echo "$(or $(VAR3),$(VAR2),$(VAR1))"
```

**結果**

```
$ make
abc
abc

ghi
```

# デバッグ関連の関数

## error

MakefileのエラーとしてTEXTが取得され、かつStopされる。
※if関数とかと組み合わせて使うのかな？

**使い方**

```basemake
$(error TEXT...)
```

**実行例**

```basemake
.PHONY: all
all:
	@echo "$(error chibi)"
```

**結果**

```
Makefile:151: *** chibi.  Stop.
```

## info

TEXTが取得される。

**使い方**

```basemake
$(info TEXT...)
```

**実行例**

```basemake
.PHONY: all
all:
	@echo "$(info chibi)"
```

**結果**

```
chibi
```

## warning

行番号とTEXTが取得される。Stopにはならない。
※if関数とかと組み合わせて使うのかな？

**使い方**

```basemake
$(warning TEXT...)
```

**実行例**

```basemake
.PHONY: all
all:
	@echo "$(warning chibi)"
```

**結果**

```
Makefile:159: chibi
```

# その他の関数

## call

他の変数やマクロを呼び出すときに使用する。
呼び出し先では、PARAMを引数として$1,$2などで表す。

**使い方**

```basemake
$(call VARIABLE,PARAM,...)
```

**実行例**

```basemake
VAR = "var $1 $2"
define MACRO
	@echo "macro $1 $2"
endef

.PHONY: all
all:
	@echo "$(call VAR,a,b)"
	$(call MACRO,a,b)
```

**結果**

```
$ make
var a b
macro a b
```

## eval

変数を展開した上で、Makefileの構文として定義される。
※実行例ではcall関数と組み合わせてみます。

**使い方**

```basemake
$(eval TEXT)
```

**実行例**

```basemake
PROGRAMS := server client
server_OBJS = server_a.o server_b.o server_c.o
client_OBJS = client_a.o client_b.o client_c.o

define template
$(1):
	@echo "$1:"
	@echo "$($1_OBJS)"
endef

.PHONY: all
all: $(PROGRAMS)
	
$(eval $(call template,server))
$(eval $(call template,client))
```

**結果**

```
$ make
server:
server_a.o server_b.o server_c.o
client:
client_a.o client_b.o client_c.o

$ make server
server:
server_a.o server_b.o server_c.o

$ make client
client:
client_a.o client_b.o client_c.o
```

## flavor

変数の形式(?)を返す。
返される値は以下の通り。
・undefined: 未定義
・simple: Simply expanded variable
・recursive: recursively expanded variable

**使い方**

```basemake
$(flavor VARIABLE)
```

**実行例**

```basemake
DEFINED := test
RECURSIVE = test

.PHONY: all
all:
	@echo $(flavor UNDEFINED)
	@echo $(flavor DEFINED)
	@echo $(flavor RECURSIVE)
```

**結果**

```
undefined
simple
recursive
```

## foreach

LISTの要素をVARに分解し、TEXTで展開して実行する。
関数名の通りfor系の関数。

※evalの実行例にforeachを追加してみよう。

**使い方**

```basemake
$(foreach VAR,LIST,TEXT)
```

**実行例**

```basemake
PROGRAMS := server client
server_OBJS = server_a.o server_b.o server_c.o
client_OBJS = client_a.o client_b.o client_c.o

define template
$(1):
	@echo "$1:"
	@echo "$($1_OBJS)"
endef

.PHONY: all
all: $(PROGRAMS)

$(foreach prog,$(PROGRAMS),$(eval $(call template,$(prog))))
```

**結果**

```
server:
server_a.o server_b.o server_c.o
client:
client_a.o client_b.o client_c.o

$ make server
server:
server_a.o server_b.o server_c.o

$ make client
client:
client_a.o client_b.o client_c.o
```

## origin

どこで定義された変数なのかが取得される。
取得される文字列は以下の通り。
・undefined: 未定義
・default: CC や MAKE など
・environment: PATHなどの環境変数
・environment override: 
・file: Makefile内で定義されたもの
・command line: コマンドラインで定義されたもの
・override: Makefile内でオーバーライドされたもの
・automatic: 自動変数

**使い方**

```basemake
$(origin VARIABLE)
```

**実行例**

```basemake
DEFINED := test
OVERRIDE := test
override OVERRIDE := test

.PHONY: all
all:
	@echo $(origin UNDEFINED)
	@echo $(origin DEFINED)
	@echo $(origin PATH)
	@echo $(origin OVERRIDE)
	@echo $(origin @)
	@echo $(origin MAKE)
```

**結果**

```
undefined
file
environment
override
automatic
default
```

## shell

shellを叩く。
lsコマンドとかでwildcardの代わりなどもできる。

**使い方**

```basemake
$(shell COMMAND)
```

**実行例**

```basemake
.PHONY: all
all:
	@echo "$(shell ls)"
```

**結果**

```
Makefile tmp
```

## value

変数を参照する関数(?)
$(VARIABLE)と同じ結果が返ってくる。

**使い方**

```basemake
$(value VARIABLE)
```

**実行例**

```basemake
VAR := test

.PHONY: all
all:
	@echo "$(VAR)"
	@echo "$(value VAR)"
```

**結果**

```
test
test
```

# 4.x系で追加された関数

## file

ファイル書き込みを行える。
上書きと追記の2種類のモードがある。

※ついでにこの関数の実験中にわかったことが、
※shell関数を使うと改行コードはスペースに変換されてMakefileで扱う形になるということ。
※ダブルクォーテーションも無くなってた。

**使い方**

```basemake
$(file OP FILENAME[,TEXT])
```

**実行例**

```basemake
.PHONY: all
all: 
	@echo "all"
	$(file > test.txt,"A")
	@echo "$(shell cat test.txt)"
	$(file >> test.txt,"B")
	@echo "$(shell cat test.txt)"
	cat test.txt
```

**結果**

```
A
A B
cat test.txt
"A"
"B"
```

## guile

GNU Guileが統合されたためMakefileからguileが使えるようになっているとのこと。

以下を参考にチャレンジ
http://qiita.com/ka_/items/4aa58cd180e535767977

GNU Guile自体、
全然わからないのでstring-appendの真似をする。

**使い方**

```basemake
$(guile SCHEME)
```

**実行例**

```basemake
all:
	@echo $(guile (string-append "Hello" "World!"))
```

**結果**

```
HelloWorld!
```