前回は、GNU makeにおいて特徴的な関数であるfile関数について取り上げた。今回取り上げるcall関数も、同じく特徴的なものの一つで、処理の一部を“関数的”なもののように使うことを可能にする。これは多用するとコードの可読性を損ないやすい。ただし、同じ処理を各所でコピペして使っているようなら、この関数を使ってまとめるのはアリだ。

“関数的”なものを作る「call関数」

まずは、call関数の使い方とその機能を見てみよう。

関数 シンタックス
call $(call 変数,パラメータ1,パラメータ2,…)
関数 内容
call パラメータ化された関数を作る関数。変数の値として複雑な式を指定することができ、それを別の値で展開するために使うことができる

この関数は、説明を読むだけではよくわからないだろう。現在主流のプログラミング言語における関数とはちょっと趣が違うので、実際に使ってみて体感するのが早いと思う。関数と言うよりも、「引数が渡せるサブルーチン」と言った方がニュアンス的には近いかもしれない。

call関数のサンプル

次のMakefileをご覧いただきたい。

# 変数定義だが、call関数を使うことでこれが関数のように
# 機能するようになる。$(1)はcall関数の1つ目のパラメータ、
# $(2)はcall関数の2つ目のパラメータを指す。
reverse = $(2) $(1)

test:
    @echo reverse = $$\(2\) $$\(1\)
    @echo
    @echo $$\(call reverse,1,2\)
    @echo $(call reverse,1,2)
    @echo 
    @echo $$\(call reverse,A,B\)
    @echo $(call reverse,A,B)

次のように書いてある部分、ここがいわゆる関数の本体ということになる。

reverse = $(2) $(1)

Makefile的にはこれは変数の定義だ。実際これは変数として振る舞うことができる。

この変数を次のようにcall関数にかける。

$(call reverse,1,2)

こうすると、「reverse = $(2) $(1)」の部分が「reverse = 2 1」と処理されて、「2 1」という結果が残ることになる。$(1)はcall関数におけるパラメータ1、$(2)はcall関数におけるパラメータ2だ。この部分がcall関数の本質的な部分と言ってもいいかもしれない。

最初のMakefileを実行すると次のようになる。

% make
reverse = $(2) $(1)

$(call reverse,1,2)
2 1

$(call reverse,A,B)
B A
% 
  • 実行結果

    実行結果

要するに、call関数を呼ぶことで変数として定義してある処理を走らせることができるというわけだ。その際、call関数に指定したパラメータを、あたかも関数の引数のように渡すことができ、$(1)や$(2)といった変数で指し示しておくことができる。“関数的”な挙動だと言えるだろう。

現在主流のプログラミング言語やシェルのような関数が定義できるわけではなく、ちょっとした処理をコールするための機能なのだが、知っておくと役に立つこともある。