Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 :

  1. Download Android Source code (and compile it! since some of the intermediate libs are needed)

  2. Download cURL

  3. unpack curl under : {android_src}/external/curl

  4. 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
like image 322
Tancho Avatar asked Jul 04 '12 13:07

Tancho


2 Answers

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,

  1. 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 :)

like image 154
Tancho Avatar answered Dec 08 '22 19:12

Tancho


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.

like image 26
Victor Laskin Avatar answered Dec 08 '22 17:12

Victor Laskin