Is Android OpenSSL build configuration armv7 safe for all arm devices? - android

I am currently in the process of updating our project OpenSSL to 1.0.1i using http://wiki.openssl.org/index.php/Android.
Looking in the config file I found that OpenSSL has 2 Android build options: android-armv7 and android-x86.
I have been able to build the armv7 configuration and it appears to be working correctly on a Nexus 5 and a Kindle Fire 1st Gen.
What I am wondering is would my current library work if it were in the armeabi directory instead of the armeabi-v7a directory? I was not able to find sufficient information as to whether it matters if the OpenSSL is built with armv7 but my project libraries are built with older arm in mind.
Note: My minimum API level is 8.

What I am wondering is would my current library work if it were in the armeabi directory instead of the armeabi-v7a directory?
I think there are a couple questions here. First, can you put libssl and libcrypto in armeabi/. That's an Android question (not an OpenSSL question). I seem to recall Brian talking about this on the NDK mailing list (but I can't find it at the moment). I believe the idea is armeabi/ is a fallback if a more specific library is not found in, for example, armeabi-v7a/.
Second is, can you run ARMv7a version of libssl and libcrypto on other platforms. I believe ARMv7a added a few hypervisor extensions over ARMv7, so you should be OK since OpenSSL does not use them. However, you might find yourself in trouble if running on an older device with ARMv6 or ARMv5.
In this case, you might want to download an older version of the Android NDK that builds for ARMv5, and then place ARMv5 version of libssl and libcrypto in armeabi/. You can find older versions of the NDK at Android NDK about a third of the way down the page.
To be more specific, Android 2.2 is API 8, and it was released around May 2010. So you might want to fetch and build with Android NDK Revision 3 from March 2010. NDK R3 only supported armeabi and targeted ARMv5TE (from the CPU-ARCH-ABIS.TXT file). The download is http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip.
OpenSSL does not follow the instructions at Standalone Toolchain for ARMv7a. Its missing the -mfloat-abi=softfp flag. You might have trouble calling a function that passes a float to the library from Java. There are not many of them, but one is RAND_add. The entropy estimate is passed as a float and after the incompatibility, your estimate will likely be 0.0f. See Hard-float and JNI on the NDK mailing list and [Bug #3080]: Android NEON and CFLAGS options.
Here's a note from the README's that you should also be aware of:
III.3. Automatic extraction of native code at install time:
-----------------------------------------------------------
When installing an application, the package manager service will scan
the .apk and look for any shared library of the form:
lib/<abi>/lib<name>.so
If one is found, then it is copied under $APPDIR/lib/lib<name>.so,
where $APPDIR corresponds to the application's specific data directory.
If you update the APK and nothing changes, then be sure to delete anything under lib\ or delte the APK first (they have a tendency to become "sticky").
Another issue you will likely encounter is building and compiling against 1.0.1. Be sure you provide a wrapper shared object with a different name. Otherwise, you will likely link against 0.9.8 at runtime, and not the 1.0.1 gear in your APK. That's because Zygote loads Android's version of OpenSSL, and that version is 0.9.8. Later, when Zygote forks to create your process, the link-loader will not map-in your version of OpenSSL because its already present from Zygote.
OpenSSL has 2 Android build options: android-armv7 and android-x86
I added android-x86 to the script in June 2014. I was able to get through the build with one patch: [Bug #3398] PATCH: fix broken compile on android-x86 with no-comp configure option. I don't have an x86 Android device, so I was not able to run the self tests on a device. Feedback is welcomed.

Related

Building Qt 5.12 LTS for Android with SSL and SQL support

With google deprecating GCC, Qt 5.12 for Android makes a transition away from it in favor of Clang. Which renders the existing building guides obsolete, as they are all GCC based.
The stock Qt build for Android is lacking some important functionality, and furthermore, the related documentation seems to be fairly outdated.
Additionally, 5.12 launches with a critical Android related bug, which pretty much mandates a custom build to incorporate the fix for the time being.
I myself haven't previously used Clang at all, and I am one of those people who really prefer to just make applications rather than to go through the often excruciatingly frustrating experience of trying to build the requisite tools.
Qt on Clang is here to stay, and 5.12 being a long term support release, I think a detailed step by step guide how to produce a working Qt build will be of benefit to a lot of people. It would definitely save me days of headaches and setbacks, and so I am willing to offer a generous bounty to the first reproducible answer, in addition to any bounties that may be required to promote the question visibility.
My personal requirements are SSL, MySQL and PostgreSQL support, although additional functionality is welcome. It would seem that a Linux based guide will be the most beneficial format, as it is also applicable to windows via MSYS.
I can't reply for all your requests, but I can say something about openssl:
Firstoff, even with Qt 5.12, if you are using the official android builds downloaded from Qt itself (via the Maintenancetool), then you still have to use the gcc toolchain and openssl 1.0.2. The Qt builds require 1.0.* and clang support has only been added to openssl since 1.1.1. Support for this version of openssl will hopefully come with Qt 5.13. See QTBUG-71391 for more details.
That beeing said, if you cross-compile Qt for Android yourself (or visit this post in the future, when Qt supports this), you can use openssl 1.1 and use clang to compile it.
The steps are documented on their github in NOTES.ANDROID. The steps are relatively straight forward and boil down to a few changes to PATH in order to build the library. A basic script, with switches for all android architectures provided by Qt, would be:
TOOLCHAIN_VERSION=4.9
HOST_ARCH=linux-x86_64
case "$ANDROID_TARGET_ARCH" in
arm64-v8a)
API_VERSION=21
ARCH_ID=android-arm64
TOOLCHAIN=aarch64-linux-android-$TOOLCHAIN_VERSION
;;
armeabi-v7a)
API_VERSION=16
ARCH_ID=android-arm
TOOLCHAIN=arm-linux-android-$TOOLCHAIN_VERSION
;;
x86)
API_VERSION=16
ARCH_ID=android-x86
TOOLCHAIN=x86-$TOOLCHAIN_VERSION
;;
*)
echo "Unsupported ANDROID_TARGET_ARCH: $ANDROID_TARGET_ARCH"
exit 1
;;
esac
export ANDROID_NDK=/path/to/ndk
export PATH=$ANDROID_NDK/toolchains/llvm/prebuilt/$HOST_ARCH/bin/:$ANDROID_NDK/toolchains/$TOOLCHAIN/prebuilt/$HOST_ARCH/bin:$PATH
./Configure $ARCH_ID shared no-ssl3 -D__ANDROID_API__=$API_VERSION
make SHLIB_VERSION_NUMBER= SHLIB_EXT=.so build_libs
In this script, ANDROID_TARGET_ARCH is simply the value of the qmake variable with the same name, so this script could be invoked by qmake. The steps that need to be done in detail are:
Prepare some variables:
TOOLCHAIN_VERSION: Simply the version of the gcc toolchain to be used (yes, this is still needed, as some tools, linke ranlib etc. are still used from there). As of NDK v18 the toolchain version is still 4.9
HOST_ARCH: The architecture of the host system. The sample sets this to linux. If you are on window/macos adjust this accordingly.
API_VERSION: The Android SDK version openssl should build for. I set the values to the version that Qt uses for builds for these plattforms, but other versions should be fine as well
ARCH_ID: The name of the android architecture as used by openssl
TOOLCHAIN: The name of the gcc toolchain to be used
Ensure the ANDROID_NDK environment variable is set to wherever you installed the NDK
Update the path to contain both, the clang/llvm toolchain and the gcc toolchain for your specific plattform. In the script, the locations of the toolchains are derived from the previous variables
Explicitly run the Configure script - and not config. Pass the target architecture and additional flags. (I for example prefer to disable ssl3 for security reasons)
Run make to build the library. The SHLIB_VERSION_NUMBER= SHLIB_EXT=.so part is needed to ensure that the binaries created do not have a version number as part of their name, as android does not support that.
And thats it!

