How to build an Android project with Ninja? - android

I have an Android project with a app/src/CMakeLists.txt file like this
cmake_minimum_required(VERSION 3.4.1)
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
main/cpp/native-lib.cpp )
I also have a app/src/main/cpp/native-lib.cpp file in my project.
When I run ninja in a terminal I get this error
ninja: error: loading 'build.ninja': No such file or directory
I'm not familiar with the NDK and I'm trying to run the project with ninja but I'm not able to find any clear documentation or example.

Android NDK uses CMake to build projects, but instead of run ninja separately, you should run below gradle command to trigger your NDK project build.
./gradlew externalNativeBuild
Internally, CMake will use the ninja build system to compile and link the C/C++ sources for your apps.

Related

CMake Error at (find_package) while trying to configure opencv in native c++ android studio

I am facing this problem while connecting opencv with native c++ in Android Studio. I am working in windows 10.
# 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.10.2)
# opencv
set(OpenCV_STATIC ON)
set(OpenCV_DIR $ENV{OPENCV_ANDROID}/sdk/native/jni)
find_package(OpenCV REQUIRED)
# Declares and names the project.
project("opencv_sample1")
# 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 )
# 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
${OpenCV_LIBS}
${jnigraphics-lib}
# Links the target library to the log library
# included in the NDK.
${log-lib} )
This is my CMakeLists.txt file.
C:\tools\OpenCV-android-sdk
This is the path for the OpenCV-android-sdk folder. I have created an environment variable named OPENCV_ANDROID and have added the above path.
Execution failed for task ':app:generateJsonModelDebug'.
> C:\Users\Sanchita Das\AndroidStudioProjects\Opencv_sample1\app\src\main\cpp\CMakeLists.txt : C/C++ debug|armeabi-v7a : CMake Error at C:\Users\Sanchita Das\AndroidStudioProjects\Opencv_sample1\app\src\main\cpp\CMakeLists.txt:10 (find_package):
Found package configuration file:
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
I have tried with the "*Try" option but got no better results.
Also have tried the method suggested in
"https://stackoverflow.com/questions/63328010/app-src-main-cpp-cmakelists-txt-c-c-debugarm64-v8a-configuration-failed"
"https://stackoverflow.com/questions/45219049/android-studio-cmake-error-build-command-failed"
but could not solve my problem.
Please anyone with any suggestions?
After a long search in the CMake file to confirm each variable, I finally found that the value of ANDROID_NDK_ABI_NAME on line 39 in the file OpenCVConfig.cmake is empty!
It might be the following possibilities: [arm64-v8a, armeabi-v7a, x86, x86_64], each representing the CPU architecture in different environments.
Try to comment out the original ANDROID_NDK_ABI_NAME, and then replaced it with ANDROID_ABI to successfully sync.

Build OpenCV for Android with CMake's ExternalProject_Add

