web-dev-qa-db-ja.com

Android NDK with Google Test

Android StudioでGoogleTestを使用しようとしています。

私が理解したところによると、NDKの最新バージョンにはgtestが含まれています。

私はそれを行う方法の明確なガイドを見つけられませんでした。

私は this document:

そこで、新しいプロジェクトを開き、jniフォルダーと次のファイルを作成しました(私が書いたファイルの中に、ドキュメントとまったく同じものがあります)。

enter image description here

しかし、それは#include gtest/gtest.hを認識しません

加えて、

  • 最後にadbを実行する方法は?
  • Android.mkファイルを作成しましたが、どこで呼び出す必要がありますか?
11
ShiraOzeri

cmakeを選択してexternalNativeBuildを駆動する場合(Android開発者 NDKガイド)によると、これが推奨されるオプションです )の場合、次の行をCMakeLists.txtに追加するだけです。

set(GOOGLETEST_ROOT ${Android_NDK}/sources/third_party/googletest/googletest)
add_library(gtest STATIC ${GOOGLETEST_ROOT}/src/gtest_main.cc ${GOOGLETEST_ROOT}/src/gtest-all.cc)
target_include_directories(gtest PRIVATE ${GOOGLETEST_ROOT})
target_include_directories(gtest PUBLIC ${GOOGLETEST_ROOT}/include)

add_executable(footest src/main/jni/foo_unittest.cc)
target_link_libraries(footest gtest)

ビルドが成功すると、app/.externalNativeBuild/cmake/debug/x86/footestが見つかります。ここから、 README.NDK の手順に従って、エミュレーターまたはデバイスで実行できます。


メモ

  • aBIが使用するターゲットと一致することを確認してください(ガイドはこれについてあまり明確ではありません)。
  • ビルドされるABIのリストは、build.gradleabiFiltersによって制御されます。 Android Studioでも、ndk-buildApplication.mkで設定されたAPP_ABIを無視します。
  • cmakeを使用すると、ファイルAndroid.mkおよびApplication.mkは無視されます。
  • gradle-3. 、およびclasspath 'com.Android.tools.build:gradle:2.3.3'の場合、現在のAndroid Studioリリース2.3.3のように、-でユニットテストターゲットを明示的に指定する必要がある場合があります。 build.gradle

    Android { defaultConfig { externalNativeBuild { cmake { targets "foo_unittest" }}}}
    
  • Android Studio 3.0、 gradle-4.1 、およびclasspath 'com.Android.tools.build:gradle:3.0.0-beta6'を使用すると、実行可能ファイルはapp/build/intermediates/cmake/debug/objの下で簡単に見つけることができます。


共有ライブラリでfoo(int x、int y)関数をfoo.cppからテストするには(にできるだけ近づけます) NDK命令)、CMakeLists.txtスクリプトにさらにいくつかの行が必要です:

# build libfoo.so
add_library(foo SHARED src/main/jni/foo.cpp)
target_link_libraries(footest foo) 

libfoo.soは、app/build/intermediates/cmake/debug/objの下にあるデバイスに手動でコピーできます。

手間を軽減するには、STATICの代わりにSHAREDを使用するか、foo.cppfootest実行可能ファイルに追加します。

add_executable(footest src/main/jni/foo_unittest.cc src/main/jni/foo.cpp)
13
Alex Cohn

Alexの優れた答えに追加するために、CMakeLists.txtに以下を追加することで、adbを使用して結果のテストバイナリをデプロイして実行することもできます。

