Cmake : Building .dylib to test Android JUnit tests - android

I am working on Android native project using C++ code built using CMake. Currently my app is running fine and native lib(.so) is successfully loaded using System.loadLibrary().
But I want to test JUnit tests on my mac in Android Studio. When running tests on mac, It throws error
myapp.dylib not found.
Here is my CMakeLists.txt :
cmake_minimum_required(VERSION 3.18.1)
# Declares and names the project.
project("myapplication")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)
add_library( # Sets the name of the library.
myapplication
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp
native2.cpp)
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)
Here is my cpp file:
#include <jni.h>
#include <string>
#include "header.h"
#include<android/log.h>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
return env->NewStringUTF(hello.c_str());
}
To build .dylib when running cmake from command line, I get other errors like jni not found and liblog(android log library) not found.
Is there a way that I can build .dylib for mac OS in such a way that it can resolve android specific dependencies like jni and log library?

Related

error: undefined reference to 'oboe::AudioStreamBuilder::openStream(oboe::AudioStream**)'

I'm trying to use Google Oboe from my Android NDK application.
When I try to use oboe::AudioStreamBuilder from native-lib.cpp all is working fine.
But when I try to use oboe::AudioStreamBuilder from a class then I get the error message "error: undefined reference to 'oboe::AudioStreamBuilder::openStream(oboe::AudioStream**)'" when I rebuild the project.
Here is native-lib.cpp that is ok :
#include <jni.h>
#include <string>
#include <android/log.h>
#include "OboeAudioRecorder.h"
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_oboeaudiorecorder_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_example_oboeaudiorecorder_MainActivity_recordAudio(
JNIEnv * env,
jobject MainActivity
) {
oboe::AudioStreamBuilder builder;
builder.setDirection(oboe::Direction::Input);
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
builder.setDeviceId(0);
oboe::AudioStream *stream;
oboe::Result r = builder.openStream(&stream);
if (r != oboe::Result::OK) {
return false;
}
return true;
}
And here is the class that cannot compile :
#include <oboe/Oboe.h>
#include <oboe/AudioStreamBuilder.h>
#include "OboeAudioRecorder.h"
OboeAudioRecorder::OboeAudioRecorder() {
oboe::AudioStreamBuilder builder;
builder.setDirection(oboe::Direction::Input);
builder.setPerformanceMode(oboe::PerformanceMode::LowLatency);
builder.setDeviceId(0);
oboe::AudioStream *stream;
oboe::Result r = builder.openStream(&stream);
if (r != oboe::Result::OK) {
return;
}
}
The CMakeLists.txt file :
# 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)
# <Begin> OBOE SPECIFIC
# Set the path to the Oboe directory.
set (OBOE_DIR "../../../../../oboe")
# Add the Oboe library as a subdirectory in your project.
# add_subdirectory tells CMake to look in this directory to
# compile oboe source files using oboe's CMake file.
# ./oboe specifies where the compiled binaries will be stored
add_subdirectory (${OBOE_DIR} ./oboe)
# Specify the path to the Oboe header files.
# This allows targets compiled with this CMake (application code)
# to see public Oboe headers, in order to access its API.
include_directories (${OBOE_DIR}/include)
# <End> OBOE SPECIFIC
# 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 )
add_library(
OboeAudioRecorder
SHARED
OboeAudioRecorder.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 oboe OboeAudioRecorder
# Links the target library to the log library
# included in the NDK.
${log-lib} )
In your CMakeLists.txt change:
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 )
to
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
OboeAudioRecorder.cpp
)
And remove all other references to OboeAudioRecorder.
Why does this work?
With the following lines you're attempting to build another library called OboeAudioRecorder:
add_library(
OboeAudioRecorder
SHARED
OboeAudioRecorder.cpp
)
This library is dependent on oboe but you don't specify that anywhere, you only specify the dependencies for the native-lib library:
target_link_libraries( # Specifies the target library.
native-lib oboe OboeAudioRecorder
# Links the target library to the log library
# included in the NDK.
${log-lib} )
That's why you get error: undefined reference when linking the OboeAudioRecorder library.
You could add a 2nd target_link_libraries(OboeAudioRecorder oboe) line but my guess is you don't want 2 separate libraries, you just want a single library which is dependent on oboe.

Compile two projects on NDK w/ gradle, one of which depends on the other's binary

