1. 程式人生 > >curl-7.39.0 for android 編譯以及jni中的使用

curl-7.39.0 for android 編譯以及jni中的使用

因為有需求需要編譯libcurl庫在android工程中使用,所以首先就需要自己編譯一個libcurl.a或者libcurl.so了,因為它用的很廣泛嘛;

另外如果一個curl庫要支援ssl,必須要在編譯的時候和ssl組合編譯,比如openssl;

瞭解了這些以後,就可以進行編譯工作了;

環境:ubuntu12.04 64

首先下載NDK,android-ndk-r10c-linux-x86_64.bin

用到的工具程式碼準備好之後就是編譯了;

1、設定編譯環境變數

export LDFLAGS="-L/data/NDK/android-ndk-r10c/platforms/android-21/arch-arm/usr/lib"
export CPPFLAGS="-I/data/NDK/android-ndk-r10c/platforms/android-21/arch-arm/usr/include"

LDFLAGS是告訴編譯器從哪裡尋找需要的庫檔案;

CPPFLAGS可選的編譯器選項,在編譯 C/C++ 程式碼檔案的時候使用。這可能是有用的,指定一個附加的包含路徑(相對於NDK的頂層目錄),巨集定義,或者編譯選項。

從NDK匯出編譯工具,然後將其新增環境變數;

 在NDK根目錄下執行:

./build/tools/make-standalone-toolchain.sh

會生成一個arm-linux-androideabi-4.6壓縮檔案,解壓到自定義的目錄下,然後將其新增進環境變數;

export PATH=$PATH:/opt/arm-linux-androideabi-4.6/bin”

2、進入到curl原始碼目錄下,執行

./configure --host=arm-linux-androideabi \
--without-ssl \
--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

最後會輸出類似如下的內容

configure: Configured to build curl/libcurl:

  curl version:     7.39.0
  Host setup:       arm-unknown-linux-androideabi
  Install prefix:   /usr/local
  Compiler:         arm-linux-androideabi-gcc
  SSL support:      no      (--with-{ssl,gnutls,nss,polarssl,cyassl,axtls,winssl,darwinssl} )
  SSH support:      no      (--with-libssh2)
  zlib support:     enabled
  GSS-API support:  no      (--with-gssapi)
  TLS-SRP support:  no      (--enable-tls-srp)
  resolver:         default (--enable-ares / --enable-threaded-resolver)
  ipv6 support:     no      (--enable-ipv6)
  IDN support:      no      (--with-{libidn,winidn})
  Build libcurl:    Shared=yes, 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:   no
  ca cert path:     no
  LDAP support:     no      (--enable-ldap / --with-ldap-lib / --with-lber-lib)
  LDAPS support:    no      (--enable-ldaps)
  RTSP support:     no      (--enable-rtsp)
  RTMP support:     no      (--with-librtmp)
  metalink support: no      (--with-libmetalink)
  HTTP2 support:    disabled (--with-nghttp2)
  Protocols:        HTTP

  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.

在這裡要注意:Compiler:         arm-linux-androideabi-gcc,如果是系統預設gcc,則需要指定使用ndk中的arm-gcc:

SYSROOT=$ANDROIDNDK/platforms/android-21/arch-arm
export CC="/opt/arm-linux-androideabi-4.6/bin/arm-linux-androideabi-gcc-4.6 --sysroot=$SYSROOT"

再執行

make

就會生成libcurl的庫檔案了,在lib/.libs下;

這個時候curl的庫是不支援進行https請求的;通過下面一句程式碼可以檢視你的庫是否支援https;

curl_easy_setopt(easy_handle, CURLOPT_USE_SSL, CURLUSESSL_ALL);
如要檢視curl的版本資訊,程式碼如下;
curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
LOGE("data version= %s, ssl_version = %s", data->version, data->ssl_version);

那接下來就需要看如何編譯支援https請求的curl庫檔案了;

首先進入到剛剛下載的openssl-android工程目錄下,執行

ndk-build

命令即可,會生成libssl.so和libcrypto.so兩個庫檔案;

再把兩個檔案放入到android-ndk-r10c\platforms\android-21\arch-arm\usr\lib目錄下;這裡的android-21對應上面指定的LDFLAGS;

然後把openssl-android/include/openssl目錄拷貝到android-ndk-r10c/platforms/android-21/arch-arm/usr/include目錄;

這個時候執行

./configure --host=arm-linux-androideabi \
--with-ssl \
--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

注意和上一次執行時不同的地方,就是--with-ssl;

執行完成以後,還需要修改curl_config.h檔案的一些巨集定義;

 開啟:HAVE_LIBSSL(#define HAVE_LIBSSL 1)、HAVE_OPENSSL_CRYPTO_H、HAVE_OPENSSL_ERR_H、HAVE_OPENSSL_PEM_H、HAVE_OPENSSL_PKCS12_H、HAVE_OPENSSL_RSA_H、HAVE_OPENSSL_SSL_H、HAVE_OPENSSL_X509_H、USE_OPENSSL、USE_SSLEAY

android沒有編譯openssl中的 engine,關掉HAVE_OPENSSL_ENGINE_H

註釋掉巨集定義HAVE_MALLOC_H和HAVE_IOCTL

註釋掉巨集 HAVE_GETPWUID_R 、HAVE_GETEUID、HAVE_GETPWUID,否則編譯的時候會出現類似: error: undefined reference to 'getpwuid_r'之類的錯誤;

這個時候再執行

make
OK,帶有https請求功能的libcurl出爐了;

再接下來,編譯完成以後就是使用了,如何在android 工程中應用呢?

jni的makefile檔案大體如下寫也就可以了;需要將libcurl.a、libcrypto.so、libssl.so、libz.so拷貝到jni目錄下;標頭檔案拷貝到openssl下;

libz.so位置在,android NDK自帶支援;

android-ndk-r10c/platforms/android-21/arch-arm/usr/lib
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

#crypto
include $(CLEAR_VARS)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := ./openssl/libcrypto.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/openssl/
include $(PREBUILT_SHARED_LIBRARY)


#openssl
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := ./openssl/libssl.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/openssl/
include $(PREBUILT_SHARED_LIBRARY)

#libz
include $(CLEAR_VARS)
LOCAL_MODULE := libz
LOCAL_SRC_FILES := ./openssl/libz.so
#LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/openssl/
include $(PREBUILT_SHARED_LIBRARY)


#libcurl
include $(CLEAR_VARS)
LOCAL_MODULE := curl
LOCAL_SRC_FILES := ./curllib/libcurl.a
include $(PREBUILT_STATIC_LIBRARY)

#ourLib
include $(CLEAR_VARS)
LOCAL_CFLAGS := -D_GNU_SOURCE
LOCAL_CPPFLAGS := -frtti
LOCAL_MODULE:= jni_curl
LOCAL_STATIC_LIBRARIES := libcurl
LOCAL_SHARED_LIBRARIES := crypto ssl libz
LOCAL_SRC_FILES := jni_main.cpp
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

至此,完成,OK;

64位環境設定:

export LDFLAGS="-L/data/NDK/android-ndk-r10c/platforms/android-21/arch-arm64/usr/lib"
export CPPFLAGS="-I/data/NDK/android-ndk-r10c/platforms/android-21/arch-arm64/usr/include" 
SYSROOT=$ANDROIDNDK/platforms/android-21/arch-arm64
export CC="/data/NDK/android-ndk-r10c/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-gcc --sysroot=$SYSROOT"