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
Related
I'm primarily a C developer who has been tasked with building some C libraries into shared object files that can be built into an Android app. I came across this link which discusses how to add a prebuilt library to an Android Studio project, but very little information on how to actually build a prebuilt library. I did find information saying I can't just use Linux cross-compilers to do so due to slight differences in ABI. How would I go about doing this? Do I need to use Android Studio? Do my sources need to include some special header? Or can I just use the cross compilers found in the NDK and compile using gcc -shared -fPIC?
It's enough to build your library with an NDK toolchain. Usually it's OK to use the lowest platform API level supported by NDK. You should produce the binaries for different CPUs. You may skip the 32-bit variants if you wish, but the rules of Android Play Store require that you have a 64-bit version. You don't need Android Studio for this task, and no changes to your sources are necessary.
If your library exports C++ API, use c++_shared runtime.
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.
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.
Android-NDK ships its own compiler to build the native code. The version shipped with my current android-NDK installation is arm-linux-androideabi-g++ (GCC) 4.6.x-google 20120106 (prerelease), I guess it's a fork of GCC 4.6.
What are the differences between it and a regular (vanilla) GCC 4.6? Is it producing better code for ARM platforms?
I'd like to use other compilers to build software for android, like vanilla GCC 4.7 or Clang, since they have a better support of C++11 and implement some features I'm struggling to use (like template aliases).
Is it possible to use the latest vanilla GCC or Clang, to build the native code for Android? What parameters should I use?
What are the cons of using a compiler different from the one shipped with android-SDK?
Android GCC is customized for the android as all the features in the GCC are not supported by the native Android. I dont think there is a possibility, you can post the same in the android ndk google groups where your answers will be replied by the Google Android Developers.
They were suggesting that we can make use of the cross compilers for compiling the android code with out using the android ndk.
Just a heads-up: google added clang3.1 in Revision 8c of the Android NDK. It's in "experimental" stage now, but easy to try out (and probably will be better supported in the near future, hopefully with a proper port of libc++, too).
the Android ndk is hard to use for the old autoconf based code, so i employed scratchbox2/emdebian to have a complete build environment. can i build a shared library in emdebian (arch is armel) and then use it in android?
The official NDK comes with a version of GCC that works with Google's custom Bionic libc. If you are using a version of GCC that is intended to work with the GNU libc then you must statically link it in (as is done by the Crystax NDK). So even if your compiler generates the correct instructions, it may be worthwhile to rework your build environment to avoid bloating your application unnecessarily.
armel is Arm Eabi. Android is ARMv5 eABI. They will probably be compatible.