(for Internet Explorer)
PROG = sample
変数を定義します。 下の方の定義が優先されます。
$(PROG)
変数の値を参照します
参考
単純展開変数
A = First
B = $(A)   #// 最も下の A
A = Second

all:
      @echo  $(B) == Second
A = First
B := $(A)   #// すぐ上の A
A = Second

all:
      @echo  $(B) == First
再帰属展開変数
再帰属展開変数(=)は、変数の値を参照するときに、変数の値にある変数の値を参照します。
単純展開変数
条件付き代入演算子(?=)は、代入先となる変数の値が定義されていないときだけ代入
します。 再帰属展開変数です。
A ?= Default

all:
      @echo  $(A) == Default
A = Specify
A ?= Default

all:
      @echo  $(A) == Specify
定義済みの場合
未定義の場合
追加代入演算子(+=)は、変数の値の末尾に追加します。
再帰属展開変数に対する一般的な追加の式 「A = $(A) PlusX」 は、A の展開が遅延されるため、
循環参照エラーになってしまいますが、追加代入演算子を使うことで、直ちに追加されます。
A = First
A = $(A) Second   #// Error!

all:
      @echo  $(A)
A = First
A += Second

all:
      @echo  $(A) == First Second
循環参照エラー
追加代入演算子
all:
      @echo  a$(A)z == az
値を定義していない変数を参照すると、空文字になります。
ただし、「make A=1」 を実行したときのようにコマンドライン変数や環境変数が定義されて
いるときは、未定義ではありません。
A = First
A =

all:
      @echo  a$(A)z == az
未定義と同じ状態にしたいときは、右辺に何も記述しないようにします。
make を実行すると、Makefile に書かれた、ルールに基づくコマンドを実行する前に、変数の
定義を行います。
つまり、最も下の方にある定義が、条件付き代入演算子(?=)であったときは、そこより
上の方にある最も下の定義が採用されます。 もし定義がなければ、環境変数の値が
採用されます。 もし、それも無ければ、未定義になります。
つまり、最も下の方にある定義が採用されます。
つまり、単純展開変数の定義(:=)より上の方にある最も下の定義が採用されます。
この2つの違いは、値に他の変数の参照があるときだけです。
単純展開変数(:=)は、変数の値を定義するときに、変数の値にある変数の値を参照します。
参照する変数名の後にコロン(:)があるときは、変数の値を参照すると同時に、参照する
内容を修正したり置換したりします。
old=new 形式 (System V 形式)
SOURCES = First.c Second.c
A = $(SOURCES:.c=.o)

all:
      @echo  $(A) == First.o Second.o
変数の修正的参照
最終的な変数の定義を確認するには、シェルから
make -p  > make_profile.txt  2>&1
を実行してできるファイルの中を、
VAR =
で検索します。
… 変数名が VAR の場合
参考
単純展開変数(:=)の変化を見たいときは、一時的な変数を追加して、その変数に、追加代入
演算子(+=)を使っていきます。
DEBUG_VAR += 1:$(VAR)
# makefile 変数 (`Makefile', 67 行目から)
# MODULE_ALL_OBJECTS := sample.o 
コマンド実行時の、単純展開変数(:=)の値は make_profile.txt にあります。
make のコマンドラインで変数の定義をしても、それを無視して変数の値を設定します。
下記の場合、CFLAGS = -gstabs+ になります。 overwrite が無いと、CFLAGS=-g になります。
コマンドライン
make CFLAGS=-g
Makefile
overwrite CFLAGS = -gstabs+
参考
$@
target (:の左)
の (command) 部分に記述します
自動変数は、値に、
の target や source などが入った変数です。
a.o : a.c
  $(CC) -c -o $@ $<
a.o : a.c
  $(CC) -c -o a.o a.c
$<
source (:の右)、の1つ目(?)
$?
source (:の右)、の全体
a.o : a.c b.h
 @echo a.c b.h
a.o : a.c b.h
 @echo $?
通常
$*
target の %
%.o : %.c
  $(CC) -c -o $@ $*.c
a.o : a.c
  $(CC) -c -o a.o a.c
a.o : a.c b.h
 @echo a.c
a.o : a.c b.h
 @echo $<
$(dir names...)
参考
$(NAME ARG) 形式は、変数の参照ではなく、組み込み関数の場合もあります。
A = First.c Second.c
B = $(addsuffix  .o,  $(A) )

