Cygwin+NDK编译curl源码库
1、curl相关链接
下载:http://curl.haxx.se/download/curl-7.37.1.tar.gz
2、openssl相关链接
下载:http://download.youkuaiyun.com/detail/lsq19871207/7730949
3、编译参考的地址:
http://blog.youkuaiyun.com/choujs/archive/2010/02/10/5304978.aspx
http://blog.youkuaiyun.com/liushilei/archive/2010/04/15/5488107.aspx
http://curl.haxx.se/mail/lib-2009-12/0071.html
http://blog.youkuaiyun.com/someonea/article/details/6312213
4、编译
4.1 、编译环境搭建
本文建立在Cgywin+NDK编译环境已搭建好的基础之上(我的是 Cygwin +android-ndk32-r10),安装目录如下:
D:/NDK
android-ndk-r10
cygwin64
4.2 编译openssl
4.2.1 建立OpenSSL工程目录
在NDK安装目录下建立如下目录:D:\NDK\android-ndk-r10\apps\OpenSSL,把从http://download.youkuaiyun.com/detail/lsq19871207/7730949下载的OpenSSL1.0.1cForAndroid.zip解压到上述目录路径下,目录结构如下图所示:
4.2.2编译openssl静态库
openssl默认编译成动态库.so文件,如果想编译成静态库.o文件,需要修改相应的Android.mk文件:
(1)OpenSSL/crypto/Android.mk:
a、把“target” 和“host shared library”的编译选项统统注释掉,只留下“host static library”编译选项,并把include $(BUILD_SHARED_LIBRARY) 修改为 include$(BUILD_STATIC_LIBRARY)
b、另外还需要连接libz,加上下面的一句
LOCAL_LDLIBS += -lz
c、Android.mk文件大致如下:
LOCAL_PATH:=$(call my-dir)
arm_cflags :=-DOPENSSL_BN_ASM_MONT -DAES_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM
arm_src_files := \
aes/asm/aes-armv4.S \
bn/asm/armv4-mont.S \
sha/asm/sha1-armv4-large.S \
sha/asm/sha256-armv4.S \
sha/asm/sha512-armv4.S
non_arm_src_files := aes/aes_core.c
local_src_files := \
cryptlib.c\
mem.c\
mem_clr.c\
mem_dbg.c\
………\
………\
………\
local_c_includes := \
$(NDK_PROJECT_PATH) \
$(NDK_PROJECT_PATH)/crypto/asn1 \
$(NDK_PROJECT_PATH)/crypto/evp \
$(NDK_PROJECT_PATH)/include \
$(NDK_PROJECT_PATH)/include/openssl \
$(NDK_PROJECT_PATH)/../include
local_c_flags := -DNO_WINDOWS_BRAINDEATH
include$(CLEAR_VARS)
include$(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES += $(local_src_files)
LOCAL_CFLAGS += $(local_c_flags)-DPURIFY
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_SRC_FILES += $(non_arm_src_files)
LOCAL_LDLIBS += -lz
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:=libcrypto
include $(BUILD_STATIC_LIBRARY)
(2)OpenSSL/ssl/Android.mk:
a、把所有的include$(BUILD_SHARED_LIBRARY) 修改为 include$(BUILD_STATIC_LIBRARY)。
b、ssl需要crypto的支持,因此需要引用libcrypto库
LOCAL_STATIC_LIBRARIES+= libcrypto
c、ssltest还需要连接libz,并且需要crypto和ssl库的支持,因此加上下面的两句
LOCAL_STATIC_LIBRARIES = libcryptolibssl
LOCAL_LDLIBS += -lz
d、Android.mk文件大致如下:
LOCAL_PATH:=$(call my-dir)
local_c_includes := \
$(NDK_PROJECT_PATH) \
$(NDK_PROJECT_PATH)/include \
$(NDK_PROJECT_PATH)/crypto \
$(NDK_PROJECT_PATH)/../include
local_src_files:= \
s2_meth.c\
s2_srvr.c\
s2_clnt.c\
………\
………\
………\
include$(CLEAR_VARS)
include$(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES += $(local_src_files)
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_STATIC_LIBRARIES += libcrypto
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:=libssl
include$(BUILD_STATIC_LIBRARY)
ifeq($(WITH_HOST_DALVIK),true)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES +=$(local_src_files)
LOCAL_C_INCLUDES +=$(local_c_includes)
LOCAL_STATIC_LIBRARIES += libcrypto
LOCAL_MODULE_TAGS :=optional
LOCAL_MODULE:=libssl
include $(BUILD_STATIC_LIBRARY)
endif
# ssltest
include$(CLEAR_VARS)
include$(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES:= ssltest.c
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_STATIC_LIBRARIES = libssl libcrypto
LOCAL_LDLIBS += -lz
LOCAL_MODULE:=ssltest
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
(3)OpenSSL/app/Android.mk:
a、openssl需要连接libz,并且需要crypto和ssl库的支持,因此加上下面几句:
LOCAL_STATIC_LIBRARIES = \
Libcrypto\
libssl
LOCAL_LDLIBS += -lz
b、Android.mk文件大致如下:
LOCAL_PATH:=$(call my-dir)
include$(CLEAR_VARS)
LOCAL_SRC_FILES:= \
app_rand.c\
apps.c\
asn1pars.c\
ca.c\
ciphers.c\
………\
………\
………\
LOCAL_STATIC_LIBRARIES := \
libssl\
libcrypto
LOCAL_C_INCLUDES := \
$(NDK_PROJECT_PATH) \
$(NDK_PROJECT_PATH)/include \
$(NDK_PROJECT_PATH)/../include
LOCAL_CFLAGS := -DMONOLITH
include$(LOCAL_PATH)/../android-config.mk
LOCAL_CFLAGS += -DOPENSSL_NO_DTLS1
LOCAL_MODULE:=openssl
LOCAL_MODULE_TAGS := tests
LOCAL_LDLIBS += -lz
include $(BUILD_EXECUTABLE)
(4)OpenSSL/jni/Application.mk:
默认只生成armeabi版本的静态库,如果需要生成armeabi-v7a或者x86版本的静态库,需要手动修改OpenSSL/jni/Application.mk文件:
APP_ABI :=armeabi armeabi-v7a x86
APP_PROJECT_PATH := $(shell pwd)
APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/Android.mk
注意:android-config.mk文件预定义了一些宏,万不可注释掉,否则编译的过程中会出现由于宏开关问题造成的函数找不到错误!
4.2.3执行编译
启动cygwin,命令行输入 “cd /cygdrive/d/ndk/android-ndk-r10/apps/OpenSSL”即可进入到刚刚建立的工程目录,执行“ndk-build”命令,即可编译。备注:cd /cygdrive表示进入当前Cygwin安装的磁盘,这时候执行ls命令,仅显示Cygwin安装路径的盘符;例如我的安装路径在d盘下,所以“cd/cygdrive/d”就直接进入到d盘了;
4.3 编译curl
4.3.1 建立工程目录
在NDK安装目录下建立如下目录:D:\NDK\android-ndk-r10\apps\curl\jni,把下载的curl-7.37.1.tar.gz解压到D:\NDK\android-ndk-r10\apps\curl\jni目录下,目录结构如下图所示:
注意:一定要新建jni目录,并把curl源码文件放到jni目录下,否则编译的时候会出现Android NDK: Could not find application project directory !错误,原因就是在于Application.mk文件必须放在jni文件夹下
4.3.2 生成curl_config.h文件
1、要创建一个头文件curl_config.h。创建方法在jni/packages/Android/Android.mk文件头部的注释里有说明。启动Cygwin,命令行输入 “cd /cygdrive/d/ndk/android-ndk-r10/apps/curl/jni/”即可进入到刚刚建立的工程目录。
2、进入cd /cygdrive/d/ndk/android-ndk-r10/apps/curl/jni/后,执行”./configure“命令,经过漫长的checking后即可在jni/lib目录下生成curl_config.h文件
4.3.3、修改curl_config.h文件
(1) configure找不到openssl,所以所生成的配置文件是不使用openssl的,关于openssl相关的宏默认都是关闭状态,因此我们需要打开相关openssl的宏:
打开: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
(2) 注释掉宏定义HAVE_MALLOC_H和HAVE_IOCTL
(3) 注释掉宏 HAVE_GETPWUID_R 、HAVE_GETEUID、HAVE_GETPWUID,否则编译的时候会出现类似:/lib/netrc.c:84: error: undefined reference to 'getpwuid_r'之类的错误
(4) 64位和32位宏控制:把SIZEOF_LONG 、SIZEOF_OFF_T、SIZEOF_SIZE_T、SIZEOF_TIME_T、SIZEOF_VOIDP做如下修改,否则会出现类似”cur/curlrules.h:134: error: size ofarray __curl_rule_01__ is negative“之类的编译错误
/* The size of `long', as computed by sizeof. */ #ifdef __arch64__ #define SIZEOF_LONG 8 #else #define SIZEOF_LONG 4 #endif /* The size of `off_t', as computed by sizeof. */ #ifdef __arch64__ #define SIZEOF_OFF_T 8 #else #define SIZEOF_OFF_T 4 #endif /* The size of `size_t', as computed by sizeof. */ #ifdef __arch64__ #define SIZEOF_SIZE_T 8 #else #define SIZEOF_SIZE_T 4 #endif /* The size of `time_t', as computed by sizeof. */ #ifdef __arch64__ #define SIZEOF_TIME_T 8 #else #define SIZEOF_TIME_T 4 #endif /* The size of `void*', as computed by sizeof. */ #ifdef __arch64__ #define SIZEOF_VOIDP 8 #else #define SIZEOF_VOIDP 4 #endif
4.3.4、建立openssl头文件目录以及库文件目录
(1)openssl头文件
把openssl源码库中的crypto和openssl目录文件夹拷贝到d/ndk/android-ndk-r10/apps/curl/jni/include目录下(curl头文件目录)
(2)openssl库文件
在d/ndk/android-ndk-r10/apps/curl/jni/目录下新建_library/static_a文件夹,并把编译好的openssl的三种版本的库文件拷贝到其中,如下图所示:
4.3.5、建立Aandroid.mk和Application.mk文件
1、在d/ndk/android-ndk-r10/apps/curl/jni/目录下新建Application.mk文件:
APP_ABI := armeabi armeabi-v7a x86 //依自己情况而定
APP_STL := stlport_static
APP_CPPFLAGS := -fexceptions -frtti
APP_CPPFLAGS+=-std=c++11
2、把d/ndk/android-ndk-r10/apps/curl/jni/ packages/Android/Android.mk文件拷贝到d/ndk/android-ndk-r10/apps/curl/jni/目录下,并做如下修改:
(1)“LOCAL_PATH := $(call my-dir)/../..”改成 “LOCAL_PATH := $(call my-dir)”
(2)添加对libcrypto.a和libssl.a不同版本库的引用
完整的Android.mk文件大致如下:
LOCAL_PATH :=$(call my-dir)
########################libArm################################
include$(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include/crypto
LOCAL_MODULE := libcryptoArm
LOCAL_SRC_FILES := _library/static_a/armeabi-v7a/libcrypto.a
include$(PREBUILT_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include/openssl
LOCAL_MODULE := libsslArm
LOCAL_SRC_FILES = _library/static_a/armeabi-v7a/libssl.a
include$(PREBUILT_STATIC_LIBRARY)
########################libArm#################################
########################libx86#################################
include$(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include/crypto
LOCAL_MODULE := libcryptox86
LOCAL_SRC_FILES := _library/static_a/x86/libcrypto.a
include$(PREBUILT_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include/openssl
LOCAL_MODULE := libsslx86
LOCAL_SRC_FILES = _library/static_a/x86/libssl.a
include$(PREBUILT_STATIC_LIBRARY)
############################libx86###############################
common_CFLAGS := -Wpointer-arith -Wwrite-strings -Wunused -Winline\
-Wnested-externs -Wmissing-declarations-Wmissing-prototypes\
-Wno-long-long -Wfloat-equal -Wno-multichar-Wsign-compare\
-Wno-format-nonliteral -Wendif-labels-Wstrict-prototypes\
-Wdeclaration-after-statement-Wno-system-headers -DHAVE_CONFIG_H\
##################################################
# Build the libcurl library
include$(CLEAR_VARS)
include$(LOCAL_PATH)/lib/Makefile.inc
CURL_HEADERS := \
curlbuild.h\
curl.h\
curlrules.h\
curlver.h\
easy.h\
mprintf.h\
multi.h\
stdcheaders.h\
typecheck-gcc.h\
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_SRC_FILES := $(addprefix $(LOCAL_PATH)/lib/,$(CSOURCES))
LOCAL_STATIC_LIBRARIES := libcryptoArm libsslArm libcryptox86 libsslx86
LOCAL_CFLAGS += $(common_CFLAGS)
LOCAL_COPY_HEADERS_TO := libcurl/curl
LOCAL_COPY_HEADERS := $(addprefix include/curl/,$(CURL_HEADERS))
LOCAL_MODULE:=libcurl
LOCAL_MODULE_TAGS := optional
include $(BUILD_STATIC_LIBRARY)
4.3.6执行编译
启动cygwin,命令行输入 “cd /cygdrive/d/ndk/android-ndk-r10/apps/url/jni”即可进入到刚刚建立的工程目录,执行“ndk-build”命令,即可编译
5、curl的应用
需要应用curl库函数的话,仅仅需要把curl库的“Include”文件夹和自己刚刚编译好的libcurl.a、libssl.a、libcrypto.a文件拷贝到自己的工程相应目录下,并在工程的Aandroid.mk文件中添加引用即可。例如:
LOCAL_PATH :=$(call my-dir)
########################libArm################################
include$(CLEAR_VARS)
LOCAL_MODULE := libcryptoArm
LOCAL_SRC_FILES := _library/armeabi-v7a/libcrypto.a
include$(PREBUILT_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_MODULE := libsslArm
LOCAL_SRC_FILES = _library/armeabi-v7a/libssl.a
LOCAL_STATIC_LIBRARIES := libcryptoArm
include$(PREBUILT_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/curl
LOCAL_MODULE := libcurlArm
LOCAL_SRC_FILES := _library/armeabi-v7a/libcurl.a
LOCAL_STATIC_LIBRARIES := libcryptoArm libsslArm
include$(PREBUILT_STATIC_LIBRARY)
##############################################################
########################libx86################################
include$(CLEAR_VARS)
LOCAL_MODULE := libcryptox86
LOCAL_SRC_FILES := _library/x86/libcrypto.a
include$(PREBUILT_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_MODULE := libsslx86
LOCAL_SRC_FILES = _library/x86/libssl.a
LOCAL_STATIC_LIBRARIES := libcryptox86
include$(PREBUILT_STATIC_LIBRARY)
include$(CLEAR_VARS)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/curl/Include
LOCAL_MODULE := libcurlx86
LOCAL_SRC_FILES := _library/x86/libcurl.a
LOCAL_STATIC_LIBRARIES := libcryptox86 libsslx86
include$(PREBUILT_STATIC_LIBRARY)
##############################################################
include$(CLEAR_VARS)
MY_SRCS :=…………
LOCAL_SRC_FILES := $(addprefix Source/,$(MY_SRCS))
LOCAL_C_INCLUDES = $(LOCAL_PATH)/Include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/curl/Include
LOCAL_MODULE := xxxxxx
LOCAL_SRC_FILES += xxxx.cpp
LOCAL_STATIC_LIBRARIES := libcurlArm libcurlx86
LOCAL_LDLIBS += -lz
LOCAL_LDLIBS += -llog
include$(BUILD_SHARED_LIBRARY)