I was able to follow directions in this question to build a shared lib of openssl for Android.
E.g.
cd openssl-fips-2.0/
./config
make
make install
And
cd openssl-1.0.1c/
./config fips --with-fipsdir=/usr/local/ssl/fips-2.0/ shared
make depend
make
This generates libcrypto.so.1.0.0 and libssl.so.1.0.0 with corresponding symbolic links to them as libcrypto.so and libssl.so.
Since the NDK build system doesn't support versioned shared libraries I had to use the symbolic links (with PREBUILT_SHARED_LIBRARY). However, with this, the libraries end up getting to the device as libcrypto.so and libssl.so instead of as libcrypto.so.1.0.0 and libssl.so.1.0.0 causing my library to fail to load as it is looking for the libraries with the version names.
The linked question mentions loading the libraries with System.load(libcrypto.so.1.0.0) instead of with System.loadLibrary() but I have not been able to get this to work even with full paths since as mentioned earlier, the file is copied to the device as libcrypto.so.
Anyone done this successfully?
Note: I've also tried modifying the openssl-1.0.1c config and makefiles to generate libcrypto.1.0.0.so (e.g. with the version number before the extension in the filename and soname) and this allowed me to get around the previous loading issue. However, with that I get an error when I try to turn on FIPS mode with FIPS_module_mode_set (FIPS_R_FINGERPRINT_DOES_NOT_MATCH).
I don't know yet why that is happening, but it could be due to NDK stripping of 'unneeded' stuff (see this question)... I'm still looking at this as well but if someone has some info on this as well it would be MUCH appreciated.
Let us identify the problem correctly. It's likely not the NDK build that causes problems, and definitely not the linker which strips away unused entries when it builds a shared lib from static lib.
First of all, I am not sure you can deliver FIPS mode in a usual APK, without rebuilding or at least rooting Android (see for example http://gcn.com/articles/2010/12/23/android-fips-security.aspx).
There is no problem for System.load() to load a versioned .so when you a) specify the full path correctly (e.g. System.load("/data/local/tmp/libssl.so.1.0.0")) and b) the file is delivered to that path. For the first tests, I would suggest to manually upload libcrypto.so.1.0.0 and libssl.so.1.0.0 to /sdcard/ and see if FIPS fingerprint becomes happier.
If the location on /sdcard/ causes any problem, you can try /data/local/ or /data/local/tmp/. You can also use /data/data/(your package)/files/. The latter has one advantage: it will be automatically deleted by the system when your app is uninstalled.
To make a versioned .so (like libcrypto.so.1.0.0) part of your APK, copy it to the assets folder of your project. It will be responsibility of your Java code to copy it from there to the designated location on disk. Make sure this Java code handles correctly upgrades and SD card swaps.
Related
Assume we have a jni folder structure below.
armeabi
a.so
b.so
armeabi-v7a
a.so
On a ARMv7-based device, I want to load b.so, but the there is no b.so under folder "armeabi-v7a", so will the system report a not found library error or use the b.so under folder "armeabi"?
And even more, what order does system look for a so file among armeabi,armeabi-v7a,arm64-v8a,x86,x86_64? For example, on a x86_64-based device, system look for the so file in folder x86_64 first, but if not found, will system continue to look for the file in x86,arm64-v8a,armeabi-v7a,armeabi in sequence?
Have you seen: http://developer.android.com/ndk/guides/abis.html#am
I believe it answers your questions:
Both the Play Store and Package Manager expect to find NDK-generated
libraries on filepaths inside the APK matching the following pattern:
/lib/<abi>/lib<name>.so
If the system does not find the native shared libraries where it expects
them, it cannot use them. In such a case, the app itself has to copy the
libraries over, and then perform dlopen().
Further down the page is this particular bit:
Automatic extraction of native code at install time
When installing an application, the package manager service scans the APK, and looks for any shared libraries of the form:
lib/<primary-abi>/lib<name>.so
If none is found, and you have defined a secondary ABI, the service scans for shared libraries of the form:
lib/<secondary-abi>/lib<name>.so
When it finds the libraries that it's looking for, the package manager copies them to /lib/lib.so, under the application's data directory (data/data//lib/).
If there is no shared-object file at all, the application builds and installs, but crashes at runtime.
So in your case if you are on a armeabi-v7a architecture, you'll have to copy the lib/armeabi/libb.so file over and use dlopen() as the PackageManager knows nothing of what needs to be loaded in your app but did find something in the lib/armeabi-v7a directory.
In addition to Morrison Chang's answer, one could always consider dropping the armeabi part altogether (so you don't need two copies of the lib, which I guess is large). In practice, there are very few modern devices (running Android 4.0 or newer) that support armeabi but not armeabi-v7a (and none since Android 4.4). See https://stackoverflow.com/a/30924571/3115956, https://stackoverflow.com/a/28926267/3115956 for a few cases of that. That will reduce the file size without losing support for any significant part of your target userbase, assuming that you require Android 4.0. If you still target older versions, it's more of a reason to keep armeabi though.
I'm using the Native Development Kit (NDK) in a project of mine, and I'm trying to automate the whole app build procedure with Python.
Whenever ndk-build is called, it copies the prebuilt shared libraries to libs/<abi>/, even if there's no changes in them or they already exist there. This causes problem when I call ant later on, as it detects changed files (the library timestamps are newer) and so rebuilds the apk without any need.
Is there a way to change the ndk-build behaviour so it checks for existing libraries in the libs/<abi>/ folder and if they need updating or some are missing, it will call ndk-build, otherwise, just proceed to the next build step?
I've tried using filecmp in Python, but as the timestamps are different between the prebuilt shared libraries and the installed ones, it doesn't work.
The OP probably doesn't need this any more, but I had the exact same problem, trying to set up a Makefile to build a project, so maybe this will be helpful to someone else in the future as well.
ndk-build is a wrapper around gnu make, that invokes a bunch of Makefiles in build/core directory of the ndk, so, while it's not universally applicable*, for your personal project you can modify those Makefiles to do whatever you want. I found a clean-installed-binaries target that a couple of build/install targets depended on, removing those dependencies fixed the issue with perpetual installs.
In whichever cases that clean target is necessary you can invoke it manually with:
ndk-build clean-installed-binaries.
*Given the time to come up with a clean opt-in solution you can submit a patch to ndk project, and if accepted it will eventually become universally applicable.
Can somebody help me write Android.mk for LibXtract or point me in correct directoin?
Here is source for lib - https://github.com/jamiebullock/LibXtract.git
Or mayby there is a way to use linux generated shared objects in Android?
Especially for bigger established projects, crafting Android.mk files is quite an effort. More so, if you are not familiar with Android NDK build architecture whose understanding requires digging deep into the documentation and Android NDK make files. I would suggest trying to use existing make files by setting CC to point to your NDK tool chain, and CFLAGS += -sysroot $(SYSROOT) where SYSROOT=${NDK_INSTALL_DIR}/platforms/android-<level>/arch-<arch>/ (depending on targeted Android API version and architecture). Even without knowing about your library, I would bet you should have good chance of success this way. Android NDK documentation (${NDK_INSTALL_DIR}/doc/STANDALONE-TOOLCHAIN.html) details the use of independent tool chain and also instructs how to create a standalone tool chain that will not require the use of -sysroot argument to xxx-gcc.
If you decide to use Android.mk instead, you might check existing projects -CSipSimple comes to my mind (PJSIP converted from standard form GNU make files).
Important is to create the shared objects using Android tool chains. It is possible to build them outside of your application source tree, and then just copy the shared objects into the package source libs/<architecture>/ directory.
Integration with your build system depends on details that are not known (including how smooth you desire this whole integration to be e.g. because of other people working with the same project). If you are creating an application from command line, the easiest would be to have GNU make file or shell script in the package root directory ensure libXtract.so and your application package is up-to-date by calling libXtract make file and ant to build and pack your Java application. If you are using ant there should be a way to specify using make to take care of libXtract.so. I am not sure if eclipse is completely relying on ant for building an application to know if this would be enough for enabling complete build by clicking mouse buttons from within eclipse, too.
The answer to this question says you could use cmake script to build Android.mk files - I have not tried this approach.
I wish to back port the Android RTP APIs introduced in version 3.1(Honeycomb) to earlier versions. I downloaded the source of version 4.0 and found that it these APIs had both java and native code. In order to build the native code with the NDK, certain shared libraries are required.
According the Android.mk file, these are libnativehelper, libcutils, libutils, and libmedia. Though the source of all of these are present in the source code, building them was difficult. Each required many other shared libraries. For eg, libmedia requires these shared libraries: libui, libcutils, libutils, libbinder, libsonivox, libicuuc, libexpat, libcamera_client, libstagefright_foundation, libgui and libdl.
So my question is, is there some way of obtaining the original 4 shared libs? Does it involve building the entire source?
Say I need to build a piece of native code which is going to use standard Android shared libraries such as libutils, libcutlis, libmedia. I would perform following steps:
Install AOSP repository with target version.
Add my source code to appropriate directories under ./frameworks/base. In your case it might be easier to create a separate folder and put proper Android.mk of course.
You might get compile errors if required functions from those standard shared libraries are not present in the previous version.
When you build the code as part of AOSP it will build required libraries and link them for you automatically.
P.S. To accomplish that you're better to use a Linux-based build host.
using cygwin terminal, build native part i.e. jni folder. To build using cygwin, goto jni folder using cygdrive command. Then type ndk-build. After successful completion, shared libraries i.e. .so files will be created in libs folder.
I can understand your problem, you can pull the libraries from /system/lib of device or emulator. But you need a system permission. But you can do it by installing application.
Otherwise build your source code on linux platfor. Building process is very easy, just using 2 or 3 command. First time it is needed long time to build. After that you need very short time to build, it will build only according to the timestamp of modified code.
Please have a look here
I've got a shared object, which I'll call 'libFoo.so', compiled against the NDK. I have a java project (I'll call it 'jarlib') that makes use of that shared object, by calling
System.loadLibrary("Foo");
That java project, I export as a jar, and use in an android application. If I comment out all the bits about the shared object, the jar works fine, and I'm able to interact with it perfectly.
I can use jarlib, along with the shared object from a Unity android application with the shared object in ./lib/armeabi/libFoo.so, and it loads it up all peachy.
I'm trying to use the jarlib and libFoo.so in my non-unity android app, and loadLibrary absolutely refuses to find the libFoo.so. I've tried placing it so it will be included in my apk in ./lib, as well as ./lib/armeabi, and nothing seems to make the load call see it.
I've tried including the libFoo.so in ./lib or ./lib/armeabi of the jarlib, but once I try to build/run my android app, I'm told:
The library 'jarlib.jar' contains native libraries that will not run on the device.
The following libraries were found:
- libFoo.so
with this, if it's in the ./lib (not ./lib/armeabi)
Additionally some of those libraries will interfer with the installation of the application because of their location in lib/
lib/ is reserved for NDK libraries.
I'm not sure what combination I'm missing, but I'm sure it can be done, I just can't seem to figure out how to do it!
Well! It turns out it was something so tiny, that it caused me eight hours of headaches.
I found that my libFoo.so wasn't showing up in my app.apk/lib/armeabi/libFoo.so like it did when unity built the apks. I assumed it had something to do with that, so I started looking for settings to make sure that my lib folder was copied to the apk.
As it turns out, the lib folder is not, however...
Remember how I said I tried it in (on the android application side):
./lib/libFoo.so
-and-
./lib/armeabi/libFoo.so
Turns out, what I needed to do was put it in a similar path. Oh so similar.
./libs/armeabi/libFoo.so
Yeah. libs. With a s.
In fact, when I renamed my folder 'lib' to 'libs', it changed the icon of the folder in eclipse to have the little android symbol on it, like the bin or res folders have. And sure enough, when you build the apk, the lib/armeabi folder is there (notice it's named 'lib' in the apk, and not 'libs'. This still confuses me.)
One of my co-workers (that was working on this project before me) told me that somewhere along the line, the folder used to be 'lib', but was then changed to 'libs' in a later version of the android SDK. Either way, having just picked up this project, I didn't realize that the folder should have been named 'lib', as it seemed fine to me. I was about ready to pull my hair out. I'm leaving this here in the hopes that SOMEONE has the same problem I did, and manages to solve it a bit faster.