I am creating an Android library that uses OpenCV via NDK. It doesn't require any Java parts of OpenCV, native parts only, so I decided not to use OpenCV for Android to reduce the size of the OpenCV code the library needs.
Now I need to download and build the native (C++) part of OpenCV using CMake so that the library won't require its users to download and install OpenCV on their own.
Currently my module's build.gradle contains this:
externalNativeBuild {
cmake {
cppFlags '-std=c++11 -frtti -fexceptions'
arguments '-DANDROID_ARM_NEON=TRUE'
}
}
And my CMakeLists.txt is:
cmake_minimum_required(VERSION 3.18.1)
project("mylib")
set(OPENCV_INSTALL_DIR ${CMAKE_BINARY_DIR}/opencv-install)
include(ExternalProject)
ExternalProject_Add(opencv
GIT_REPOSITORY https://github.com/opencv/opencv.git
GIT_TAG 4.5.5
UPDATE_DISCONNECTED TRUE
CMAKE_ARGS
<OpenCV arguments I need>
-DCMAKE_INSTALL_PREFIX=${OPENCV_INSTALL_DIR}
)
include_directories(${OPENCV_INSTALL_DIR}/include)
link_directories(${OPENCV_INSTALL_DIR}/lib)
set(OPENCV_LIBRARIES <OpenCV modules I use>)
add_library(mylib SHARED mylib.cpp)
add_dependencies(mylib opencv)
find_library(log-lib log)
target_link_libraries(mylib ${log-lib} ${OPENCV_LIBRARIES})
I am using Android Studio. When I try to build the library, the downloading process goes fine, but at the configure step I get the following error:
FAILED: opencv-prefix/src/opencv-stamp/opencv-configure
cmd.exe /C "cd /D <my lib module path>\.cxx\Debug\612145b5\x86_64\opencv-prefix\src\opencv-build && <my Android SDK path>\cmake\3.18.1\bin\cmake.exe -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_EXAMPLES=OFF -DBUILD_opencv_apps=OFF -DBUILD_JAVA=OFF -DBUILD_FAT_JAVA_LIB=OFF -DBUILD_opencv_python2=OFF -DBUILD_opencv_python3=OFF -DWITH_GTK=OFF -DWITH_WIN32UI=OFF -DWITH_FFMPEG=OFF -DWITH_V4L=OFF -DCPU_BASELINE=NEON -DCMAKE_INSTALL_PREFIX=<my lib module path>/.cxx/Debug/612145b5/x86_64/opencv-install -GNinja <my lib module path>/.cxx/Debug/612145b5/x86_64/opencv-prefix/src/opencv && <my Android SDK path>\cmake\3.18.1\bin\cmake.exe -E touch <my lib module path>/.cxx/Debug/612145b5/x86_64/opencv-prefix/src/opencv-stamp/opencv-configure"
CMake Error: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
As I see, CMake cannot find the following components:
Ninja
C++ compiler
C compiler
I can get rid of the first error, if I add ninja's path from NDK to the PATH variable, I don't think thats how it should be done though. Neither do I want to pass CMAKE_CXX_COMPILER and CMAKE_C_COMPILER to CMake manually, as it seems like it should be done automatically by Android Studio.
So, how can I fix this?

Adding VTK to Android Studio 3.3 project with NDK r17c