find_program(ADB adb)
add_custom_command(TARGET footest POST_BUILD
    COMMAND ${ADB} Shell mkdir -p /data/local/tmp/${Android_ABI}
    COMMAND ${ADB} Push $<TARGET_FILE:native-lib> /data/local/tmp/${Android_ABI}/
    COMMAND ${ADB} Push $<TARGET_FILE:footest> /data/local/tmp/${Android_ABI}/
    COMMAND ${ADB} Shell \"export LD_LIBRARY_PATH=/data/local/tmp/${Android_ABI}\; /data/local/tmp/${Android_ABI}/footest\")

上記の例では、footestは共有ライブラリnative-libに依存していることに注意してください。これが、それをプッシュする理由です。 native-libへのパスは、LD_LIBRARY_PATH環境変数を設定することによって指定されます。

5
donturner

みんなの答えをおんぶするために...ここのすべての解決策が100%うまくいったわけではありませんが、私はここのすべての答えを組み合わせて、私のために働く何かを得ました。ライブラリをCMakeでビルドしています。そのビルドは、Android Studioプラグインによって生成されます。GoogleTestsはbashadbを介して直接実行されます。 。

警告:

  • googletestの公式ドキュメント は基本的に、コンパイルするすべてのプラットフォームで動作するバージョンを提供してくれました。非常に些細なことです! Android GradleプラグインはAndroid用のクロスコンパイルを使用するという引数を追加する必要がありました。テストにはgmockが必要なため、この方法を使用しました。NDKにはありません(すごい)。私は公式の指示を使用することになりました。
  • 単体テストは実行可能ファイルであるため、CMakeLists.txtで、add_executable(UnitTest "")を使用して単体テストを作成し、そこにリンクする必要があります。
  • 誰もが言っているように、${AS_STUDIO_LIBRARY_ROOT}/build/intermediates/cmake/${release|debug}/obj/${Arch}はコンパイルされたソースを格納します。これには、共有ライブラリと他のライブラリ、および単体テストの実行可能ファイルが含まれている必要があります。この実行可能ファイルは最終的なAPKに到達しないため、心配する必要はありません。
  • 以下を実行して、ファイルのアクセス許可の問題を防止します。すべてを/data/local/tmp/<PROJECT_NAME>に直接コピーしてからchmod 777することは、特にPixel 2とエミュレーターでは、何らかの理由で機能しません:
    1. adb Pushリソース、ライブラリ、およびgoogletest実行可能ファイルを最初に/sdcard/<PROJECT_NAME>フォルダーに移動します
    2. adb Shell mv /sdcard/<PROJECT_NAME> /data/local/tmp/.
    3. chmod 777 -R /data/local/tmp/<PROJECT_NAME>

これがすべて完了すると、次のようにgoogletestを実行できるようになります。

adb Shell LD_LIBRARY_PATH=/data/local/tmp/<PROJECT_NAME>; cd /data/local/tmp/<PROJECT_NAME>; ./<GOOGLE_TEST_EXECUTABLE>

また、Visual StudioCodeを介してgdbserverおよびgdbを介してリモートデバッグを機能させました。代わりにlldbを使用したいのですが、まだわかりません。完全なデバッグを機能させるためのこのトピックには複数の段落が必要になるため、Visual StudioCodeでlldbを使用したり、この問題をどのように解決したか知りたい場合は、お気軽にPM PM $ === me 。

単体テストの実行後にファイルを削除することを忘れないでください。そうしないと、ファイルがデバイスに残ります。

1
Jeremy Jao

私は基本的にアレックスコーンズアンサーを使用しました。 Ubuntu18-04。 Android studio内からビルドする必要があります。注stuidioの外部でcmakeを実行すると、現在のプラットフォームのビルドのみが取得されます。armeabiのビルドを制限する必要がありました。ターゲットシステムはこれで、静的ライブラリは静的にリンクしていたので、ビルドターゲットフットレストをダウンロードして実行するだけで済みました。これは基本的にAlex Cohnのファイルであり、2つの静的ライブラリをリンクするために追加されたファイルです。

# gtest setup
set(Android_NDK /home/labhras/Android/Sdk/ndk/20.0.5594570)
set(GOOGLETEST_ROOT ${Android_NDK}/sources/third_party/googletest)
add_library(gtest STATIC ${GOOGLETEST_ROOT}/src/gtest_main.cc ${GOOGLETEST_ROOT}/src/gtest-all.cc)
target_include_directories(gtest PRIVATE ${GOOGLETEST_ROOT})
target_include_directories(gtest PUBLIC ${GOOGLETEST_ROOT}/include)

# link_directories(~/AndroidStudioProjects/Nativecgtest/app/src/main/cpp)

add_library(libtsl.a STATIC IMPORTED)
set_target_properties(libtsl.a
        PROPERTIES IMPORTED_LOCATION /home/labhras/AndroidStudioProjects/Nativecgtest/app/src/main/cpp/libtsl.a
        INTERFACE_INCLUDE_DIRECTORIES /home/labhras/AndroidStudioProjects/Nativecgtest/app/src/main/cpp/libtsl.a
        )


add_library(libtcl.a STATIC IMPORTED)
set_target_properties(libtcl.a
        PROPERTIES IMPORTED_LOCATION /home/labhras/AndroidStudioProjects/Nativecgtest/app/src/main/cpp/libtcl.a
        INTERFACE_INCLUDE_DIRECTORIES /home/labhras/AndroidStudioProjects/Nativecgtest/app/src/main/cpp/libtcl.a
        )

add_executable(footest  test2.cpp)
target_link_libraries(footest gtest libtsl.a libtcl.a)

App build.gradleのabiFilters行を使用して、ビルドをarmeabiに制限しました。

defaultConfig {
    externalNativeBuild {
        cmake {
            abiFilters "armeabi-v7a"
        }
    }

}
0
drlolly

CMakeまたはndk-build(Android.mk)を使用できますが、両方を使用することはできません。 NDKの最も優れた部分はCMakeのために配管されていません。 https://github.com/Android-ndk/ndk/issues/5

0
Dan Albert