Saturday, January 9, 2016

続・Visual StudioからAndroid開発を実践してみた

Visual Studio 2015からAndroidの開発をしてみましたが、思わぬエラーに遭遇して悩みました。そんな経験を書き連ねてみます。


Clangで内部エラー


Visual Studio 2015でのデフォルトのコンパイラがClangなのですが、特定のソースファイルをコンパイルする時に以下のような内部エラーを発生させるようです。
1>  This application has requested the Runtime to terminate it in an unusual way.
1>  Please contact the application's support team for more information.
1>  Assertion failed!
1>
1>  Program: C:\ProgramData\Microsoft\AndroidNDK\android-ndk-r10e\toolchains\llvm-3.6\prebuilt\windows\bin\clang.exe
1>  File: /s/ndk-toolchain/src/llvm-3.6/llvm/tools/clang/lib/AST/DeclBase.cpp, Line 1299
1>
1>  Expression: DeclKind != Decl::LinkageSpec && "Should not perform lookups into linkage specs!"
1>clang.exe : error : clang frontend command failed with exit code 3 (use -v to see invocation)
1>  clang version 3.6
1>  Target: armv7-none-linux-androideabi
1>  Thread model: posix
1>  clang.exe: note: diagnostic msg: PLEASE submit a bug report to http://source.android.com/source/report-bugs.html and include the crash backtrace, preprocessed source, and associated run script.
1>  clang.exe: note: diagnostic msg:
1>  ********************
1>
1>  PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
1>  Preprocessed source(s) and associated run script(s) are located at:
1>  clang.exe: note: diagnostic msg: C:\Users\Jin0103\AppData\Local\Temp\bvh-1eb1f7.cpp
1>  clang.exe: note: diagnostic msg: C:\Users\Jin0103\AppData\Local\Temp\bvh-1eb1f7.sh
1>  clang.exe: note: diagnostic msg:
1>
1>  ********************

回避方法が無さそうなので、やむを得ずGCCに切り替えました。プロジェクトのプロパティのPlatform Toolsetで変更可能です。



libmのリンク


Visual Studioではsin, cos等の数学ライブラリは明示的にリンクしなければ以下のようなリンクエラーを出すようです。

1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(51): error : undefined reference to 'sin'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(56): error : undefined reference to 'cos'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(61): error : undefined reference to 'tan'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(66): error : undefined reference to 'asin'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(71): error : undefined reference to 'acos'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(78): error : undefined reference to 'atan2'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(109): error : undefined reference to 'floor'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(120): error : undefined reference to 'ceil'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(138): error : undefined reference to 'fmod'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(157): error : undefined reference to 'ceil'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(157): error : undefined reference to 'floor'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(167): error : undefined reference to 'sqrt'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(183): error : undefined reference to 'log'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(186): error : undefined reference to 'log10'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(187): error : undefined reference to 'log'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(187): error : undefined reference to 'log'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lmathlib.c(194): error : undefined reference to 'exp'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lobject.c(103): error : undefined reference to 'pow'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lobject.c(104): error : undefined reference to 'floor'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lobject.c(108): error : undefined reference to 'fmod'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/ltable.c(92): error : undefined reference to 'floor'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/ltable.c(103): error : undefined reference to 'frexp'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lvm.c(858): error : undefined reference to 'fmod'
1>D:\github\AdamasF\VisualStudio\..\submodules\lua\src/lvm.c(883): error : undefined reference to 'pow'

Androidのライブラリはファイル名が全てlibGLESv3, libOpenSLESのようにlibで始まるのですが、libを省略してGLESv3, OpenSLESのように指定する習慣があるようです。数学ライブラリはlibmなので、mとだけ指定するとリンクできます。


Precompiled Headerは切ってみる


なぜ発生するかわからないコンパイルエラーが出るときは、Precompiled Headerを切ってみます。(デフォルトで使うようになっている)


GCCのプリコンパイル済みヘッダはWindows+Visual Studioのものと仕組みが違います。

Windows+Visual Studioでは、例えばstdafx.hを各ソースの最上位でincludeすることを強制して重複する作業を省略しようとします。

GCCでは、各ソースの最上位で強制的にpch.hをincludeしたことにしてしまうようです。

個人的な経験なので参考にならないかもしれませんが、なぜかCであるLuaのソースコードで__cplusplusが定義されたり、Luaのソースコードで最上位で定義されなければならないLUA_COREやLUA_LIB等のマクロ定義に先駆けてlua.hがincludeされたことになっていました。

ぱっと見で分かり難いエラーの原因がプリコンパイル済みヘッダの間違った使い方であったというのはありがちなシチュエーションなので、仕組みを理解したうえで適用するか決めるのがよさそうです。

Sunday, January 3, 2016

Visual StudioからAndroid開発を実践してみた

実際に開発を進めてみるとハマることが多く、メモを残します。

assetsやresフォルダの扱い


Android Studioのようにエクスプローラー上にassetsやresフォルダがあっても自動的に取り込まれません。


Visual Studio上で明示的にassetsやresフォルダを作ってファイルを一つ一つ追加します。

ところで、例えばdrawableフォルダを追加する時に既にエクスプローラー上にdrawableフォルダがある場合エラーが発生します。


これは、Visual Studioがプロジェクト上の概念的なフォルダではなく、本当にディスク上にフォルダを生成しようとしているためです。よって、既存のdrawableフォルダを一度別の場所に移動してからVisual Studio上でdrawableフォルダを作るという過程が必要です。

この辺はWindowsアプリを開発しているときと挙動が違ってややこしいです。


Activityが無いアプリの実機へのインストール


Visual Studio上からapkを実機で実行する場合、起動するActivityをプロジェクトのプロパティに指定するようになっています。



ところが、ウィジェットやライブ壁紙の場合起動可能なアクティビティが存在しない場合があります。その際、Ctrl-F5で実行しようとすると以下のようなエラーが発生してインストールすらしてくれません。

Could not retrieve the launch activity from the package (apk)

こういう時は、以下のようにコマンドラインから入力してインストールします。(バッチを作ります)
adb install -r ARM\Release\KiriWidget.apk

Visual Studio 2015から使われるadb.exeは以下のパスにあるようです。必要に応じて環境変数PATHに通しておきます。

C:\Program Files (x86)\Android\android-sdk\platform-tools