How to get libssl.so and libcrypto.so from apk

So i am try to build openSSL into my qt android app. and to all my efforts from using precompiled binary to installing ubuntu 18 and still failing i am getting desperate.
I have read from this thread:
QT + OpenSSL + Android
that i can get them from ANY existing apk, so how do i extract it from the apk? Because i do not find it in the android ndk and sdk. if its only selected apk, what program do i use indor for me to see it.
im using Qt 5.11 on windows, but i have linux OS too if needed :) Thank you!
I've built OpenSSL for android a few months ago, with zero issues. Just follow this guide for Linux:
export ANDROID_NDK_ROOT="/home/dev/android-ndk-r12b"
SR="$ANDROID_NDK_ROOT/platforms/android-16/arch-arm"
BR="$ANDROID_NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-"
RANLIB="$BR"ranlib CC="$BR"gcc ./Configure android-armeabi --prefix=$SR/usr --sysroot=$SR
ANDROID_DEV=$SR/usr make
make install
Obviously, you will have to replace the paths with your own depending on where and what NDK version you install, and you will already have downloaded and extracted the OpenSSL source. Also, keep in mind that Qt doesn't seem to work with the latest and "greatest" android toolchains. In fact, android has already switched to llvm, but for Qt you will need to use the older gcc toolchains.
You can use this script to build libcrypto.
There are many prebuilt binaries you can get online, without having to rummage about in apk files, for example this repo has openssl libcrypto for a bunch of platforms, including android.
Don't know where you got the idea that you could get the libs from any apk file, obviously, it has to be a package from an application that incorporates those libraries for dynamic linking.
Last but not least, if you still plan on getting pre-compiled binaries, keep in mind they have to be built with a version that is compatible with your compiler. Which is why it is best to build the libs yourself, with the same toolchain you are using for your application. There is also the danger of getting "bad" libs from an unknown source, they might be outdated or tampered with.
You can open them by simply changing their extension to ".zip" :) will update if i can find apps that has these files.
PS: No all apk has libcrypto.so and libssl.so.

