I'm new to Android's NDK and I don't understand the differences between static and shared libraries. What are they, and when would I choose one type over the other?
The term shared library is not a perfect fit regarding Android's NDK, because in many cases the .so libraries aren't actually shared between applications. It's better to classify the libraries that the NDK builds as static and dynamic.
Every Android application is a Java application, and the only entry point for the NDK code is loading it as a dynamic library and call it trough JNI.
Static libraries are an archives of compiled object files. They get bundled in other libraries at build time. Unused portions of code from static libraries are stripped by the NDK to reduce total size.
Dynamic libraries are loaded at runtime from separate files. They can contain static libraries that they are dependent on or load more dynamic libraries.
So what you actually need for Android development is at least one shared library, that will be called from Java code, and linked with it's dependencies as static libraries preferably.
Native shared libraries: The NDK builds these libraries, or .so files, from your native source code.
Native static libraries: The NDK can also build static libraries, or .a files, which you can link against other libraries.
This is according to NDK Documentation
Static libs – all library binaries will be included as part of our executable during the linking process. Thus, we won’t need the libs anymore, but it’ll increase the size of our executable file.
Shared libs – the final executable only has references to the libs, not the code itself. It requires that the environment in which we run our executable has access to all the files of the libs used by our program.
Related
I have a dynamic linked library (.so) built for general Linux platforms usage (x86, armv7a), now I'm going to port the library for Android usage.
What I expect is to use dlopen in the JNI library's CPP code to access the other library which is not in JNI form. So that I only need to develop a few JNI functions to bridge the exported functions of the original library.
This is all for avoid rebuilding whole codes of the original library. There are a large number of source files and the structure is very complicated. Otherwise I have to rewrite the makefile for NDK building for them.
To try this concept, I almost progress to the last step.
First, I put the original library and JNI library together in location /data/data/com.example.myapp/lib in the device's root file system (I use the emulator in Android Studio, the tool will copy .so files in project's lib folder automatically in installation).
The following I use adt to login the android's shell and I issue file command to list the files in the lib directory
generic_x86_arm:/data/data/com.example.myapp/lib # file *
libSmart.so: ELF shared object, 32-bit LSB 386, BuildID=179c89de2ebe921fe1b9be6e78e83148f3781568, stripped
libmain.so: ELF shared object, 32-bit LSB 386, for Android 16, built by NDK r21e (7075529), BuildID=6b395607222185aac9c163dc205b26add1ab55c4, stripped
libSmart.so: The original library I built for general Linux platforms
libmain.so: The JNI library which will called by JAVA of android activity.
I can open libSmart.so by fopen(), but can't open it by dlopen() which it returns NULL.
Is there some constraints to do these? Or is any libraries used in Android (even not directly called by JAVA) must be built with JNI?
I am sorry maybe this is stupid what I am asking, but I have a question about linking static/shared libraries in android.
I am creating a new C++ Native android studio project. After build, I open the apk file, and inside lib the folder there are placed libraries libnative-lib.so for every ABI. Size of APK is 3.580 KB.
But if I change inside CMakeLists.txt to build the native lib like Static lib, so now I got this:
add_library(native-lib
STATIC
native-lib.cpp)
When APK is built, I can not find the static library (libnative-lib.a). There is no lib folder in the apk. Also, the size is 2.836 KB.
Can someone please explain(or give me link for more info about this) where is the library placed in the STATIC build?
And on run I got error if I link static:
No implementation found for java.lang.String com.example.myapplication.MainActivity.stringFromJNI()
You can't use native static libraries directly in Android apps.
Android user space is basically a Java (or more precisely Dalvik VM).
So all user-facing applications must be written in Java or Kotlin (which both compile to Dalvik bytecode).
Static C/C++ libraries must be link in to a C/C++ executable or dynamic library to be used. They can not be loaded directly by Linux or Android.
Since Android app does not have a C/C++ executable in it, the only way to use a static library with an Android app is to link it with a dynamic library (*.so) that can be loaded via Java Native Interface.
Since JNI uses the system loader to load the library, it can only load dynamic libraries, and of those, only ones that export functions with proper naming conventions so they can be matched to a Java class that will be used to call the native code.
Usually when including native libraries in Android, shared libraries are used and loaded at runtime via System.load().
In my case, I've got a static library (.a archive) compiled for Android which I want to access in Java-Code.
Is it even possible to access static libraries without the approach of linking it in a shared library and then loading the shared library?
I just found following question linking static library.
The answer is to link the static library into shared library then load the shared library.
Here is what I want to do:
There is a project written in c/c++ that I want to compile and deploy to an Android device.
I want every library that this project references to be statically linked to the whole compilation so that I can get a self contained binary (or a couple of them).
Question 1: After searching I found that there are more or less two types of libraries, dynamic and static. My question here is, do I have to provide the static libraries or is the gcc toolchain able to somehow compile them from the headers?
Question 2: When searching about static linking I only found examples of using flags only for a finite amount of libraries and for object files. I want a recursive function. That is "for every library reference within the project link the static version of it. If there is not such version, compile and link it (is this possible?)
Libraries cannot be compiled from headers. You need the sources of all libraries you need. Usually, such sources come with their build scripts, and these scripts may allow choosing static or shared target. Unfortunately, in some cases only one target type is supported.
Typically, we build third party libraries separately, using their build scripts (some involve standalone toolchains, others may use CMake to configure, yet others - and their share increases as Android platform grows in popularity - provide Android.mk build scripts and are compiled with convenient ndk-build command.
At any rate, the app that uses these libraries must include explicit references to all these libraries, usually by adding include $(PREBUILT_STATIC_LIBRARY) to its Android.mk. But if you have many libraries in one directory, you can use gnu-make wildcards, e.g.
LOCAL_LDLIBS += -Ljni/libs $(patsubst jni/libs/lib%.a,-l%,$(wildcard jni/libs/lib*.a))
So , I have installed Ubuntu(but still use the Android kernel) on my Android phone with the intention of using it to compile native code for the device using the glibc.
I made a library, which I plan to use it in an app which I want to make, using JNI, but I am using the math library. My question is:
Is there a way to include these libraries into the library that I
created so that my phone can use the glibc library instead of the
bionic(which is what the NDK uses) library?
NOTE: I have tried making a test program that uses the library and statically links to make sure that the compiled code would work on the android OS and not just Ubuntu, and I came to the conclusion that it does :) So any answer pertaining to my question would be a great help.
You can use ar to extract the original .o files from any .a files:
ar x libm.a
You can then select whichever .o files you like and link them into your own code.
.a library files can be viewed as tar files with extra symbol-index features (although I don't know how similar the internals are).
WARNING: in general, you can only use .o files from static libraries in your main application. If you try to link them into a shared library (.so file) you may be out of luck. The .o file needs to have been created with -fPIC for that to work, and this is often not the case for static libraries.