all:
      @echo  $(B) == First.c.o Second.c.o
参考
末尾に追加します。
objcopy --only-keep-debug  $@  $(basename $@).dbg
objcopy --only-keep-debug  sample.so  sample.dbg
$@=sample.so の場合
ファイル名の拡張子を除いたものを返します。
参考
For each file name in names return an absolute name that does not contain any . or .. components,
nor any repeated path separators (/). Note that, in contrast to realpath function, abspath does not
resolve symlinks and does not require the file names to refer to an existing file or directory.
Use the wildcard function to test for existence.
A = First Second
B = $(abspath $(A))

all:
      @echo  $(B) == /home/user1/First /home/user1/Second
関連
$(if $(V),,@)$(CROSS_COMPILE)$(CC)
$(if condition, true_case, false_case)
サンプル
条件 condition によって、true_case か false_case のどちらかに置き換わります。
$(if $(V),,@)
変数V が 0 以外(?) なら、空文字に、変数V が 0 なら、@ に置き換わります。
つまり、V が0 以外(?) なら、$(CROSS_COMPILE)$(CC) を展開したコマンドを
表示します。
a.o : a.c
  @echo compiling ...
make は、実行するコマンドを表示しますが、コマンドの先頭に @ を付けると表示しなくなります。
include (path)
Makefile に別のファイルをインクルードします
define two-lines
echo foo
echo $(bar)
endef
two-lines = echo foo; echo $(bar)
再帰属展開変数に、複数行の値を設定します。
上記は、下記と同じです。
endef だけの行で、定義は終了します。
参考
も同時に使えます。
overwrite define two-lines
echo foo
echo $(bar)
endef
foo: $(objects)
ifeq ($(CC),gcc)
        $(CC) -o foo $(objects) $(libs_for_gcc)
else
        $(CC) -o foo $(objects) $(normal_libs)
endif
ifeq ($(DEBUG),0)
  CFLAGS  = $(CFLAGS) -DNDEBUG
else
  CFLAGS  = $(CFLAGS) -g -DDEBUG
  LDFLAGS = $(LDFLAGS) -g
endif
条件によって、変数定義を変える:
条件によってコマンドを変える:
参考
ifeq ($(CC),gcc)

ifeq ("$(CC)","gcc")
比較する両者は、クォーテーションを囲むかどうかを統一してください。
関連
%.o: %.c
    $(CC) -c $(CFLAGS) -o $@ $<
(% を含むtarget) : (% を含むsource)
     (command)
%.o: %.c foo.h
    $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
サンプル
サンプル
ソース・ファイル名の一部(拡張子など)が一致した場合のルール。

target.o ファイルを更新する必要がある場合 (all のような最終ターゲットをルートとするツリーに
target.o ファイルが含まれる場合)、target.o をターゲットとするメイク・ルールが無くても、
%.o をターゲットとするメイク・ルールがあれば、そのコマンドを実行します。
書式:
target.o ファイルを更新する必要がある場合にも、実行される
source(右辺)には、% を含まないファイルを指定することも可能
( %.o : %.c )
a.o : a.c
  $(CC) -c $(CPPFLAGS) $(CFLAGS) a.c
( %.o : %.cc )
記述された明示ルールに、(fname).o に対応する該当するターゲットがない場合、
(fname).(ext) のファイルが存在するかどうかを探し、見つかったファイルの拡張子から、
暗黙ルールが使われます。
a.o : a.cc
  $(CXX) -c $(CPPFLAGS) $(CXXFLAGS) a.cc
C++言語としてコンパイルします
暗黙ルールは、
または、下記の組み込み暗黙ルールが使われます。
.c.o:
        $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
他のソースを指定できないため、型ルールを使うことを推奨
参考
.PHONY: all install clean
  command
.PHONY に依存するターゲット(上記の all, install clean と、それから更に依存するファイルなど)は、
常に更新されたものとみなされます。
Makefile には、ソースファイルやオブジェクトファイルの代わりに、下記のファイルを指定したり、
特殊なルールを作成したりできます。(Makefile の応用)
ソースファイルの代わりにタイムスタンプを更新する空ファイル。
入れ替えたソースファイルのタイムスタンプを更新したくないとき、代理更新ファイルを
Makefile に指定し、ソースファイルを入れ替えたときに代理更新ファイルのタイムスタンプを
更新する。
すべての処理が完了したときにタイムスタンプを更新する空ファイル。

