How to configure gcc to compile for android? - android

I've read in the gcc documentation that it supports building android binaries with the -mandroid and -mbionic switches. First I tried it with the native gcc built from svn. Result:
dancsi#dancsi-VirtualBox:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc/i686-pc-linux-gnu/4.7.0/lto-wrapper
Target: i686-pc-linux-gnu
Configured with: ../source/configure --enable-threads --disable-nls
Thread model: posix
gcc version 4.7.0 20110611 (experimental) (GCC)
dancsi#dancsi-VirtualBox:~$ g++ test.cpp -mandroid -o test.out
dancsi#dancsi-VirtualBox:~$ file test.out
test.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
Basically, it failed. Next, I tried to compile the same gcc sources with target=arm-linux-androideabi, (without defining sysroot,...), and it passed the configuration, but failed to build saying pthread.h is not found:
In file included from ../.././gcc/gthr-default.h:1:0,
from ../../../combined/libgcc/../gcc/gthr.h:160,
from ../../../combined/libgcc/../gcc/unwind-dw2.c:37:
../../../combined/libgcc/../gcc/gthr-posix.h:41:21: fatal error: pthread.h: No such file or directory
compilation terminated.
So, does anybody have the instructions for how to use gcc to build android binaries (I don't want to use code sourcery or android-ndk)?
EDIT:
my configure options
configure --target=arm-linux-android --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-libssp --disable-libgomp --disable-nls --enable-languages=c,c++,java

I had exactly the same problem as described by dancsi while trying to compile my own cross compilation tool chains for Android (I wanted to build a 32 bit variant of them so I don't need to buy a 64 bit PC or do my android stuff in a VM).
I am using the tool chain sources from the official AOSP tool chain repo:
repo init -u https://android.googlesource.com/toolchain/manifest
The solution is to use the following 2 extra configure options: --with-headers and --with-libs. I've got this solution by reading the following file: [android-toolchain-repo]/build/README:
The other way is to specify the headers and libraries with --with-headers and
--with-libs separately. If you configure your tree with a prefix. The headers
and libraries will be copied to the install directory specified by the prefix.
For the values of those 2 extra parameters I used [android-src-repo]/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/lib and [android-src-repo]/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/include. [android-src-repo] is referring to my repo checkout of the base AOSP sources (in my case I am on the android-4.2.2_r1 branch of it).
The end-result of the two configure statements I need are the following:
./configure --target=arm-eabi --host=i686-linux-gnu --build=i686-linux-gnu --disable-gold \
--with-gcc-version=4.6 --with-binutils-version=2.21 --with-gmp-version=4.2.4 --with-mpfr-version=2.4.1 \
--with-gdb-version=7.3.x --with-gold-version=2.21 --prefix=/tmp/toolchain --disable-multilib \
--with-libs=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/lib \
--with-headers=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/include \
--program-transform-name='s&^&arm-eabi-&' --with-arch=armv5te --disable-option-checking
./configure --target=arm-linux-androideabi --host=i686-linux-gnu --build=i686-linux-gnu --enable-gold \
--with-gcc-version=4.6 --with-binutils-version=2.21 --with-gmp-version=4.2.4 --with-mpfr-version=2.4.1 \
--with-gdb-version=7.3.x --with-gold-version=2.21 --prefix=/tmp/toolchain \
--with-libs=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/lib \
--with-headers=/home/boeboe/android-src/prebuilts/ndk/8/platforms/android-14/arch-arm/usr/include \
--program-transform-name='s&^&arm-linux-androideabi-&' --disable-option-checking
Notice the extra --disable-option-checking argument which was necessary for configure to accept all arguments!
This long list of arguments was constructed by checking the original configure arguments passed for the default 64 bit version of the 4.6 gcc toolchain. This can be checked in the SOURCES files available in [android-src-repo]/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6 and [android-src-repo]/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6.
In the same files, git tags can be found, so I also checkout those specific version in my [android-toolchain-repo]. For the extra modules needed by gcc, like gmp/mpfr/gdb..., I extracted the correct versions of the tar-balls available in [android-toolchain-repo]/gmp|mpfr|gdb. This was the easiest way I could find out, for my original configure statement to be able to pick up those modules.
The same technique as described above also allowed me to compile a 32 bit variant of the latest gcc 4.7 tool chain (currently being used on the MAIN branch of AOSP). The configure options were of course different in this case.

In file included from ../.././gcc/gthr-default.h:1:0,
from /mnt/network/source/gcc/libgcc/../gcc/gthr.h:160,
from /mnt/network/source/gcc/libgcc/../gcc/unwind-dw2.c:37:
/mnt/network/source/gcc/libgcc/../gcc/gthr-posix.h:41:21: fatal error: pthread.h: No such file or directory
compilation terminated.
make[2]: *** [unwind-dw2.o] Error 1
make[1]: *** [all-target-libgcc] Error 2
make: *** [all] Error 2
I'm getting the same error as you, but I'm not compiling for Android. I'm trying to build w64-mingw32 compiler.
AR=x86_64-w64-mingw32-ar RANLIB=x86_64-w64-mingw32-ranlib
../gcc-4.5.1/configure --prefix=/tools \
--with-local-prefix=/tools --enable-clocale=gnu \
--enable-shared --enable-threads=posix \
--enable-__cxa_atexit --enable-languages=c,c++ \
--disable-libstdcxx-pch --disable-multilib \
--disable-bootstrap --disable-libgomp \
--without-ppl --without-cloog --build=$MACHTYPE --host=$MACHTYPE --target=x86_64-w64-mingw32
My response is so you know its not just Android, the trouble is more general then just building for the ARM architecture.
I think its a c++ issue, cause I had/have no trouble with building a c compiler alone.

Related

How to change Install Dir when Building OpenCV 3.1.0 on Ubuntu 18.04 for Android NDK18rc and ARMEABI-7?

I am trying for over one week to compile OpenCV 3.1.0 for Android with NDK r18 on Ubuntu 18.04.
I have used the following command:
cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DANDROID_NDK="/home/qamaruddin/Downloads/android-ndk-r18-linux-x86_64/android-ndk-r18/" \
-DCMAKE_TOOLCHAIN_FILE="/home/qamaruddin/Downloads/android-ndk-r18-linux-x86_64/android-ndk-r18/build/cmake/android.toolchain.cmake" \
-DANDROID_NATIVE_API_LEVEL=19 \
-DANDROID_ABI="armeabi-v7a" \
-DWITH_CUDA=OFF \
-DWITH_MATLAB=OFF \
-DBUILD_ANDROID_EXAMPLES=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_TESTS=OFF \
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
-DCMAKE_C_COMPILER=/usr/bin/clang \
-DOPENCV_EXTRA_MODULES_PATH="/opt/opencv_contrib/modules/" \
-DCMAKE_INSTALL_PREFIX:PATH="/home/mig-ocv/ocv-android-310/" \
-DEXECUTABLE_OUTPUT_PATH:PATH="/home/mig-ocv/ocv-android-310/" \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH="/home/mig-ocv/ocv-android-310/" \
-DCMAKE_BUILD_TYPE=Release \
/opt/opencv
Follwed by make & make install/strip.
I have tried different versions of OpenCV 3 such as 3.1.0, 3.4.3, and 3.4.0. I have also tried NDKr15c, NDKr17c, and NDKr18c.
I have tried the following variations:
Change NDK version
Change OpenCV 3 version
Install using python script located at opencv/platforms/androind/setup.py
Build using CMAKE
Use Ninja for CMAKE, but this gives the error: "ninja: error: loading 'build/build.global.ninja': No such file or directory"
Install without Ninja with CMAKE
At the moment, using the above-posted command for CMAKE builds successfully, but I can't change the target install dir since it always builds into /usr/local/ and when I inspect the target directory it does not have the familiar OpenCV for Android structure which is:
1- etc
2- java
3- native --> jni --> include
I wonder what is wrong in my process that makes it so difficult to build OpenCV 3 from source for Android with OpenCV Contrib.
Note that $ANDROID_HOME is set to the android SDKs directory on my system and $ANDROID_NDK is also set.
I have seen all duplicate questions on StackOverflow and other forums, but none seems to work in my case.
When I try to build with Ninja with this command:
cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DANDROID_NDK="$HOME/Downloads/android-ndk-r17b/" \
-DCMAKE_TOOLCHAIN_FILE="$HOME/Downloads/android-ndk-r17b/build/cmake/android.toolchain.cmake" \
-DANDROID_NATIVE_API_LEVEL=21 \
-DANDROID_ABI="armeabi-v7a" \
-DWITH_CUDA=OFF \
-DWITH_MATLAB=OFF \
-DBUILD_ANDROID_EXAMPLES=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_TESTS=OFF \
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
-DCMAKE_C_COMPILER=/usr/bin/clang \
-DOPENCV_EXTRA_MODULES_PATH="$HOME/ocv/opencv_contrib/modules/" \
-DCMAKE_INSTALL_PREFIX:PATH="$HOME/agusta/ocv-android-310/" \
-DEXECUTABLE_OUTPUT_PATH:PATH="$HOME/agusta/ocv-android-310/" \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH="$HOME/agusta/ocv-android-310/" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_MAKE_PROGRAM=/usr/bin/ninja \
$HOME/ocv/opencv
I get:
CMake Deprecation Warning at CMakeLists.txt:72 (cmake_policy):
The OLD behavior for policy CMP0022 will be removed from a future version
of CMake.
The cmake-policies(7) manual explains that the OLD behaviors of all
policies are deprecated and that a policy should be set to OLD only under
specific short-term circumstances. Projects should be ported to the NEW
behavior and not rely on setting a policy to OLD.
CMake Deprecation Warning at CMakeLists.txt:77 (cmake_policy):
The OLD behavior for policy CMP0026 will be removed from a future version
of CMake.
The cmake-policies(7) manual explains that the OLD behaviors of all
policies are deprecated and that a policy should be set to OLD only under
specific short-term circumstances. Projects should be ported to the NEW
behavior and not rely on setting a policy to OLD.
CMake Deprecation Warning at CMakeLists.txt:82 (cmake_policy):
The OLD behavior for policy CMP0042 will be removed from a future version
of CMake.
The cmake-policies(7) manual explains that the OLD behaviors of all
policies are deprecated and that a policy should be set to OLD only under
specific short-term circumstances. Projects should be ported to the NEW
behavior and not rely on setting a policy to OLD.
-- Check for working CXX compiler: /home/qamaruddin/Downloads/android-ndk-r17b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++
CMake Error: Generator: execution of make failed. Make command was: "/usr/bin/ninja" "cmTC_c4cee/fast"
-- Check for working CXX compiler: /home/qamaruddin/Downloads/android-ndk-r17b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ -- broken
CMake Error at /usr/local/share/cmake-3.12/Modules/CMakeTestCXXCompiler.cmake:45 (message):
The C++ compiler
"/home/qamaruddin/Downloads/android-ndk-r17b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++"
is not able to compile a simple test program.
It fails with the following output:
Change Dir: /home/qamaruddin/agusta/temp/CMakeFiles/CMakeTmp
Run Build Command:"/usr/bin/ninja" "cmTC_c4cee/fast"
No such file or directory
Generator: execution of make failed. Make command was: "/usr/bin/ninja" "cmTC_c4cee/fast"
CMake will not be able to correctly generate this project.
Call Stack (most recent call first):
CMakeLists.txt:93 (project)
-- Configuring incomplete, errors occurred!
See also "/home/qamaruddin/agusta/temp/CMakeFiles/CMakeOutput.log".
See also "/home/qamaruddin/agusta/temp/CMakeFiles/CMakeError.log".
You have changed variables that require your cache to be deleted.
Configure will be re-run and you may have to reset some variables.
The following variables have changed:
CMAKE_CXX_COMPILER= /usr/bin/clang++
CMAKE_C_COMPILER= /usr/bin/clang
-- Generating done
CMake Warning:
Manually-specified variables were not used by the project:
BUILD_ANDROID_EXAMPLES
BUILD_DOCS
BUILD_PERF_TESTS
BUILD_TESTS
EXECUTABLE_OUTPUT_PATH
OPENCV_EXTRA_MODULES_PATH
WITH_CUDA
WITH_MATLAB
-- Build files have been written to: /home/qamaruddin/agusta/temp
I have managed to get it to work, basically, OCV didn't support NDKr18, and I also had to install ninja from source. I have also used python3 instead of python2 to run the opencv/platforms/android/build_sdk.py . One more thing is that I use Eclipse Android ADT which Google has for no reason deprecated ;(, but I find it super fast compared to the heavy Android Studio.
# export ANDROID_ABI=armeabi-v7a
# export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.8
# export ANDROID_NDK=$HOME/Downloads/android-ndk-r17c-linux-x86_64/android-ndk-r17c/
# export ANDROID_SDK=$HOME/android-sdks/
./../opencv/platforms/android/build_sdk.py --extra_modules_path=/opt/opencv_contrib/modules --config ../opencv/platforms/android/ndk-17.config.py

Invalid character linking FFmpeg 3.4.2 built with NDK r16

I'm in the process of updating my applications FFmpeg version from 2.8.6 to 3.4.2. I've managed to get FFmpeg built, but when I build my native library I'm getting a linker error:
/usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libswresample.so:1:1: invalid character
/usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libavcodec.so:1:1: invalid character
/usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libavfilter.so:1:1: invalid character
/usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libavutil.so:1:1: invalid character
The libraries are correct, but I don't understand where the :1:1: is coming from (assuming the trailing : is probably a delineator between the command and the error message). The path to the library is correct, but the filename definitely does not have a :1:1 in it.
I'm building on a Mac, so the first thing I do is:
sed -i ".orig" "s/SHFLAGS='-shared -Wl,-soname,\$(SLIBNAME)'/SHFLAGS='-shared -Wl,-install_name,\$(SLIBNAME)'/g" configure
so that ld uses the -install_name flag, rather than -soname. I used to have to do some other configure manipulation to strip the library naming out, but that doesn't seem to be necessary anymore (even if I do it I still get the same error).
FFmpeg was built using the following options:
./configure --prefix=output --enable-shared --disable-everything
--disable-iconv --disable-zlib --disable-bzlib
--enable-encoder=aac --enable-decoder=aac --enable-encoder=pcm_alaw
--enable-decoder=pcm_alaw --enable-encoder=pcm_mulaw
--enable-decoder=pcm_mulaw --enable-encoder=adpcm_g726
--enable-decoder=adpcm_g726 --enable-encoder=adpcm_ima_wav
--enable-decoder=adpcm_ima_wav --enable-encoder=mjpeg
--enable-decoder=mjpeg --enable-encoder=wmav1
--enable-decoder=wmav1 --enable-encoder=wmav2
--enable-decoder=wmav2 --enable-encoder=wmv1 --enable-decoder=wmv1
--enable-encoder=wmv2 --enable-decoder=wmv2
--enable-encoder=h264_vaapi --enable-encoder=hevc_vaapi
--enable-encoder=h264_nvenc --enable-encoder=hevc_nvenc
--enable-encoder=h264_omx --enable-encoder=h264_qsv
--enable-encoder=hevc_qsv --enable-decoder=aac_fixed
--enable-decoder=aac_latm --enable-decoder=adpcm_g726le
--enable-decoder=h263 --enable-decoder=h264 --enable-decoder=hevc
--enable-decoder=mjpegb --enable-decoder=mpeg4
--enable-decoder=h264_qsv --enable-decoder=h264_vdpau
--enable-decoder=hevc_qsv --enable-decoder=hevc_qsv
--enable-filter=scale --enable-filter=scale_vaapi
--enable-filter=scale_cuda --enable-filter=scale_npp
--enable-filter=scale_qsv --enable-parser=aac --enable-parser=h263
--enable-parser=h264 --enable-parser=hevc --enable-parser=mjpeg
--enable-muxer=asf --enable-demuxer=asf --enable-muxer=avi
--enable-demuxer=avi --enable-muxer=h263 --enable-demuxer=h263
--enable-muxer=h264 --enable-demuxer=h264 --enable-muxer=hevc
--enable-demuxer=hevc --enable-muxer=mjpeg --enable-demuxer=mjpeg
--enable-muxer=pcm_alaw --enable-demuxer=pcm_alaw
--enable-muxer=pcm_mulaw --enable-demuxer=pcm_mulaw --enable-muxer=wav
--enable-demuxer=wav --enable-demuxer=aac --enable-hwaccel=h264_d3d11va
--enable-hwaccel=hevc_d3d11va --enable-hwaccel=h264_d3d11va2
--enable-hwaccel=hevc_d3d11va2 --enable-hwaccel=h264_dxva2
--enable-hwaccel=hevc_dxva2 --enable-hwaccel=h264_vaapi
--enable-hwaccel=hevc_vaapi --enable-hwaccel=h264_vdpau
--enable-hwaccel=hevc_vdpau --enable-hwaccel=h264_nvenc
--enable-hwaccel=hevc_nvenc --enable-hwaccel=h264_qsv
--enable-hwaccel=hevc_qsv --enable-hwaccel=h264_vdpau
--enable-hwaccel=hevc_vdpau --disable-programs --enable-cross-compile
--cross-prefix=/shared/dev/toolchain/android/darwin-x86_64/ndk-r16/android-19/arm/bin/arm-linux-androideabi-
--arch=arm --target-os=android --disable-asm --disable-stripping
--disable-static --cc=clang --enable-pic
NDK toolchain is a standalone x86 toolchain built using NDK r16's make_standalone_toolchain.py tool.
The native project is built using CMake and using the clang android toolchain.
I've also got an arm version that gives the same linker error.
I'm not sure where exactly to start looking. Did this come from the build config options? I had to do quite a bit of tweaking to get it to build using NDK r16, but it was mostly stuff like adding --disable-stripping and changing --target-os from linux to android. Is it something with the NDK r16 toolchain?
Does anyone have any idea what the problem might be, or where I might start looking?
Ok, I figured this out.
It turns out that passing --cc=clang will configure the makefiles to use the system clang, not the clang available in the provided --cross-prefix. This was resulting in a binary built for the Darwin-x86_64 architecture, and NOT the Android x86 or Android ARM architectures.
Fix was to pass the complete path to the clang compiler with the --cc configure option.
I've made my build script available on GitHub for anyone else having trouble building FFmpeg for Android using NDK r16b:
android-ffmpeg-buildscript

Compiling gentoo-bionic on a x86_64 linux machine

As you may know, Bionic is a C library used by Google to run Android applications. There are efforts to compile it in Linux machines, so it could be easily used outside Android. This is the code from one the latest efforts, originally called Gentoo-bionic. The original project was Gentoo-based, but the current source is not Gentoo-specific. I am using Ubuntu. Here's the code:
https://github.com/gentoobionic/bionic
And this is the presentation about it on ELC2013:
http://elinux.org/images/2/25/2013_elc_gentoo_bionic.pdf
http://free-electrons.com/blog/elc-2013-videos/ (bad sound)
I tried to compile it on X86_64 Ubuntu, but failed. I tried:
./autogen.sh
./configure
I got:
configure: error: unsupported host cpu x86_64
So I tried:
./configure --build=arm-linux --target=arm-linux --host=arm-linux
It configured fine, but I got:
$ make
make: *** No rule to make target `libc/arch-x86/include/machine/cpu-features.h',
needed by `all-am'. Stop.
Is there a chance that someone can suggest a workaround?
I dont know anything about bionic. I just want to help you.
when i viewed configure file, i saw this code.
Makefile.h.am:Line 135
if TARGET_ARCH_IS_X86
includemachine_HEADERS += \
$(addprefix $(top_srcdir)/libc/arch-x86/include/, \
machine/fpu_control.h \
machine/sigcontext.h \
machine/wordsize.h \
)
endif
if TARGET_ARCH_IS_ARM
includemachine_HEADERS += \
$(addprefix $(top_srcdir)/libc/arch-x86/include/, \
machine/cpu-features.h \
)
endif
configure.ac: Line 94
case $host_cpu in
*i?86*)
TARGET_ARCH=x86
COMMON_LDFLAGS="${COMMON_LDFLAGS} ${COMMON_LDFLAGS_X86}"
COMMON_CFLAGS="${COMMON_CFLAGS} ${COMMON_CFLAGS_X86}"
COMMON_INCLUDES="${COMMON_INCLUDES} ${COMMON_INCLUDES_X86}"
COMMON_LDLIBS="${COMMON_LDLIBS} ${COMMON_LDLIBS_X86}"
;;
*arm*)
TARGET_ARCH=arm
COMMON_LDFLAGS="${COMMON_LDFLAGS} ${COMMON_LDFLAGS_ARM}"
COMMON_CFLAGS="${COMMON_CFLAGS} ${COMMON_CFLAGS_ARM}"
COMMON_INCLUDES="${COMMON_INCLUDES} ${COMMON_INCLUDES_ARM}"
COMMON_LDLIBS="${COMMON_LDLIBS} ${COMMON_LDLIBS_ARM}"
;;
*)
AC_MSG_ERROR([unsupported host cpu $host_cpu])
;;
esac
There is no cpu-features.h file on include/machine folder. So, you have to use different target.
Since Nov 2015 my set of ebuid scripts compile bionic for x86_64 and i386 on my Gentoo x86_64 desktop. Tools required: glibc-targeting GCC version 4.9.3 or 5.3.0; binutils 2.4.25 or older, glibc-targeting clang 3.5.0, make.
If you can install those tools on your desktop, you can potentially compile bionic.
Note however that my ebuilds apply zillion of patches.
To see what they do, you can the following:
Boot live Gentoo DVD on a x86_64 desktop or notebook.
Install my scripts.
Run them capturing output, for instance
USE=verbose ebuild bionic/bionic-5.1.1-r29.ebuild clean install qmerge 2>&1 | tee /tmp/bionic.cout
Once such command terminates, you get the patched source tree, intermediate and final compilation result, and full build log with gcc/clang/ld/ar command-lines.