I am trying to add the VTK to my native Android project in AS 3.3. I have installed the NDK r17c. I would like to use some of the VTK functionalities in my native application. Also, I am using gradle 3.3.2 for building my android project and CMake 3.6.4 for building native side of the project. My problem is that I haven't found a suitable tutorial (I am new to Android native development) for importing the VTK into the Android Studio using all building tools that I have described. Is there a way to do that?
Also, I would like to add that I am using Windows 7 OS.
EDIT: I had updated my CMakeLists.txt file with some lines I had found relevant in the official example (https://github.com/Kitware/VTK/tree/master/Examples/Android). I would like to use VTK inside my native-lib library:
# 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.
link_directories(src/main/jni/japi src/main/jni/acquisition)
file(GLOB native_SRC
"src/main/jni/japi/*.h"
"src/main/jni/japi/*.cpp"
)
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_SRC})
file(GLOB acquisition_SRC
"src/main/jni/acquisition/*.h"
"src/main/jni/acquisition/*.cpp"
)
#file(GLOB acquisition_SRC
# "src/main/jni/acquisition/*.h"
# )
add_library( acquisition-lib STATIC ${acquisition_SRC})
#add_library(
# acquisition-lib
#
# STATIC
#
# src/main/jni/acquisition/test-lib.h
# src/main/jni/acquisition/test-lib.cpp)
# 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})
target_link_libraries( native-lib acquisition-lib )
set(OpenCV_DIR "../opencv/src/sdk/native/jni")
find_package(OpenCV REQUIRED)
message(STATUS "OpenCV libraries: ${OpenCV_LIBS}")
target_link_libraries(native-lib ${OpenCV_LIBS})
target_link_libraries(acquisition-lib ${OpenCV_LIBS})
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--exclude-libs,libippicv.a -Wl,--exclude-libs,libippiw.a")
##ADDED for including the VTK
find_package(VTK COMPONENTS
vtkInteractionStyle
vtkRenderingOpenGL2
vtkRenderingFreeType
vtkTestingCore
vtkTestingRendering
)
include(${VTK_USE_FILE})
target_link_libraries( native-lib ${VTK_LIBRARIES} )
Ok, it took me about a week to get this working, but it paid off. I will list all the things I needed to do to be able to use VTK in my android application.
STEP 1: Building VTK on Linux machine
Because Android is based on the Linux OS, you need to build libraries in .a or .so format. To do this, the easiest thing to do is to build VTK on Linux machine. So you have to install Linux to your machine eather as dual boot or, as in my case, install a virtual machine that runs Linux.
After that, you need to install all the thing needed to download and build VTK for Android. Here is the list of the things you need to download and install to your Linux machine:
Download and install the Android NDK- I downloaded the same version that I am using in my Android Studio - r17c
Download and install the Android SDK , i.e. Android Studio
Download and install ANT
Download and install Java
Download and install CMake - also after I installed it, I needed to run: sudo apt-get update && sudo apt-get install build-essential
Download and install Git
Install OpenGL - I used: sudo apt-get install freeglut3-dev
Define ANDROID_NDK environment variable - point it to unzipped android NDK folder
Define ANT_HOME environment variable - point it to unzipped ANT folder
Define JAVA_HOME environment variable - point it to unzipped Java JRE folder
Define ANDROID_SDK environment variable - point it to the location of Android/Sdk folder
Define CMAKE_HOME environment variable - point it to the location of your installed CMake
Add to PATH enviroment variable: ANT_HOME/bin, JAVA_HOME/bin, ANDROID_SDK/platform-tools, ANDROID_SDK/tools, CMAKE_HOME/bin
After the installation of the all the needed tools above, you need to download the VTK source code using git:
Create an 'vtk' folder somewhere
cd vtk
git clone https://github.com/Kitware/VTK.git
Now, you can go and build the VTK:
mkdir vtk/vtk-android
cd vtk-android
ccmake ../VTK
press c (configure)
press c (configure)
press q (quit)
cmake -DVTK_ANDROID_BUILD=ON -DANDROID_NATIVE_API_LEVEL=23 -DANDROID_ARCH_ABI=arm64-v8a ../VTK - here I defined the 23 api level because that is what I am using in my applicatin. Also, here is where you define the architecture ABI of your targeted devices. My device is arm64-v8a so I am using that. In order to build VTK for other architectures, you will need to build for every each one of them. Also, you can edit this in the next step!
ccmake ../VTK
OPTIONAL: at this point, you can define additional modules you need in your application. If you just skip this step, the modules (.a files) you will get are:
vtkCommonColor, vtkCommonComputationalGeometry, vtkCommonCore,
vtkCommonDataModel, vtkCommonExecutionModel, vtkCommonMath, vtkCommonMisc,
vtkCommonSystem, vtkCommonTransforms, vtkDICOMParser, vtkdoubleconversion,
vtkexpat, vtkFiltersCore, vtkFiltersExtraction, vtkFiltersGeneral,
vtkFiltersGeometry, vtkFiltersHybrid, vtkFiltersModeling, vtkFiltersSources,
vtkFiltersStatistics, vtkfreetype, vtkglew, vtkImagingCore,
vtkImagingFourier, vtkImagingMath, vtkImagingSources, vtkInfovisCore,
vtkInteractionStyle, vtkIOCore vtkIOGeometry, vtkIOImage, vtkIOInfovis,
vtkIOLegacy, vtkIOPLY, vtkIOXML, vtkIOXMLParser, vtkjpeg, vtkjsoncpp,
vtklibxml2, vtklz4, vtklzma, vtkmetaio, vtkParallelCore, vtkpng,
vtkRenderingCore, vtkRenderingFreeType, vtkRenderingOpenGL2,
vtkRenderingVolume, vtkRenderingVolumeOpenGL2, vtksys, vtkTestingRendering,
vtktiff, vtkWrappingTools, vtkzlib
If these modules are not sufficient for you, you need to add some lines to VTK/CMake/vtkAndroid.cmake file because there the build for android is defined. Lines you add must look like:
-DVTK_MODULE_ENABLE_VTK_[name-of-the-module]:STRING=YES
You can find out all possible name-of-the-module values if you press t (toggle) and scroll to VTK_MODULE_ENABLE_VTK_... part of the configuration.
c (configue)
g (generate)
make
Ok, so the build process starts. On my laptop it took ~30mins (I assigned 3GB of RAM to the virtual machine).
STEP 2 : Importing the VTK to the Android Studio
After the build process is finished, you need to copy the folder vtk/vtk-android/CMakeExternals/Install/vtk-android to the your Windows machine.
The folder lib contains the build VTK library as a set of static libraries (.a files), and the folder include contains all the header files of the VTK you neeed to get the VTK working in full.
Now, in your Android Studio project, create a new Android Library module called vtk.
Create the src/main/jni folder and inside that folder copy the lib and include folder described above.
In jni folder crate an vtk-lib.cpp file which will serve as an interface from your Java code to the VTK library. An example may be:
#include <jni.h>
#include <vtkConeSource.h>
extern "C"
JNIEXPORT void JNICALL
Java_link_to_your_java_function(
JNIEnv *env,
jobject /*this*/) {
vtkConeSource *cone = vtkConeSource::New();
cone->SetHeight(3.0);
cone->Delete();
}
In the build.gradle file of your vtk module, add this lines:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_CPP_FEATURES=rtti exceptions",
"-DANDROID_STL=gnustl_shared"
abiFilters 'arm64-v8a'
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
}
After that, to the jni folder add a CMakeLists.txt file which will be used for building the module:
cmake_minimum_required(VERSION 3.4.1)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI})
add_library(vtk-common-color STATIC IMPORTED)
set_target_properties(vtk-common-color
PROPERTIES IMPORTED_LOCATION
${LIB_DIR}/libvtkCommonColor-8.90.a)
#53 more libraries from lib folder
add_library( vtk-lib SHARED ${PROJECT_SOURCE_DIR}/vtk-lib.cpp)
target_include_directories(vtk-lib PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(
vtk-lib
-Wl,--start-group -L ${TARGET_OUT}
vtk-common-color
#53 more libraries names
-Wl,--end-group
)
And that's it, voila!
You can
start with the official example on GitHub:
NativeVTK is built around the
Android native interface and does not have any Java code associated with it.
Any unser interface elements would need to be created in C++ using regular
VTK widgets or other OpenGL elements. This is best for applications that
are mainly focused on rendering or visualization with very minimal user
interface. In this example all the key code is in jni/main.cxx and it will
look very much like the regular VTK code you are used to.
It doesn't use Android Studio, and for good! Loading huge amounts of 3rd party native code into Android Studio is both useless and frustrating. It is much better to have such libraries compiled with their native build tools, and only import small modules that require lots of changes and/or interactive debugging.

Checking preprocessor directives with Android Studio Gradle Build, NDK and CMake

I'm passing in preprocessor directives via CMakeLists.txt for the build of a native android library using android NDK.
add_definitions(-DMY_DIRECTIVE=1)
It would be great to double check that those preprocessor directives are actually finding their way into the calls to the compiler (llvm ?)
But the gradle build output doesn't seem to include the calls to the compiler, I just get:
Building C object CMakeFiles/my_project.dir/home/me/projects/my_proj/src/my_native.c.o
Is there a means to make the gradle output more verbose such that I can see the actual compiler calls and check those preprocessor directives are present?
The answer is to understand that Gradle utilises CMake to build the android NDK component (shared library) of an android project, and CMake utilises Ninja as a build system to handle the calls to the compiler. The compiler used by android NDK now defaults to LLVM->Clang.
So in order to actually see the Clang calls you have to find the build.ninja files for each target of your android project.
In my case I am only building for an armeabi-v7a target architecture. Therefore the relevant build.ninja files are found in:
/home/me/projects/my_proj/app/.externalNativeBuild/cmake/debug/armeabi-v7a
/home/me/projects/my_proj/app/.externalNativeBuild/cmake/release/armeabi-v7a
cd to either directory and run:
ninja -v
i.e. the -v option is the key to see all the calls to the clang compiler that the native build (android NDK) part of your android project generates.
Note if you have installed CMake via the android package manager, you may find that ninja is not installed in a location that is on your PATH. For me the ninja binary is located as follows:
~/Android/Sdk/cmake/3.6.3155560/bin/ninja
(same directory as cmake binary)
Therefore for me to see all the clang compiler calls for my android project's debug armeabi-v7a build I have to run:
cd /home/me/projects/my_proj/app/.externalNativeBuild/cmake/debug/armeabi-v7a
~/Android/Sdk/cmake/3.6.3155560/bin/ninja -v
Note if ninja tells you ninja: no work to do.
Then run:
~/Android/Sdk/cmake/3.6.3155560/bin/ninja clean
Relevant ninja documentation is -> https://ninja-build.org/manual.html#_extra_tools

Adding sub directory in cmake not working

I'm trying to add another cmake project which has CMakeLists.txt file as a compilation dependency which i can use in another .cpp file.
Location of project which i want to add: Users/brainfreak/Downloads/assimp-master/
Location of main project: /Users/brainfreak/AndroidStudioProjects/ModelShow/app/src/main/cpp/hellojni.cpp
This is used as a native code in a Android Studio project. I followed the tutorial in https://developer.android.com/studio/projects/add-native-code.html#create-cmake-script under "Include other CMake projects"
This is the main CMakeLists.txt that i came up with:
/Users/brainfreak/AndroidStudioProjects/ModelShow/app/src/main/cpp/CMakeLists.txt
cmake_minimum_required( VERSION 2.6 )
add_library(model-lib SHARED hellojni.cpp)
set (src_dir Users/brainfreak/Downloads/assimp-master/)
set (output_dir Users/brainfreak/Downloads/assimp-master/output)
file(MAKE_DIRECTORY ${output_dir})
add_subdirectory(${src_dir} ${output_dir})
add_library(assimp STATIC IMPORTED)
set_target_properties( assimp PROPERTIES IMPORTED_LOCATION
${output_dir}/${ANDROID_ABI}/assimp)
include_directories(${src_dir}/include)
target_link_libraries(model-lib assimp)
The error i always get:
Execution failed for task ':app:externalNativeBuildDebug'.
> Build command failed.
Error while executing process /Users/brainfreak/Android/sdk/cmake/3.6.3155560/bin/cmake with arguments {--build /Users/brainfreak/AndroidStudioProjects/ModelShow/app/.externalNativeBuild/cmake/debug/x86 --target model-lib}
ninja: error: 'Users/brainfreak/Downloads/assimp-master/output/x86/assimp', needed by '/Users/brainfreak/AndroidStudioProjects/ModelShow/app/build/intermediates/cmake/debug/obj/x86/libmodel-lib.so', missing and no known rule to make it
I don't know what file to place under "${output_dir}/${ANDROID_ABI}/" for the script to find. Can you tell where i'm going wrong?
Assuming that you got one of the latest releases from https://github.com/assimp and followed the instructions (note that this was tested with NDK r14, available for download from https://developer.android.com/ndk/downloads/older_releases), you have produced file libassimp.so inside project "Code" folder. Make sure that you build the x86 version of the library.
Copy this file to /Users/brainfreak/Downloads/assimp-master/output/x86/, and prepare your CMakeLists.txt:
cmake_minimum_required( VERSION 2.6 )
add_library(model-lib SHARED hellojni.cpp)
set (src_dir /Users/brainfreak/Downloads/assimp-master/)
set (output_dir /Users/brainfreak/Downloads/assimp-master/output)
file(MAKE_DIRECTORY ${output_dir})
add_subdirectory(${src_dir} ${output_dir})
add_library(assimp STATIC IMPORTED)
set_target_properties( assimp PROPERTIES IMPORTED_LOCATION
${output_dir}/${ANDROID_ABI}/libassimp.so)
include_directories(${src_dir}/include)
target_link_libraries(model-lib assimp)
Note that the file that your script was missing slash (/) before Users which could cause the confusion.
Don't forget to set abiFilters in your app/build.gradle:
ndk {
// Specifies the ABI configurations of your native
// libraries Gradle should build and package with your APK.
abiFilters 'x86'
}

Categories

Resources