make した結果、複数のファイルが作られるとき、それらがすべて更新されていることを示す
空ファイル。 all ターゲットに近いが、all に対応するファイルを作るところが異なる。
通常の処理の代わりに、以前行った処理の結果としてできたファイルをキャッシュから復帰
させるときに更新する空ファイル。 または、どのキャッシュを使うかを記述するファイル。
リビルドするときは、キャッシュ選択ファイルを削除すること。
キャッシュ選択ファイルが存在して、コミット・ファイルより新しければ、キャッシュから復帰する。
キャッシュ選択ファイルが存在して、コミット・ファイルと同じ日時なら、何もしない。
キャッシュ選択ファイルが存在しないなら、通常の処理を行う。
MakeFileClass(vbslib) では、タイムスタンプの比較を Make を始めた直後だけ行いますが、
このため、別の Make ルールによってターゲットファイルが更新されたときでも、両方の
Make コマンドを実行してしまいます。
Make ルール1
Make ルール2
ターゲットファイル
これを避けるには、Make コマンドを実行するときに、再度タイムスタンプを確認してください。
vbslib では、UBound( MakeRule::AllNewSource ) >= 0 のときだけ実行するようにします。
WorkspaceBuildTargetSplitter (オーダー調整用更新分離パス)
ソース
キャッシュ
ターゲットファイル
Make ルール
ターゲット1ファイル
ターゲット2ファイル
Make ルール1
Make ルール2A
Make ルール2B
下記の Makeルール2(A/B)より Makeルール1を優先するときは、依存関係を設定しますが、
ターゲット1ファイルを更新しても Makeルール2を起動させないようにするには、間に
「オーダー調整用更新分離パス」を挟むように、Makeルール2を A/Bに分離します。
このパスに、実際のファイルが作られることはありません。 また、Make ルール1のコマンド
で、ターゲット2ファイルを更新し、Makeルール2Bは、「代理Makeコマンドに対応したMake
コマンド」 にする必要があります。
更新
キャッシュ選択ファイルをソースとしたメイクルールの MakeRule::Priority を使って、キャッシュ
側の優先度を高くするか、下記の方法を使います。
参考
-I
-I. -I../include
サンプル:
インクルードパスを指定します。
#inlucde 文に記述した相対パスの基準フォルダパスを指定します。
-L
ライブラリパスを指定します。
-L../include
サンプル:
gdb でデバッグできるデバッグ版を作成します。リンクするときも指定します。
-g
サンプル:
コンパイルオプション
リンクオプション
-v
コンパイルの内部動作を表示します。
gcc のバージョン、スペック、インクルードパス
-v
サンプル:
ほぼすべての警告を有効にします。
ただし、Visual C++ で出る警告に対応してないものが多くあります。
例: 未初期化のローカル変数、暗黙の型変換など
-x のオプションを無効にするには、-x- のように末尾に - を付けます。
警告をエラー扱いにする
-Werror
-Wno-error=
-l
リンクするライブラリのファイル名を指定します。
ただし、先頭の lib と末尾の .so は記述しません。
サンプル: libX11.so をリンクします
-lX11
-o
実行ファイルやオブジェクトファイルの名前を指定します。
-osample
サンプル: sample ファイルを出力します
-gstabs+
#pragma GCC push_options
#pragma GCC optimize ("O0")

(最小単位は、関数定義)

#pragma GCC pop_options
ソースの一部だけ最適化をオフにする
オブジェクトファイルから、デバッグ情報を取り除きます。
バイナリ・ファイルのサイズが約20%小さくなります。
バイナリ・ファイルの解読が難しくなります。
参考
--strip-unneeded オプション:
  Remove all symbols that are not needed for relocation processing.
  共有オブジェクトでも使えるように、再配置に必要な情報は取り除きません。
  通常は、設定しておくとよいでしょう。
objcopy --only-keep-debug  sample.so  sample.dbg
strip --strip-unneeded  sample.so
objcopy --add-gnu-debuglink=sample.dbg sample.so
サンプル
sample.so からデバッグ情報を sample.dbg に分離し、かつデバッグできるようにします。