Building OpenSSL for Android (ARMv7) on Win32

How can I build OpenSSL for Android ARM v7 (using Android NDK) on Win32?
Until the OpenSSL's wiki and setenv-android.sh are updated accordingly, I'll publish the recipe here. The required fixes to the process are:
Update setenv-android.sh to support Windows.
Update PATH to use Android NDK's (mingw) GNU make (rather than Cygwin's).
Invoke make with a Windows-style path to Cygwin's perl.
This recipe will be a strange hybrid of Cygwin and mingw (since Android NDK gcc toolchains for win32 are mingw). I'm assuming a Windows x86_64 build of the Android NDK unpacked into c:\android-ndk-r9d, and that you wish to use a gcc 4.8 toolchain.
Install Android NDK (duh!).
Install Cygwin -- make sure to include perl
Start Cygwin shell as an administrator to make sure native symlinks will work.
Within the console, run the following script to set the variables:
export \
CYGWIN=winsymlinks:native \
ANDROID_API=android-14 \
ANDROID_DEV=c:/android-ndk-r9d/platforms/android-14/arch-arm/usr \
PATH=/cygdrive/c/android-ndk-r9d/prebuilt/windows-x86_64/bin:/cygdrive/c/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/bin:$PATH \
MACHINE=armv7 \
SYSTEM=android \
ARCH=arm \
CROSS_COMPILE=arm-linux-androideabi-
Now, unpack openssl:
tar xzfv openssl-1.0.1i.tar.gz (or whatever your tarball is)
cd openssl-1.0.1i (or whatever your version is)
Make sure you have actual native Win32 (!) symlinks in include/openssl:
cmd /c "dir include\openssl"
You should see something like:
13-Aug-14 05:59 PM <SYMLINK> aes.h [..\..\crypto\aes\aes.h]
13-Aug-14 05:59 PM <SYMLINK> asn1.h [..\..\crypto\asn1\asn1.h]
(etc.)
Now it's time to configure:
./config shared -no-ssl2 -no-ssl3 -no-comp -no-hw -no-engine --openssldir=/foo/bar
Ignore the failure to build (due to failure to find perl). We'll rectify this right away. Do this:
make PERL=$(cygpath -w $(which perl))
Now wait for a few minutes until it builds, and presto, you have your libcrypto.so etc.
Just a couple of comments on my experience with this:
Executing this statement:
PERL=$(cygpath -w $(which perl))
in the cygwin shell allows the shell to interpret the backslashes as escape characters and the build process chokes. To solve this I did the following:
$ echo $(cygpath -w $(which perl))
which produced the windows formatted path to the perl executable:
C:\cygwin64\bin\perl
Then I added this line to the export shown above:
PERL=c:/cygwin64/bin/perl \
There are other ways of doing this, but it worked and headed off the problem with the ./config statement documented above (not finding perl).
Second issue was the -no- statements. After running the configure, the script reports that you'll have to run make depend. I wanted to exclude MD5 (i.e. -no-md5) and when I did the make depend, it errored out with a report that MD5 was disabled. Uhhh, yes, that was kind of the idea, but I just won't use MD5 hashes. I did use the -no-ssl2 and didn't get any complaints after the make depend.
Third issue and this is a mystery. The build broke on compiling crypto because it could not find a symbol that is supposed to be defined in /crypto/objects/obj_xref.h. When I looked at the file, it was empty. Something in the perl script I suppose, but no time to debug right now, since I'm at proof of concept phase. I placed a copy from a patch that I picked up at https://github.com/devpack/openssl-android
After that, my build ran to completion. I've done no testing with this and it is not a trustworthy solution, but it did compile and produce the static libraries that I need for proof of concept for my client.
Just as an update, my shared library built with these libraries loaded fine on my target.