Which version of NDK should I use with a Titanium Android module?

According to the source and wiki, Titanium requires r9 of the Android NDK. But in the Android archives, the oldest version available is r10e (May 2015). The current version is r14b.
With r14b (and r13b) I get compilation failures from ndk-build involving a C++ type mismatch.
[ERROR] /Users/jdee/Library/Application Support/Titanium/mobilesdk/osx/6.1.0.GA/android/native/include/AndroidUtil.h:57:49: warning: format specifies type 'int' but the argument has type 'long' [-Wformat]
I can compile a module cleanly using r10e, r11c and r12b, but I'm hesitant to release something with an unsupported NDK version. It seems strange that Titanium requires a version of NDK from 2014 as well. I'm not sure which version to use.
As of today, the same wiki page speaks of NDK r12, which can be downloaded from the official archive. The drawbacks of using an older NDK are, outweighed by the risks of relying on tiny nuances of compiler compatibility. It would require exhaustive testing on a wide range of supported devices to prove that your build with NDK r16 is OK. And note that upgrading NDK requires some fixes, see https://github.com/appcelerator/titanium_mobile/pull/9926.
As long as you don't need the native APIs that are specific for Oreo and higher, you can use r12 without fear.
If your project involves other NDK components that cannot be built with NDK r12, please remember that you can mix shared libraries built separately (with different NDK versions) in one app, as long as they do not share C++ objects between them. Titanium v8 framework is safe is this sense.
One point of weakness here is the shared STL runtime libc++_shared.so. You cannot have two different versions of it in your app. Probably the safest solution for such situation is to change the Titanium Application.mk file to use
APP_STL := c++_static

Android NDK build-host-executable.mk: No such file or directory

