※2019/04/04更新
NDK Build
従来cocos2d-xのプロジェクトに自前のクラスを追加したら、iOSの場合はXcodeにファイルを追加すれば良いし、Androidの場合はproj.android/app/jni/Android.mkに相応のファイルを追加すれば良かったのですが、v3.17ではそう行かなくなったようです。
実験として、新規プロジェクトを作成:
cocos new Test1 -l cpp
そして、デフォルトのHelloWorldシーンをMainシーンに変えてみました。
iOSで動作確認の上、上記Android.mkにMainScene.cppを追加して以下にすれば良いはずです。
LOCAL_SRC_FILES := $(LOCAL_PATH)/hellocpp/main.cpp \
$(LOCAL_PATH)/../../../Classes/AppDelegate.cpp \
$(LOCAL_PATH)/../../../Classes/HelloWorldScene.cpp \
$(LOCAL_PATH)/../../../Classes/MainScene.cpp
ところが、実行すると以下のようなエラーが出ました。
$ cocos run -p android
...
/Users/poo/test/Test1/Classes/AppDelegate.cpp:121: error: undefined reference to 'MainScene::createScene()'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
Mainシーンのクラスファイルが見つからないようですね。
ログをよく見ると、最初に実行されたコマンドは以下でした。
running: '"/Users/poo/test/Test1/proj.android/gradlew" --parallel --info assembleDebug -PPROP_BUILD_TYPE=cmake'
最後のビルドタイプはcmakeになっていることが分かります。
調べたところ(参考1)、proj.android/gradle.propertiesの中でデフォルトPROP_BUILD_TYPE設定がcmakeになっているので、それをndk-buildに変えればAndroid.mkが参照されるようになっているとのことでした。
しかし実際いくら変えても、実行されるコマンドは”-PPROP_BUILD_TYPE=cmake”のままで、もちろんビルドも失敗で終わります。
そこまで言うならcmakeを使うよとすっかり負けてしまいました。Orz
※2018/11/18追記:
proj.android/gradle.propertiesの設定はAndroid Studioに有効であり、コマンドラインでは–build-typeの指定で解決できることが分かりました。
つまりndk-buildでビルドしたいなら、コマンドは以下になります。
$ cocos run -p android --build-type ndk-build
今回はこれが回答になるかと思います。
以下のCMake部分では新たに追加した参考3によると、Google NDKのガイドではCMakeをネイティブライブラリをビルドするデフォルトツールとされているため、今後はndk-buildが徐々に減り、CMakeが徐々に増える傾向となるでしょう。
なので、早いうち慣れとくといいと思います。
しかしSDKBOXを使うなら、現段階v1.0.2.0ではCMakeに関してはノータッチのようですので、インポートするとCMakeではコンパイルエラーになります。
設定に関する情報も探してみましたが、見つかったのが参考5ぐらいで、まだまだ情報が少ないです。
ちなみに、参考5の情報は既に古いようで、そのままやってもうまくいきませんでしたので、今のところSDKBOXを使うなら、やっぱりndk-buildに切り替えたほうが一番手っ取り早いだと思います。
※2019/04/04更新:ここら辺が参考になります。
SDKBox 2.4.3.0 bugfix
CMake
CMakeのクラスファイルリストはプロジェクトルートにある「CMakeLists.txt」で設定できます。
デフォルトはこうなっているはずです。
list(APPEND GAME_SOURCE
Classes/AppDelegate.cpp
Classes/HelloWorldScene.cpp
)
list(APPEND GAME_HEADER
Classes/AppDelegate.h
Classes/HelloWorldScene.h
)
ここに追加したcppファイルとヘッダーをそれぞれ追加すれば良いはずです。
また、Classesディレクトリーの下にサブディレクトリーを作り、それらを追加したい場合、もうひと手間かかります。
例えば今回のMainSceneはClasses/mainのところに置くとします。
構造はこうなるはずです。
Classes/
├── AppDelegate.cpp
├── AppDelegate.h
├── HelloWorldScene.cpp
├── HelloWorldScene.h
└── main
├── MainScene.cpp
└── MainScene.h
この場合、上記のcppとヘッダーファイル追加するだけでは足りません。
このようなエラーになるはずです。
/Users/poo/test/Test1/Classes/AppDelegate.cpp:26:10: fatal error: 'MainScene.h' file not found
#include "MainScene.h"
^~~~~~~~~~~~~
1 error generated.
サブディレクトリーを作った場合、CMakeLists.txtの128行あたりにある「PRIVATE Classes」のあとにサブディレクトリーを追加する必要があります。
target_include_directories(${APP_NAME}
PRIVATE Classes
PRIVATE Classes/main #<=ここらへんに追加
PRIVATE ${COCOS2DX_ROOT_PATH}/cocos/audio/include/
)
※2019/04/04追加
同じファイルの最後辺りに、必要に応じて以下を追加します。
# add admob lib
if(ANDROID)
add_definitions(-DSDKBOX_ENABLED)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/proj.android/app/jni/PluginAdmob/)
target_link_libraries(${APP_NAME} ext_PluginAdMob
)
endif()
# add Firebase lib
if(ANDROID)
add_definitions(-DSDKBOX_ENABLED)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/proj.android/app/jni/PluginFirebase/)
target_link_libraries(${APP_NAME} ext_PluginFirebase
)
endif()
# add IAP lib
if(ANDROID)
add_definitions(-DSDKBOX_ENABLED)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/proj.android/app/jni/PluginIAP/)
target_link_libraries(${APP_NAME} ext_PluginIAP
)
endif()
# add Sdkbox Ads lib
if(ANDROID)
add_definitions(-DSDKBOX_ENABLED)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/proj.android/app/jni/PluginSdkboxAds/)
target_link_libraries(${APP_NAME} ext_PluginSdkboxAds
)
endif()
# add sdkbox lib
if(ANDROID)
add_definitions(-DSDKBOX_ENABLED)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/proj.android/app/jni/sdkbox/)
target_link_libraries(${APP_NAME} ext_sdkbox
)
endif()
まとめ
新しいクラスファイル追加した場合、Android版ではCMakeLists.txtに以下の3箇所に追加する必要になります。
- list(APPEND GAME_SOURCE ブロックにCPPファイルを追加
- list(APPEND GAME_HEADER ブロックにヘッダーファイルを追加
- Classesの下にサブディレクトリーがあれば、target_include_directories(${APP_NAME} ブロックにそのディレクトリーを追加
ファイルがたくさんあるときは、以下のコマンドでリストアップしてからコピペするといいでしょう。
#cpp
find Classes -name *.cpp -type f
#header
find Classes -name *.h -type f
参考
- CMake Guide
- How to properly add include directories with CMake
- Android template project doesn’t build on `PROP_BUILD_TYPE=ndk-build`
- Can’t use cmake build for android when using cocos console
- SDKBOX CMake integration
- SDKBox 2.4.3.0 bugfix