porting libcurl on android with ssl support

I am trying to port libCurl to android with SSL support,
step one would be to port the curl without ssl support I guess so I started doing that. but I run into a problem.
as I read on the dev website and in the Android.mk file, the hard part is configuring the make first. so what I did is :
Download Android Source code (and compile it! since some of the intermediate libs are needed)
Download cURL
unpack curl under : {android_src}/external/curl
make the configure script for curl by creating a sh file in the external/curl folder with this content.
`
export A=/home/user/Development/AOSP/2.3.3
export CC=$A/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc
export NDK=/home/user/Development/Tools/sdk/android/ndk
export NDKLIBS=$NDK/platforms/android-4/arch-arm/usr/include
export SYSROOT=$A/ndk/build/platforms/android-4/arch-arm
export CPPFLAGS="-I $A/system/core/include"
export LDFLAGS="-L$A/out/target/product/generic/obj/lib/ -L$A/out/target/product/generic/system/lib/-L$SYSROOT/usr/lib -Wl,--gc-sections -nostdlib -lc -lm -ldl -llog -lgcc -Wl,--no-undefined,-z,nocopyreloc -Wl,-dynamic-linker,/system/bin/linker -L$NDK/out/target/product/generic/obj/lib/"
export CFLAGS="-fno-exceptions -Wno-multichar -mthumb -mthumb-interwork -nostdlib -lc -ldl -lm -march=armv5te -mtune=xscale -msoft-float -mandroid -fPIC -mthumb-interwork -mthumb -mlong-calls -ffunction-sections -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DOS_ANDROID -D__NEW__ -D__SGI_STL_INTERNAL_PAIR_H -I$SYSROOT/usr/include -I $A/system/core/include -I $NDKLIBS"
./configure --host=arm-eabi --with-ssl=$A/external/openssl
`
And the output summary is this one :
configure: Configured to build curl/libcurl:
curl version: 7.26.0
Host setup: arm-unknown-eabi
Install prefix: /usr/local
Compiler: /home/tanco/Development/AOSP/2.3.3/prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gcc
SSL support: no (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls} )
SSH support: no (--with-libssh2)
zlib support: enabled
krb4 support: no (--with-krb4*)
GSSAPI support: no (--with-gssapi)
SPNEGO support: no (--with-spnego)
TLS-SRP support: no (--enable-tls-srp)
resolver: default (--enable-ares / --enable-threaded-resolver)
ipv6 support: no (--enable-ipv6)
IDN support: no (--with-libidn)
Build libcurl: Shared=no, Static=yes
Built-in manual: enabled
--libcurl option: enabled (--disable-libcurl-option)
Verbose errors: enabled (--disable-verbose)
SSPI support: no (--enable-sspi)
ca cert bundle: /etc/ssl/certs/ca-certificates.crt
ca cert path: no
LDAP support: no (--enable-ldap / --with-ldap-lib / --with-lber-lib)
LDAPS support: no (--enable-ldaps)
RTSP support: enabled
RTMP support: no (--with-librtmp)
Protocols: DICT FILE FTP GOPHER HTTP IMAP POP3 RTSP SMTP TELNET TFTP
SONAME bump: yes - WARNING: this library will be built with the SONAME
number bumped due to (a detected) ABI breakage.
See lib/README.curl_off_t for details on this.
First strange thing that comes to mind is why is SSL not included in the config since the linker shows to the intermediate libs and ssl support flag is called, but after when I use the same curl_config.h file in the jni project which I created for the build (since it has a standalone Android.mk file it can be compiled simply by unzipping in the jni folder of a android project, copying the config file created in the AOSP source and calling ndk-build)
so I compile and I get :
$ ndk-build
Compile thumb : curl <= url.c
In file included from /Projects/temp/testNDK/jni/lib/url.c:32:0:
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h: In function 'getpagesize':
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h:171:3: warning: nested extern declaration of '__page_size' [-Wnested-externs]
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h: In function '__getpageshift':
/Tools/sdk/android/ndk/platforms/android-14/arch-arm/usr/include/unistd.h:175:3: warning: nested extern declaration of '__page_shift' [-Wnested-externs]
/Projects/temp/testNDK/jni/lib/url.c: At top level:
/Projects/temp/testNDK/jni/lib/url.c:57:2: error: #error "We can't compile without socket() support!"
make: *** [/Projects/temp/testNDK/obj/local/armeabi/objs/curl/lib/url.o] Error 1
Here is the solution, updated to NDK8c
step zero: download and fix the Android NDK
I don't know how but the ndk has a very interesting flaw, which (in my oppinion) doesn't allow you to compile lot's of stuff, so to be able to compile OpenSSL you need to make a small fix, extract the ndk8c whereever you keep your tools, and then edit the file :
android-ndk-r8c/build/gmsl/__gmsl
line 512 :
change line
int_encode = $(__gmsl_tr1)$(wordlist 1,$1,$(__gmsl_input_int))
with line
int_encode = $(__gmsl_tr1)$(wordlist 1,$(words $1),$(__gmsl_input_int))
And you're good to go!
step one : Download OpenSSL and compile for Android :
either compile a ported version found here
or Download the official 1.0.0c version of OpenSSL and then compile it for android using the manual provided in the github I linked for the Android compatible version
So the next step is to get the libssl.so and libcrypto.so
and put the them in the NDK folder for easy access, so copy them from
openssl-folder/libs/armeabi/
to
android-ndk-r8c/platforms/android-8/arch-arm/usr/lib
this way when compiling you can include the libs using a simple linker switch -lssl -lcrypto
Step two : get Curl's latest source for here
Open the file in Docs/INSTALL and follow the steps needed to make the standalone toolchain and put in your desired folder, and then the tricky part, I needed to have android's source code for the config to continue, even though I have a standalone compiled openssl you can include the header files from there too, in anycase this is the more complicated version so you choose what you do, I did not choose to evade them so you can go to Google AOSP site and go trough the steps to build and initialize the environment.
so it would be something like :
1.download,
go to root of the source code and run :
~: build/envsetup.sh; lunch 1; make;
So finally we need to compile curl with SSL support, so,
Step three
extract curl to the desired folder
(I have a specific desire of disabling everything except http/s to keep the library as small as possible meaning about ~300k, if you want more protocols in your lib, remove the --disable-protocol for the desired protocol)
run the following :
make clean
export PATH=/opt/arm-linux-androideabi-4.4.3/bin:$PATH
export LDFLAGS="\
-lssl \
-lcrypto \
-L/home/user/Development/Tools/sdk/android/ndk/platforms/android-8/arch-arm/usr/lib"
export CFLAGS="\
-I/home/user/Development/AOSP/2.3.7/system/core/include \
-I/home/user/Development/Tools/sdk/android/ndk/platforms/android-8/arch-arm/usr/include"
./configure --host=arm-linux-androideabi \
--with-ssl=/home/user/Development/Projects/portingLibs/openssl-android-master \
--disable-ftp \
--disable-gopher \
--disable-file \
--disable-imap \
--disable-ldap \
--disable-ldaps \
--disable-pop3 \
--disable-proxy \
--disable-rtsp \
--disable-smtp \
--disable-telnet \
--disable-tftp \
--without-gnutls \
--without-libidn \
--without-librtmp \
--disable-dict
make
Note that in the block above, if you don't want to use the AOSP source, you could switch
-I/home/user/Development/AOSP/2.3.7/system/core/include \
with the include folder for your ssl distribution.
So finally you have :
static :
curl-7.28.1/lib/.libs/libcurl.a
and shared :
curl-7.28.1/lib/.libs/libcurl.so.5.3
So that's it.. take the file, and compile away :)
I like the way to use Docker for building such static libs. There is full script here - you just run it and grab the result. Sample: https://gist.github.com/VictorLaskin/1c45245d4cdeab033956
Such script will:
setup compilation tools / utils download sdk/ndk
create custom cross-compilation toolchain download source code for libs (zlib, openssl, curl)
setup environment settings for cross compilation
configure and make libs
gather output at one folder and create the way to get
compiled libs
This specific version is using latest NDK 10e and clang toolchain.
There is post with more details here: http://vitiy.info/dockerfile-example-to-compile-libcurl-for-android-inside-docker-container/
I hope this will help someone to not waste precious time.
Steps for compiling libcurl.so with ssl support for android jni could be found here :
http://ieroot.com/2015/03/29/1728.html
I struggled for a week for figuring out it.
Ask if any questions. I'll reply as soon as possible.

Categories

Resources