Issue
I'm working on a large project with many native modules and I'd like to introduce unit tests of the C++ code that are as simple/fast to run as Java JUnit local (i.e. running on the host OS, not instrumented) tests.
I've followed the official instructions for setting up gtest, but running my external native build results in a linker error:
> Task :app:externalNativeBuildDebug FAILED
Build GoogleTests x86_64
[1/2] Building CXX object CMakeFiles/GoogleTests.dir/googletest_unittests/shared/TautologyTe
sts.cpp.o
[2/2] Linking CXX executable GoogleTests
FAILED: cmd.exe /C "cd . && C:\Users\Jeffrey.Creswell\AppData\Local\Android\Sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=x86_64-none-linux-android21 --gcc-toolchain=C:/Users/Jeffrey.Creswell/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Users/Jeffrey.Creswell/AppData/Local/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -Wformat -Werror=format-security -stdlib=libc++ -std=c++14 -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--gc-sections CMakeFiles/GoogleTests.dir/googletest_unittests/shared/TautologyTests.cpp.o CMakeFiles/GoogleTests.dir/googletest_unittests/Tautology.cpp.o -o GoogleTests C:/Users/Jeffrey.Creswell/androidstudio_projects/NativeAndroidSandbox/app/src/main/cpp/googletest_unittests/libs/windows/x86_64/gtestd.lib -latomic -lm && cd ."
C:\Users\Jeffrey.Creswell\androidstudio_projects\NativeAndroidSandbox\app\src\main\cpp\googletest_unittests\shared/TautologyTests.cpp:19: error: undefined reference to 'testing::internal::GetTestTypeId()'
C:\Users\Jeffrey.Creswell\androidstudio_projects\NativeAndroidSandbox\app\src\main\cpp\googletest_unittests\shared/TautologyTests.cpp:19: error: undefined reference to 'testing::internal::MakeAndRegisterTestInfo(char const*, char const*, char const*, char const*, testing::internal::CodeLocation, void const*, void (*)(), void (*)(), testing::internal::TestFactoryBase*)'
...
I built gtestd.lib in Visual Studio and referenced it as a prebuilt in CMakeLists.txt to try to simplify the equation somewhat:
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
set(gtest_INC googletest_unittests/include)
include_directories(${gtest_INC})
add_library(gtest STATIC IMPORTED)
set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/googletest_unittests/libs/windows/x86_64/gtestd.lib)
add_executable(GoogleTests
${CMAKE_CURRENT_SOURCE_DIR}/googletest_unittests/shared/TautologyTests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/googletest_unittests/Tautology.cpp)
target_link_libraries(GoogleTests gtest)
# todo: insert add_test() cmake commands once the linker error above is resolved
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
I think the main problem is the argument "--target=x86_64-none-linux-android21"
to clang++.exe
; it implies compilation of the test executable for Android/Linux, when what I really want is to compile for the host OS (Windows 10). I don't know if this could produce the linker error I'm seeing, but attempting to link a Linux executable to a Windows static library seems like it would fail similarly. How can I tell the Android NDK's clang++ to target the host OS (ideally by modifications to my CMakeLists.txt
)? Assuming that's not the problem, is there a known way to get a local (running on host OS) C++ unit test scenario working within Android Studio?
NOTE: I looked at a similar question and the accepted answer appears to work, but generates an Android executable -- I would prefer a situation where I can ideally just hit the green arrow in Android Studio and have my C++ unit tests run automatically on the local machine.
Solution
Android Studio does not support host development.
If you want to build your tests against your host and run them there, you'll have to invoke CMake from outside Android Studio (command line would be an option, as would Visual Studio).
Answered By - Dan Albert
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.