Android app loading shared library from incorrect location - c++11

I am working on an Android app that is using a c++ shared library. Originally, the project works fine. I recently upgrade the Android Studio to version 4.0.1. I also updated my Gradle version to 4.x but after the update, I have strange problems, so the Gradle version is changed back to 3.6.3.
When the code runs to the statement
try{
System.loadLibrary("something");
} catch(Exception e) {...}
The application throws an exception
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN3Eld12PtrModelRefsEv" referenced by "/data/app/com.myapp-aXvdrU70cJvaDOn1c13zEQ==/lib/arm/libsomething.so"...
In the apk file, I can see the library binary file is located in
apk/debug/app-armeabi-v7a-debug.apk/lib/armeabi-v7a/libsomething.so
It seems the app is trying to load the shared library from lib/arm instead of lib/armeabi-v7a
Under the folder something, I have the file build.gradle configs like:
android {
defaultConfig{
ndk {
abiFilters "armeabi-v7a"
}
}
}
Using the readelf -A libsomething.so to check my library file attribute. I have the following result
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "ARM v7"
Tag_CPU_arch: v7
Tag_CPU_arch_profile: Application
Tag_ARM_ISA_use: Yes
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv3
Tag_Advanced_SIMD_arch: NEONv1
Tag_ABI_PCS_GOT_use: GOT-indirect
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: int
Tag_CPU_unaligned_access: v6
Tag_ABI_FP_16bit_format: IEEE 754
I tried to use System.setProperty("java.library.path", "lib/armeabi-v7a"); to change the library loading path. But it does not change anything.
So, how can I let the function System.loadLibrary loading the binary library file from the correct location?
Android Studio version: 4.0.1
Android Gradle Plugin Version: 3.6.3
Gradle Version:6.3

I finally found that I forgot to add a CPP file to the make file. _ZN3Eld12PtrModelRefsEv is a mangled function name of PtrModelRefs which is the most important info I missed. Basically it is saying undefined function.

Related

Use withType() for configuring Gradle task not compiling in IntelliJ

I'm trying to configure the Test task inside a custom Gradle plugin written in Java.
Applying the plugins I need like so in build.gradle.kts:
plugins {
`java-gradle-plugin`
`maven-publish`
}
I can compile the code successfully through the command line as in ./gradlew clean build
But, IntelliJ complains about Test.class in the following code:
public static void configureTesting(final Project project) {
project.getTasks().withType(Test.class).configureEach(task -> {
});
}
Saying:
Required type: java.lang.Class <S>
Provided: java.lang.Class <Test>
reason: no instance(s) of type variable(s) exist so that T conforms to Task
I import the Test class like this:
import org.gradle.api.tasks.testing.Test;
Gradle version: 6.7.1
IntelliJ: 2020.2.3
I spent some (a lot of) time googling this. Eventually I found a comment somewhere saying that one could try to use the internal SDK (jbr) that ships with IntelliJ instead of a manually downloaded SDK. That made it work. The internal SDK is Java 11 and I've also installed the latest version of Java 11 from Oracle. Even though they are both Java 11, the internal SDK (jbr) is working as it should, but not the external SDK. For other projects the external SDK is working fine, but not for building a Gradle plugin.

NDK Error "Unexpected native build target xyz. Valid targets are:"

I have an Android Studio project which depends on a native shared library. I have created a cmake file to compile the library and I have added a soft link to the shared library inside the android project (in src/main/jniLibs/armeabi). That way when the android project is built, the shared library is included in the package.
Here is the relevant part of build.gradle:
android {
...
externalNativeBuild {
cmake {
path "../cpp/CMakeLists.txt"
}
}
}
The problem is that gradle tries to open the shared library before invoking the instructions to build it.
Information:Gradle tasks [:app:assembleDebug]
Error:Could not list contents of 'app/src/main/jniLibs/armeabi/libfoo.so'. Couldn't follow symbolic link.
How can I invoke the cmake from inside the project and include the library in the project at the same time?
--
EDIT
In the cmake the shared library is built with ExternalProject_Add. Unfortunately gradle doesn't see that target, nor does it see imported shared libraries as targets. So this does not work:
add_library(libfoo SHARED IMPORTED GLOBAL)
add_dependencies(libfoo libactual)
I tried to invoke building the particular target with a gradle config:
defaultConfig {
...
externalNativeBuild {
cmake {
targets "libfoo"
}
}
}
But gradle still doesn't see it and fails with:
Unexpected native build target libfoo. Valid values are:
The valid values are basically an empty list.
Currently I work around this by creating a fictional executable depending on the library.
add_executable(libfoo a.c)
add_dependencies(libfoo libactual)
In my case, I added a new CMake target, but having none was cached somehow (by CMake or Gradle).
Simply close Android Studio, remove the entire build or .build directory, then open Android Studio and build again.
Note that sub-projects have their own separate build directory.
So, you may need to search for the word build, and after ensuring found result is not required, remove them too.
If still not fixed, remember that CMake has it's own separate cache files, which normallay are inside said directories unless you run CMake directly (outside of Android Studio).

Android Studio NDK error, couldn't find GLES3/gl3.h although it exist

