Android.mkでMakefileの関数を使う

Android NDKで使用するAndroid.mkでもMakefileの関数が使えるかどうかを調 べてみました。 LOCAL_SRC_FILESが少し特殊ではあるものの、Makefileと同様の関数を使用で きるようです(全て使えるかどうかは調べておりません)。

 

Table of Contents

1 Makefileの関数

私がよく使う関数を挙げてみます。

1.1 wildcard

Makefile中でもシェルスクリプトのように*がワイルドカードとして用いる ことができます。以下ではカレントディレクトリの*.oに該当するファイル が削除されます。

clean:
  rm -f *.o

しかし、変数にワイルドカードを使うにはwildcard関数が必要となります。

var := $(wildcard *.cpp)

例えばカレントディレクトリにa.cppとb.cppというファイルがあった場合、 varの内容はa.cpp b.cppとなります。

1.2 patsubst

patsubst関数を用いることで、文字列を置換することができます。以下では varの内容はAreplace Breplaceとなります。

var := $(patsubst %pattern,%replace,Apattern Bpattern)

patsubst関数とsubst関数は似ておりますが、patsubst関数ではパターン以 外の文字列を参照することができます(アペンディクスを削除して、プレフィ クスを付けたりすることが可能)。

var1 := $(subst prefix,replace,prefixA prefixB)
var2 := $(patsubst prefix%,%appendix,prefixA prefixB)

1.3 info / warning / error

これらの関数は文字列を表示する為のものです。以下ではtextと出力されま す。$(var)等を指定することで変数の値を出力できます。

$(info text)

info関数とwarning関数の違いはwarning関数では呼ばれた箇所のファイル名 と行数を表示する点です。warning関数とerror関数の違いはerror関数では 呼ばれた時点でexitする点です。

Makefileをデバッグする場合は位置が分かり処理が継続されるwarning関数 がおすすめです(後ほど削除することを想定して)。

1.4 使用例

以下ではカレントディレクトリに存在するアペンディクスが.cppというファ イルに対し、$(CXX)を実行しております。

PROGS := $(patsubst %.cpp,%,$(wildcard *.cpp))
CXXFLAGS += $(EXTRA_CXXFLAGS)
LDLIBS += $(EXTRA_LDLIBS)

all: $(PROGS)

clean:
  rm -rf $(PROGS) *.dSYM

all: $(PROGS)を記述した時点でMakefileは暗黙のうちに$(PROGS)を生成す る$(CXX)を実行します。ただし、CXXFLAGSの位置は以下の通りとなりますの で、ライブラリの設定はLDLIBSで実行する必要があります(環境によっては -lpthread等のライブラリの設定は<PROG>.cppより後に指定しないと参照エ ラーとなってしまう)。

$(CXX) $(CXXFLAGS) -o <PROG> <PROG>.cpp

2 Android.mkでMakefileの関数を使う

以下はSDL2のandroid-project/jni/src/Android.mkの内容です。ユーザは YourSourceHere.cを任意に書き換えることで、SDL2を使用したコードを Android向けにビルドできます。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := main

SDL_PATH := ../SDL

LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include

# Add your application source files here...
LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \
  YourSourceHere.c

LOCAL_SHARED_LIBRARIES := SDL2

LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog

include $(BUILD_SHARED_LIBRARY)

コードが少しのファイルの場合は逐一YourSourceHere.cを書き換えてやれば 良いのですが、ファイル数が増えた場合に手間がかかります。この手間を削 減する為にMakefileのwildcard関数とpatsubst関数を利用します。

# Add your application source files here...
LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \
  $(patsubst $(LOCAL_PATH)/%,%,$(wildcard $(LOCAL_PATH)/*.cpp))

ここで留意すべき点はwildcard関数の引数に$(LOCAL_PATH)ディレクトリを 指定している点と、LOCAL_SRC_FILESにその結果を渡す際に$(LOCAL_PATH)の パスを削除している点です。

$(LOCAL_PATH)にディレクトリのパスが設定されている場合(./ではない 場合)、wildcard関数は別の場所を検索しようとします(Androidアプリケー ションプロジェクトのトップディレクトリ?)。それを防ぐ為に現在のディ レクトリを示す$(LOCAL_PATH)を指定します。

その一方でLOCAL_SRC_FILESは、与えられた内容それぞれに対して $(LOCAL_PATH)を加えようとします。例えば$(LOCAL_PATH)がdirで、 LOCAL_SRC_FILESがfile.cppの場合、dir/file.cppになります。 先ほどのwildcard関数の結果は$(LOCAL_PATH)のパスを含むものである為、 dir/dir/file.cppとなり、不正なファイルを参照することになります。 そこで、patsubst関数を用いてwildcard関数の結果から$(LOCAL_PATH)を削 除しています。

info/warning/error関数もMakefileと同様に使用できます。