Short question:
I'm trying to build an app that has a JNI dependency, using Eclipse ADT and NDK r10e (the current version). The JNI dependency (apparently) builds a binary to run on the build host, using build-host-executable.mk from the NDK. However, that script seems to have been removed in recent NDK versions. What do I do?
Long question:
The JNI dependency is platform/external/srec from AOSP, which comes with an Android.mk file (actually, several of them).
I have set up Eclipse to build the native parts according to the instructions here, and copied the JNI code tree into the jni directory of my app's source tree. Additionally, I had to edit jni/Android.mk, adding the following line:
export TARGET_BUILD_TYPE := debug
which, as I understand it, would be set by the AOSP toolchain but is not set when building from Eclipse.
However, I get the following error:
android-ndk-r10e/build/core/build-host-executable.mk: No such file or directory
This is caused by a line in one of my Android.mk files:
include $(BUILD_HOST_EXECUTABLE)
The NDK defines BUILD_HOST_EXECUTABLE in build/core/build-all.mk:
BUILD_HOST_EXECUTABLE := $(BUILD_SYSTEM)/build-host-executable.mk
However, build_host_executable.mk is absent from the build/core directory (and so are the other build-host-*.mk scripts declared in the surrounding lines).
Googling around a bit, I find that this script seems to have been present in earlier NDK versions (up to at least NDK r7 r7b) but seems to be absent from later versions (possibly since r10b). The JNI lib was used by the (now abandoned) Voice Dial app. It had its last commit in December 2014, though the last real code change might have been in June 2014. AOSP had stopped building it by June 2015. Comparing this with the NDK release history, it might never have been built against NDK versions later than r9d or maybe r10.
The NDK r7b I found appears to be a patched version to which host target support added, see also https://github.com/flyskywhy/android-ndk-host. Looks like support for this was planned in NDK and some stubs added, but it was never fully implemented. That gives me the choice of either building the host stuff with the local toolchain, or patching NDK r10e to add host target support.
On the other hand, this package has been part of AOSP for a while (Cyanogenmod included it until KitKat and dropped it in Lollipop), therefore the AOSP toolchain must have been capable of building it. Any pointers to that toolchain? Maybe it's possible to extract the relevant parts from the AOSP toolchain and add them to the package.
The JNI dependency in question is taken from the AOSP code tree. The toolchain used by AOSP is different from NDK, though both are built around a set of GNU make macros. The format for Android.mk (their makefile equivalent) is intentionally similar between both, so that in many cases a project can be built with either toolchain.
One case for which this will not work is host targets, i.e. building binaries (executables or libraries) intended to run on the build host rather than on the Android device. The AOSP toolchain has this kind of support but the NDK doesn't. Confusingly, the NDK does have some stubs for that functionality (including definitions for BUILD_HOST_EXECUTABLE and similar) but the implementation is missing.
There are three options. Be aware that the package you are building may depend on other packages from the AOSP source code, which you would need to build as well.
Build the native code (or the host targets) using the AOSP toolchain, as described in this answer. This approach is most likely to be successful, as this is the toolchain for which the package was designed. It requires at least the packages containing the build tools, which are several gigabytes in size. You can get the entire AOSP source code as described here, which should give you all the dependencies you need, but this will download some 50 gigabytes (!) of data.
There is a patched version of NDK which adds support for host targets here (or just the make macros here). However, it is based on the now-outdated NDK r7b and had its last commit sometime in 2012 – you'll be working with a toolchain that is somewhat exotic and no longer maintained. Also, you'll need to determine your dependencies manually by examining the package.
Ditch the Android.mk files that build the host targets and build these with a regular GNU toolchain. An introduction to that can be found here. You can amend a higher-level Android.mk to invoke the "other" toolchain for your host targets, so you can automate the whole build. All of this may be a lot of work if the Android.mk content is very complex, but it is a one-time effort, after which your code will build with standard toolchains. As with the previous approach, you'll need to determine your dependencies manually. Dependencies which are required for the host target may be easier, though, if they are standard libraries which were ported to Android, as there may be an upstream version designed to be built with the GNU toolchain.

How to target multiple architectures using NDK?

Background
I've recently started to develop some code using the NDK, and I've thought of a possible portability problem that could occur while developing using NDK.
The problem
Since NDK uses native code, it needs to be compiled per CPU architecture. This is a problem since the user needs to run the app no matter what CPU the device has.
Possible solutions I've found so far
I've noticed I can modify the file "jni/Application.mk" and use:
APP_ABI := armeabi armeabi-v7a x86
however, I don't know what I should do from this step on. Will the app contain all of the compiled code for each of the CPU architectures and automatically choose the correct one when running itself?
Also, what if there will be another CPU architecture that is unknown?
What will happen if I try to run the app on Google TV, which according to what I remember doesn't support the NDK at all?
Another solution I've found is the multi-apk support. However, I'm not sure I understand it. Does it all mean that you create the same APK, each time with a different configuration? No special automation tool from ADT to help with that?
If you don't set APP_ABI at all, or use
APP_ABI := all
in your Application.mk, then ndk-build will build for all architectures supported by your version of NDK. The latest one, to date r8d, will in addition to armeabi armeabi-v7a x86 build also for mips. When another architecture will be released, you will hopefully automatically get the APK built to support it.
When you application is installed on an Android device, the system will automatically choose the matching ABI version and install the correct shared libraries from the APK.
One drawback of this approach is that if the native libraries are big, your "monolithic" APK file may become huge. You can use the multi-APK approach to make user downloads smaller. The official site recommends: You should generally use multiple APKs to support different device configurations only when your APK is too large (greater than 50MB). You should carefully follow the version code guildlines if you choose this route.
Unfortunately, there are no trustworthy prophecies regarding NDK support on Google TV, but there seem to be no technical justification for its current unavailability. If and when it arrives, your ndk-build will take care of it automatically.
UPDATE Here is a simple process to maintain split APK. And by the way, the new Android TV does support NDK.
For the latest version (now r9) you have to specify in "jni/Application.mk"
APP_ABI := all
or
APP_ABI := armeabi armeabi-v7a x86 mips
without ./ndk_build will only build 'armeabi'

Categories

Resources