I'm trying to make an app on Android Studio that use the NDK and OpenGL ES 3.0.When I #include < GLES3/gl3.h >, the IDE has auto completion as I typing, I think it's a sign meaning that the IDE can find it
However, I got the error : "Error:(22, 10) fatal error: 'GLES3/gl3.h' file not found" when I build the project. I check the NDK path in Project Structure, which is :
sdk\ndk-bundle\platforms\android-21\arch-arm64\usr\include\GLES3
it's correct and the GLES3/gl3.h does exist there.
I have declared my CMakeList with GLESv3 already:
cmake_minimum_required(VERSION 3.4.1)
# now build app's shared lib
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
add_library(gl3jni SHARED
gl_code.cpp
stb_image.cpp
)
# add lib dependencies
target_link_libraries(gl3jni
android
log
EGL
GLESv3)
I also declare the OpenGL ES version in the Manifest.xml with:
<uses-feature android:glEsVersion="0x00030000" android:required="true"/>
What am I doing wrong?
Android ndk-bundle has openglES3 since api 18, but in arm platform.
I mean, if you are going to compile your project in armV8_64, you must set your min sdk to 21. But if you are going to use armeabi or armeabiV7 the minimum api will be 18.
So change your minSDK dependig on your preferences in the app/build.gradle file.
I suggest you to define the API 21 and define your product flavours to support for all architectures, besides you can make other 3rdparty library linkings, the code should be something like this:
android.productFlavors {
// for detailed abiFilter descriptions, refer to "Supported ABIs" #
// https://developer.android.com/ndk/guides/abis.html#sa
create("arm") {
ndk.abiFilters.add("armeabi")
ndk.ldFlags.add("-L${file(''your_libraries_path'')}".toString())
ndk.ldLibs.addAll(["your_armeabi_library"])
}
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
ndk.ldFlags.add("-L${file('your_libraries_path')}".toString())
ndk.ldLibs.addAll(["your_armv7_library"])
}
create("arm8") {
ndk.abiFilters.add("arm64-v8a")
ndk.ldFlags.add("-L${file(''your_libraries_path')}".toString())
ndk.ldLibs.addAll(["your_armv8_library"])
}
}
This gradle code is from the gradle 0.8.3 experimental plugin, so if you have not this version, you need to make some changes to fit into your gradle version.
For me I only have to change the minSdkVersion in build.gradle to 19.
do not forget to set
APP_PLATFORM := android-23 (or other depending on uelordi answer)
to application.mk

Adding OCMock to Xcode will not link at runtime

I'm trying to get a basic app mac app running with XCTest and OCMock. But I am getting linking errors at runtime, I have several plain XCTests that run just fine, but the OCMock test is not working (other test hidden for brevity):
#import <OCMock/OCMock.h>
- (void)testLoadingInvalidSettingsThrowsAnError
{
id harkMock = [OCMockObject mockForClass:[Hark class]];
[[[harkMock stub] andReturn:#"bla"] getSettingsAsRawJson];
XCTAssertThrowsSpecificNamed([harkMock loadSettings], NSException, #"InvalidJson");
}
The error received at runtime:
2014-02-21 11:02:47.929 Hark[90819:303] Error loading /Users/chancee/Library/Developer/Xcode/DerivedData/Hark-bsndafsdxydbivhhuuuyelepegkp/Build/Products/Debug/HarkTests.xctest/Contents/MacOS/HarkTests: dlopen(/Users/chancee/Library/Developer/Xcode/DerivedData/Hark-bsndafsdxydbivhhuuuyelepegkp/Build/Products/Debug/HarkTests.xctest/Contents/MacOS/HarkTests, 262): Library not loaded: #rpath/OCMock.framework/Versions/A/OCMock
Referenced from: /Users/chancee/Library/Developer/Xcode/DerivedData/Hark-bsndafsdxydbivhhuuuyelepegkp/Build/Products/Debug/HarkTests.xctest/Contents/MacOS/HarkTests
Reason: image not found
What I've done:
Download the latest OCMock.framework and placed it into /Library/Frameworks
For my HarkTests target in Xcode I have added OCMock in the "Link Binary With Libraries" - however it does not show up in the list of available frameworks, I have to manually navigate to it. This raises a red flag for me, but I don't know why Xcode doesn't recognise it.
Compiles fine. But throws the above error at runtime (so no tests run).
The logic for finding frameworks at compile time is different from the logic for finding the framework at runtime. OCMock uses the #rpath mechanism. I would have thought that /Library/Frameworks is on the path by default. That doesn't seem to be the case. You could try to set the Runpath Search Paths build setting to include the directory into which you have installed OCMock.

Android studio include aar dependency

I'm trying to add ActionbarSherlock as dependency using line I got from gradleplease
(Instead of these methods. At least according to this link:
"In Gradle you no longer need to add in these libraries as source code projects; you can simply refer to them as dependencies, and the build system will handle the rest; downloading, merging in resources and manifest entries, etc. For each library, look up the corresponding AAR library dependency name (provided the library in question has been updated as a android library artifact), and add these to the dependency section."
this setup should not be necessary anymore)
But it doesn't work and module settings in Android studio shows error: "Library 'ComActionbarsherlockComActionbarsherlock440.aar': Invalid classes root"
Any idea?
Add these line in your module build.gradle
dependencies {
compile 'com.actionbarsherlock:actionbarsherlock:4.4.0#aar'
}

Resources