So when you go to the official Google Tango SDK Download page you will find the Client API comes with both the header file and a .so library for both ARM v7 and v8 but in the Google Sample repo they have this static library file which if not included in my current Android.mk file will not build. Am I able to build the Client API without needing that static file?
Note: I am trying to build it as a prebuilt going off the sample makefile.
The static library libtango_client_stub.a is a clumsy attempt to resolve the limitation of modern NDK. On the face of it, you don't need this dummy library, but it is referenced in an imported Android.mk (via $(call import-module,tango_client_api)). If you use this Android.mk, you need the libraries in tango_client_api/libs, including the libtango_client_stub.a.
The bottom line is, you need the shared library tango_client_api/lib/armeabi-v7a for linking, but should not have its copy in your APK: this library should be preinstalled on your Tango device (see https://developers.google.com/tango/release-notes#unity_sdk_changes_15).
Related
The Android app I am working on is completely written in C++. I need to integrate it with a static library that also is written in C++. There is no dependency on STL in any of the projects.
The static library uses cmake to build. Unfortunately, the app is based on an old AOSP version of Android NDK and has no support for cmake.
I also have a newer version of Android NDK in a different directory. This version does support cmake toolchains.
I am thinking I will build the static library against the new NDK and use it in my main project. The ABI is the same for both the projects - armv7a.
I have tested this logic with a sample code. It seems to work. I am able to invoke methods in the static library from my main app.
Also, there are no name-mangling issues.
The question I have is if there is any issue I am overlooking.
I am thinking it should not matter that the compilers used to build the sources are different. As long as they are producing arm-compatible code, I should be able to able to integrate them.
As a matter of fact, another library that I am using, gstreamer, is available for download as pre-built binaries at https://gstreamer.freedesktop.org/data/pkg/android.
Please advice.
For those interested, mixing NDKs doesn't seem to be an issue as long as you follow certain guidelines. Some of them are listed at https://developer.android.com/ndk/guides/cpp-support.
Essentially, there is no problem if your project is 'C' based. However, if you are using C++, you must not use STL.
I have managed to build part of my code with two NDKs and I am not seeing any link time or runtime errors.
I do some native Android development which involves OpenSSL.
I cross compile it for armeabi (32b) using the Android NDK stand-alone toolchains. I cross-compile the native C libraries, copy the OpenSSL/native library .so files inside of my libs/ folder, which is referenced by my gradle this way:
sourceSets {
main {
jniLibs.srcDir(file("libs/"))
}
}
Anyway, the end result is that my .apk looks like this:
- > classes.dex
- > lib/
-> armeabi/
-> libcrypto.so
-> libssl.so
-> libmynativelibrary.so
- > res/ (...)
- > resources.arsc
- > META-INF/ (...)
- > kotlin/ (...)
- > AndroidManifest.xml
The shared libraries are correct 32-bit ARM ELF files. I've been using this exact APK on an API level 24 device with great success (Android 7.0+).
The issue: When I switch to an API level 21 device (Android 5.1-, I suspect that I would have the same issue with Android 6.0), the program instantly crashes when loading libmynativelibrary.so.
Since libcrypto.so is a dependency of libmynativelibrary.so, the program attempts to load it. It actually works fine on API level 24+, but crashes on API level 23-. It's because the loaded library is not the one in my .apk, but the one in the system. And such libraries seem to not be available below API level 24.
My question: How do I explicitly tell Android to look for the library in the .apk file first instead of the regular system libraries directories?
Thanks in advance.
Before Nogut, the system libraries were not protected from user apps. The name collisions are problematic, they caused Google to invent a separate namespace for the C++ shared runtime library, which is part of Android NDK.
The OpenSSL libraries are also widely used beyond your control. They may get loaded into your process even before you have a chance to load your own libssl.
Therefore, the best choice would be to build OpenSSL as static libs, and have libmynativelibrary.so linked to it statically. This way you have a monolithic binary that does not depend on others.
If you cannot follow this course, you should build OpenSSL libraries with mangled names, e.g. libmyssl.so and libmycrypto.so. This may help to avoid the simple name clash with system libraries.
Even better, follow the example of NDK and provide a unique namespace to you SSL API.
Don't expect that loading the libraries explicitly from their unpacked location at ApplicationInfo.nativeLibraryDir will be a robust solution: as I hunted before, the system libraries may happen to get loaded into your address space before.
Note that before Lollipop, you have too manually load all non-system dependencies, and in the proper order.
Also, the new NDK has dropped armeabi , so consider switching to armeabi-v7a.
I have an Android Studio project to which I've added an ndk module. My ndk module builds and creates lots of different .so files in various build/intermediates directories. However, when I run the app it is unable to load the library .so from my System.loadLibrary call.
Java files that I include in the same module are found just fine so I was expecting Android Studio to 'find' the ndk files as well.
In looking at the google hello-libs demo I see that they have added a step in the CMakeLists.txt file to set the LIBRARY_OUTPUT_DIRECTORY:
set(distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../distribution)
set_target_properties(gperf
PROPERTIES
LIBRARY_OUTPUT_DIRECTORY
"${distribution_DIR}/gperf/lib/${ANDROID_ABI}")
and then added an associated reference in app:build.gradle
jniLibs.srcDirs = ['../distribution/gperf/lib']
Adding similar entries to my project allowed it to run properly.
Is there a simpler way to cause an ndk compiled module to be included in the main application? If not, is there a way to do it without having to figure out all the relative ../../ path elements. I guess I was hoping the module CMakeLists.txt would be
the same configuration regardless of what other projects it might be included in but having to know where it's including project is located seems to break this.
I have windows dynamic linked library which I want to access from Linux environment. I don't have the source code of that library, so I cannot build .so file.
Is there a way by using Winelib or any other library or tool for converting library file to .so file, so that I can call functions defined in that library?
There is no easy way to do it, because the DLL cannot run in Linux enviromnemt all by itself. It will probably rely on user32.dll msvcrt.dll and friends at runtime, so you'll have to provide those files as well.
You can use winelib, but it doesn't just convert a .dll to an .so. You'll have to link the whole project that wants to call the DLL against winelib, and include the DLL itself with your app at runtime. If you are trying to port a Windows app to Linux, winelib will be able to convert your makefile for you, but it's far from automatic for complex projects.
Here's my dilemma: I'm attempting to create a .dll version of my project. This project uses the V8 and CURL libraries which are currently built as debug .libs. I'd like to package all of them up in a single DLL that can be shared (I understand I need to alter my code with __declspec(dllexport) but that's a separate issue) to others.
Do I need to compile the V8 and CURL libraries as DLLs then somehow wrap them up in my own DLL?
If you have a .lib with no .dll for the CURL libraries, then they are most certainly static libraries. When you link them to your DLL, the code from these libraries is linked into your DLL.
I've generally had to include the source for the dependencies (in your case both V8 and CURL) in my project and build that way to get them completely incorporated without extra headaches.
If you have libs and you link to those you SHOULD get them merged though.