I'm compiling a library in gradle like this:
externalNativeBuild {
// Encapsulates your CMake build configurations.
cmake {
// Provides a relative path to your CMake build script.
path "../../JRTPLIB/CMakeLists.txt"
}
}
I need to compile another source, probably using cmake or any other tool, also inside gradle, that will link to the compiled object from the lib above (JRTPLIB).
The obvious way would be to include the source of the library above in the lib I want to use and just link, but I need to do it separatedly.
The other way would be to rely on the generated library object at android/app/build/intermediates/cmake/... but first, it's supposed to have a debug binary and a release one in this folder, making it more coplicated to link, and secondly, it's not an elegant solution.
So how to do it?
Here's a simple example that accomplishes something like what I think you're trying to do.
Two libraries are being built and packaged into the app, where the second library depends on the first one. I chose to have lib1 and lib2 as part of the current project, but they could really be located anywhere.
app/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_subdirectory(src/main/cpp/lib1)
add_subdirectory(src/main/cpp/lib2)
app/src/main/cpp/lib1/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib1
SHARED
native-lib1.cpp )
target_include_directories(native-lib1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
app/src/main/cpp/lib2/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
native-lib2
SHARED
native-lib2.cpp )
find_library(log-lib log)
# native-lib2 depends on log and native-lib1
target_link_libraries(native-lib2 ${log-lib} native-lib1)
app/src/main/cpp/lib1/native-lib1.h
#pragma once
int foo();
app/src/main/cpp/lib1/native-lib1.cpp
#include "native-lib1.h"
int foo()
{
return 42;
}
app/src/main/cpp/lib2/native-lib2.cpp
#include <jni.h>
#include <android/log.h>
#include <string>
#include "native-lib1.h"
extern "C" JNIEXPORT jstring JNICALL Java_com_example_cmaketwolibs_MainActivity_stringFromJNI(
JNIEnv *env, jobject thiz) {
// Call function from native-lib1
__android_log_print(ANDROID_LOG_WARN,
"native-lib2", "Calling native-lib1\'s foo(): %d",
foo());
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

Error:(49) undefined reference to 'cv::Stitcher::createDefault(bool)' in using OpenCV native in Android

I am developing an Android application that involves some image processing. I am now stitching images using OpenCV. I am doing it in c++. So, I integrated the OpenCV (both native c++ and Java) into my Android project. But when I use the stitching features in c++ and run my project, it is giving me the compilation error.
This is my whole c++ library (native-lib) for stitching images.
//
// Created by Acer on 3/28/2018.
//
#include <jni.h>
#include <string>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <fstream>
#include <opencv2/stitching.hpp>
using namespace std;
using namespace cv;
extern "C" {
jstring
Java_media_memento_memento_SphereCameraActivity_stitchPhotos(
JNIEnv *env,
jobject /* this */, jlong addrMat, jlong addrNewMat, jlongArray addrsPreviews) {
Mat &in = *(Mat *) addrMat;
Mat &newMat = *(Mat *) addrNewMat;
int size = env->GetArrayLength(addrsPreviews);
jlong *addrPreviewArray = env->GetLongArrayElements(addrsPreviews, NULL);
vector<Mat> imgs(size);
for (long i = 0; i < size; i++) {
jlong previewAddress = addrPreviewArray[i];
imgs[i] = *(Mat *) previewAddress;
}
bool try_use_gpu = false;
Mat pano;
Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
Stitcher::Status status = stitcher.stitch(imgs, pano);
if (status != Stitcher::OK) {
//the return map would be null
} else {
//copy the map.
pano.copyTo(newMat);
newMat = pano;
}
env->ReleaseLongArrayElements(addrsPreviews, addrPreviewArray, 0);
}
}
This is my CMakeList.txt file
set(pathToProject C:/Users/iljim/Desktop/memento/memento-android)
set(pathToOpenCv C:/Users/iljim/Desktop/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk)
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_VERBOSE_MAKEFILE on)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(C:/Users/iljim/Desktop/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk/sdk/native/jni/include)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
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).
src/main/cpp/native-lib.cpp )
add_library( # Specifies the name of the library.
cubemap
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/cubemap.cpp )
add_library( lib_opencv SHARED IMPORTED )
set_target_properties(lib_opencv PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_java3.so)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included 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 the
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# OpenCV lib
lib_opencv
# Cubemap lib
cubemap
# Links the target library to the log library
# included in the NDK.
${log-lib} )
When I run, I got the mentioned error.
Error:error: linker command failed with exit code 1 (use -v to see invocation)
Error:(49) undefined reference to 'cv::Stitcher::createDefault(bool)'
Error:(50) undefined reference to 'cv::Stitcher::stitch(cv::_InputArray const&, cv::_OutputArray const&)'
I found this link - undefined reference to `cv::Stitcher::createDefault(bool)'. But I believe I integrated the c++ opencv native lib properly. That is why I can use other libraries. When I check the file in the SDK folder, the stitching.hpp exists. So, what might be possible and how can I solve it?
I had a quite similar problem and solved it with linking "libopencv_stitching.a" static library from OpenCV SDK in my CMakeLists.txt file.
file(GLOB CVLIBS
path/to/your/opencv/sdk/staticlibs/${ANDROID_ABI}/libopencv_stitching.a)
...
target_link_libraries( # Specifies the target library.
...
${CVLIBS}
# Links the target library to the log library
# included in the NDK.
${log-lib})
Also this answer can be useful as well: Building OpenCV for Android and using it with the NDK

opencv header file not included in cpp file android studio

I am learning OpenCV library and want to develop a face recognization app, to do so I started with the integration of NDK with the android studio but I am stuck here in between.
I am able to successfully print the text message from cpp to activity in the Android framework
// Cpp Code
extern "C"
JNIEXPORT jstring JNICALL
Java_com_detectface_tasolmyfacerec_utils_Opencv_toastCPPNative(JNIEnv *env, jobject instance) {
std::string hello = "OpenCV FaceDetection";
return env->NewStringUTF(hello.c_str());
}
//Java Code
public native String toastCPPNative();
But when started adding the cpp supported headers they are not included and showing red highlight text, I want to include that files so that I can use the opencv algorithms
#include <opencv2/core.hpp>
CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
add_library( # Sets the name of the library.
facedetection-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/facedetection-lib.cpp )
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 )
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
I am providing the screenshots also

Compiling 1 library with 2 sub-libraries with Android Studio's CMake and NDK

Working on an Android NDK project. The project is using CMake to build the C++ libraries.
The library has the following structue -
Main Library
main.cpp
CMakeLists.txt
hello (sub library)/
CMakeLists.txt
include/
hello.h
src/
hello.c
world (sub library)/
CMakeLists.txt
include/
world.h
src/
world.c
The contents are the following:
main.cpp
#include <jni.h>
#include <string>
#include <hello.h>
#include <world.h>
extern "C"
JNIEXPORT jstring
JNICALL
Java_com_test_myapplication_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string str = hello() + world();
return env->NewStringUTF(str.c_str());
}
CMakeLists.txt for main.cpp
cmake_minimum_required(VERSION 3.4.1)
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).
src/main/cpp/native-lib.cpp )
add_subdirectory(src/main/cpp/hello)
include_directories(src/main/cpp/hello)
add_subdirectory(src/main/cpp/world)
include_directories(src/main/cpp/world)
target_link_libraries( # Specifies the target library.
native-lib
hello
world)
world.h
#include <string>
std::string world();
world.c
#include "world.h"
std::string world() {
return std::string("world");
}
CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (world)
add_definitions(/DVERSION="0.4.0")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os")
include_directories(include/)
set(SOURCES
src/world.c
include/world.h
)
add_library(world STATIC IMPORTED
${SOURCES}
)
target_include_directories(world PUBLIC ./)
The content is the same for the "hello" library as the only difference is the output returned from hello's function.
Now, my experience with CMake is close to non-existent and I can't get this to work. I'm constantly getting errors upon building it. Latest error is the following -
CMake Error at src/main/cpp/hello/CMakeLists.txt:19
(target_include_directories): Cannot specify include directories for
imported target "hello". CMake Error at
src/main/cpp/world/CMakeLists.txt:19 (target_include_directories):
Cannot specify include directories for imported target "world".
I just can't find a way to compile all of it into a simple library that will be used in the app. Sometimes I get " not found", sometimes it can't find the header files and etc.
I'd appericiate if someone will be able to post a simple structure and CMake of the correct way of doing so as I'm lost.
In the actual project I try to use libmicrohttpd, but again, can't make it work. I've tried using CentOS's libraries but Android Studio seems to use the system's libraries which causes things to get messed up. This is the reason for which I download the library and try to compile it via Android Studio.
So, again, if anyone will be able to find a way to compile all of the 3 libraries together into a single library (main) which connected the other 2 (hello, world), I'd greatly appericiate it.
Much appericiated.

Categories

Resources