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と同様に使用できます。