ubuntu移植libcurl到Android平臺

最近移植了很多C++平臺的庫,很多都是后臺開發(fā)的庫橙喘,因為NDK開發(fā)时鸵,以后很可能會使用,提前預研一下厅瞎。
libcurl這個庫很有名饰潜,用的人比較多,下載源碼和簸,直接就可以編譯使用彭雾,以前在Windows平臺下開發(fā)網絡模塊的時候,用到過這個庫锁保,很強大
最近在跟后臺的人聊天過程中了解了很多C++開發(fā)的相關庫薯酝,這是其中一個半沽,Android中網絡操作的庫有很多種,從基本的Httpurlconnection到httpclient吴菠,volley者填,okhttp等等,很多選擇做葵,使用起來也非常方便占哟,當然了,如果在jni層下使用網絡庫酿矢,libcurl是個很不錯的選擇榨乎,所以筆者決定記錄一下移植的過程,之前有移植的經驗瘫筐,這個也比較簡單蜜暑。

新建腳本build_curl.sh

#!/usr/bin/env bash

# ====================================================================
# Sets the cross compile environment for Android
# Based upon OpenSSL's setenv-android.sh (by TH, JW, and SM).
#
# Crypto++ Library is copyrighted as a compilation and (as of version 5.6.2)
# licensed under the Boost Software License 1.0, while the individual files
# in the compilation are all public domain.
#
# See http://www.cryptopp.com/wiki/Android_(Command_Line) for more details
# ====================================================================

unset IS_CROSS_COMPILE

unset IS_IOS
unset IS_ANDROID
unset IS_ARM_EMBEDDED

unset AOSP_FLAGS
unset AOSP_SYSROOT
unset AOSP_STL_INC
unset AOSP_STL_LIB
unset AOSP_BITS_INC

# Set AOSP_TOOLCHAIN_SUFFIX to your preference of tools and STL library.
#   Note: 4.9 is required for the latest architectures, like ARM64/AARCH64.
# AOSP_TOOLCHAIN_SUFFIX=4.8
# AOSP_TOOLCHAIN_SUFFIX=4.9
if [ -z "$AOSP_TOOLCHAIN_SUFFIX" ]; then
    AOSP_TOOLCHAIN_SUFFIX=4.9
fi

# Set AOSP_API to the API you want to use. 'armeabi' and 'armeabi-v7a' need
#   API 3 (or above), 'mips' and 'x86' need API 9 (or above), etc.
# AOSP_API="android-3"     # Android 1.5 and above
# AOSP_API="android-4"     # Android 1.6 and above
# AOSP_API="android-5"     # Android 2.0 and above
# AOSP_API="android-8"     # Android 2.2 and above
# AOSP_API="android-9"     # Android 2.3 and above
# AOSP_API="android-14"    # Android 4.0 and above
# AOSP_API="android-18"    # Android 4.3 and above
# AOSP_API="android-19"    # Android 4.4 and above
# AOSP_API="android-21"    # Android 5.0 and above
# AOSP_API="android-23"    # Android 6.0 and above
if [ -z "$AOSP_API" ]; then
    AOSP_API="android-21"
fi

#####################################################################

# ANDROID_NDK_ROOT should always be set by the user (even when not running this script)
#   http://groups.google.com/group/android-ndk/browse_thread/thread/a998e139aca71d77.
# If the user did not specify the NDK location, try and pick it up. We expect something
#   like ANDROID_NDK_ROOT=/opt/android-ndk-r10e or ANDROID_NDK_ROOT=/usr/local/android-ndk-r10e.

export ANDROID_NDK_ROOT=/workspace/android-ndk-r10e

if [ -z "$ANDROID_NDK_ROOT" ]; then
    ANDROID_NDK_ROOT=$(find /opt -maxdepth 1 -type d -name android-ndk-r10* 2>/dev/null | tail -1)

    if [ -z "$ANDROID_NDK_ROOT" ]; then
        ANDROID_NDK_ROOT=$(find /usr/local -maxdepth 1 -type d -name android-ndk-r10* 2>/dev/null | tail -1)
    fi
    if [ -z "$ANDROID_NDK_ROOT" ]; then
        ANDROID_NDK_ROOT=$(find $HOME -maxdepth 1 -type d -name android-ndk-r10* 2>/dev/null | tail -1)
    fi
fi

# Error checking
if [ ! -d "$ANDROID_NDK_ROOT/toolchains" ]; then
    echo "ERROR: ANDROID_NDK_ROOT is not a valid path. Please set it."
    [ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1
fi

#####################################################################

if [ "$#" -lt 1 ]; then
    THE_ARCH=armv7
else
    THE_ARCH=$(tr [A-Z] [a-z] <<< "$1")
fi

# https://developer.android.com/ndk/guides/abis.html
case "$THE_ARCH" in
  arm|armv5|armv6|armv7|armeabi)
    TOOLCHAIN_BASE="arm-linux-androideabi"
    TOOLNAME_BASE="arm-linux-androideabi"
    AOSP_ABI="armeabi"
    AOSP_ARCH="arch-arm"
    AOSP_FLAGS="-march=armv5te -mtune=xscale -mthumb -msoft-float -funwind-tables -fexceptions -frtti"
    ;;
  armv7a|armeabi-v7a)
    TOOLCHAIN_BASE="arm-linux-androideabi"
    TOOLNAME_BASE="arm-linux-androideabi"
    AOSP_ABI="armeabi-v7a"
    AOSP_ARCH="arch-arm"
    AOSP_FLAGS="-march=armv7-a -mthumb -mfpu=vfpv3-d16 -mfloat-abi=softfp -Wl,--fix-cortex-a8 -funwind-tables -fexceptions -frtti"
    ;;
  hard|armv7a-hard|armeabi-v7a-hard)
    TOOLCHAIN_BASE="arm-linux-androideabi"
    TOOLNAME_BASE="arm-linux-androideabi"
    AOSP_ABI="armeabi-v7a"
    AOSP_ARCH="arch-arm"
    AOSP_FLAGS="-mhard-float -D_NDK_MATH_NO_SOFTFP=1 -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -Wl,--fix-cortex-a8 -funwind-tables -fexceptions -frtti -Wl,--no-warn-mismatch -Wl,-lm_hard"
    ;;
  neon|armv7a-neon)
    TOOLCHAIN_BASE="arm-linux-androideabi"
    TOOLNAME_BASE="arm-linux-androideabi"
    AOSP_ABI="armeabi-v7a"
    AOSP_ARCH="arch-arm"
    AOSP_FLAGS="-march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -Wl,--fix-cortex-a8 -funwind-tables -fexceptions -frtti"
    ;;
  armv8|armv8a|aarch64|arm64|arm64-v8a)
    TOOLCHAIN_BASE="aarch64-linux-android"
    TOOLNAME_BASE="aarch64-linux-android"
    AOSP_ABI="arm64-v8a"
    AOSP_ARCH="arch-arm64"
    AOSP_FLAGS="-funwind-tables -fexceptions -frtti"
    ;;
  mips|mipsel)
    TOOLCHAIN_BASE="mipsel-linux-android"
    TOOLNAME_BASE="mipsel-linux-android"
    AOSP_ABI="mips"
    AOSP_ARCH="arch-mips"
    AOSP_FLAGS="-funwind-tables -fexceptions -frtti"
    ;;
  mips64|mipsel64|mips64el)
    TOOLCHAIN_BASE="mips64el-linux-android"
    TOOLNAME_BASE="mips64el-linux-android"
    AOSP_ABI="mips64"
    AOSP_ARCH="arch-mips64"
    AOSP_FLAGS="-funwind-tables -fexceptions -frtti"
    ;;
  x86)
    TOOLCHAIN_BASE="x86"
    TOOLNAME_BASE="i686-linux-android"
    AOSP_ABI="x86"
    AOSP_ARCH="arch-x86"
    AOSP_FLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -funwind-tables -fexceptions -frtti"
    ;;
  x86_64|x64)
    TOOLCHAIN_BASE="x86_64"
    TOOLNAME_BASE="x86_64-linux-android"
    AOSP_ABI="x86_64"
    AOSP_ARCH="arch-x86_64"
    AOSP_FLAGS="-march=x86-64 -msse4.2 -mpopcnt -mtune=intel -funwind-tables -fexceptions -frtti"
    ;;
  *)
    echo "ERROR: Unknown architecture $1"
    [ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1
    ;;
esac


# Based on ANDROID_NDK_ROOT, try and pick up the path for the tools. We expect something
# like /opt/android-ndk-r10e/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86_64/bin
# Once we locate the tools, we add it to the PATH.
AOSP_TOOLCHAIN_PATH=""
for host in "linux-x86_64" "darwin-x86_64" "linux-x86" "darwin-x86"
do
    if [ -d "$ANDROID_NDK_ROOT/toolchains/$TOOLCHAIN_BASE-$AOSP_TOOLCHAIN_SUFFIX/prebuilt/$host/bin" ]; then
        AOSP_TOOLCHAIN_PATH="$ANDROID_NDK_ROOT/toolchains/$TOOLCHAIN_BASE-$AOSP_TOOLCHAIN_SUFFIX/prebuilt/$host/bin"
        break
    fi
done


#####################################################################

# Error checking
if [ ! -d "$ANDROID_NDK_ROOT/platforms/$AOSP_API" ]; then
    echo "ERROR: AOSP_API is not valid. Does the NDK support the API? Please edit this script."
    [ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1
elif [ ! -d "$ANDROID_NDK_ROOT/platforms/$AOSP_API/$AOSP_ARCH" ]; then
    echo "ERROR: AOSP_ARCH is not valid. Does the NDK support the architecture? Please edit this script."
    [ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1
fi

# Android SYSROOT. It will be used on the command line with --sysroot
#   http://android.googlesource.com/platform/ndk/+/ics-mr0/docs/STANDALONE-TOOLCHAIN.html
export AOSP_SYSROOT="$ANDROID_NDK_ROOT/platforms/$AOSP_API/$AOSP_ARCH"

# TODO: export for the previous GNUmakefile-cross. These can go away eventually.
export ANDROID_SYSROOT=$AOSP_SYSROOT


#####################################################################


export CPP="$AOSP_TOOLCHAIN_PATH/$TOOLNAME_BASE-cpp --sysroot=$AOSP_SYSROOT"
export CC="$AOSP_TOOLCHAIN_PATH/$TOOLNAME_BASE-gcc --sysroot=$AOSP_SYSROOT"
export CXX="$AOSP_TOOLCHAIN_PATH/$TOOLNAME_BASE-g++ --sysroot=$AOSP_SYSROOT"
export CFLAGS="-pie -fPIE"
export LDFLAGS="-pie -fPIE"
#####################################################################

export PREFIX=/usr/local/curl/$AOSP_ABI
export CC="$AOSP_TOOLCHAIN_PATH/$TOOLNAME_BASE-gcc --sysroot=$AOSP_SYSROOT"


VERBOSE=1
if [ ! -z "$VERBOSE" ] && [ "$VERBOSE" != "0" ]; then
  echo "ANDROID_NDK_ROOT: $ANDROID_NDK_ROOT"
  echo "AOSP_TOOLCHAIN_PATH: $AOSP_TOOLCHAIN_PATH"
  echo "AOSP_ABI: $AOSP_ABI"  
  echo "AOSP_API: $AOSP_API"
  echo "CC: $CC"
  echo "AOSP_SYSROOT: $AOSP_SYSROOT"
fi


./configure \
    --prefix=$PREFIX \
    --enable-static \
    --enable-shared \
    --host=$TOOLNAME_BASE

[ "$0" = "$BASH_SOURCE" ] && exit 0 || return 0

注意:

腳本中的
export ANDROID_NDK_ROOT=
需要改成你本機的環(huán)境

build_all.sh

#!/bin/bash

for arch in armeabi armeabi-v7a armeabi-v7a-hard arm64-v8a mips mips64 x86 x86_64
do
    bash build_curl.sh $arch
    make
    sudo make install
done

目錄結構

|—curl源碼目錄
  |—build_curl.sh
  |—build_all.sh
  |—...

執(zhí)行腳本

sh build_all.sh

編譯成功之后
在/usr/local/curl目錄里

測試一下

新建JNI目錄,將剛才生成的armeabi目錄里的include文件夾和lib文件夾復制進去
新建Android.mk文件

LOCAL_PATH := $(call my-dir)

#libcurl庫
include $(CLEAR_VARS)
LOCAL_MODULE := libcurl
LOCAL_SRC_FILES := lib/libcurl.a 
include $(PREBUILT_STATIC_LIBRARY) 


#測試程序
include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := main.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_STATIC_LIBRARIES := libcurl

LOCAL_CFLAGS += -pie -fPIE
LOCAL_LDFLAGS += -pie -fPIE

include $(BUILD_EXECUTABLE)

新建Application.mk添加對C++的支持

APP_ABI := armeabi
APP_PLATFORM := 12
APP_CPPFLAGS += -fexceptions -frtti
APP_STL := stlport_static

新建源文件

#include <curl/curl.h>
#include <iostream>

using namespace std;

int main(int argc,char * argv[])
{
    //定義CURL類型的指針
    CURL * curl;
    //定義CURLcode類型的變量严肪,保存返回狀態(tài)碼
    CURLcode res;

    //初始化一個CURL類型的指針
    curl = curl_easy_init();
    if(curl!=NULL)
    {

        curl_easy_setopt(curl, CURLOPT_URL, argv[1]);        
        //curl_easy_setopt(curl, CURLOPT_WRITEDATA, recv);

        res = curl_easy_perform(curl);
        if(res != CURLE_OK){
             cout << curl_easy_strerror(res) << endl;
    }

        //清除curl操作.
        curl_easy_cleanup(curl);
    }

    return 0;
}

目錄結構



編譯生成

ndk-build

最后push到手機上執(zhí)行

注意:
如果是生成Linux下的靜態(tài)庫史煎,最好把不必要的選項禁用掉,不然鏈接可能會出錯驳糯。

./configure --prefix=/usr/local/curl --disable-shared --enable-static --without-libidn --without-ssl --without-librtmp --without-gnutls --without-nss --without-libssh2 --without-zlib --without-winidn --disable-rtsp --disable-ldap --disable-ldaps --disable-ipv6

庫地址:
https://github.com/byhook/libcurl-android

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市氢橙,隨后出現的幾起案子酝枢,更是在濱河造成了極大的恐慌,老刑警劉巖悍手,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帘睦,死亡現場離奇詭異,居然都是意外死亡坦康,警方通過查閱死者的電腦和手機竣付,發(fā)現死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滞欠,“玉大人古胆,你說我怎么就攤上這事∩歌担” “怎么了逸绎?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長夭谤。 經常有香客問我棺牧,道長,這世上最難降的妖魔是什么朗儒? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任颊乘,我火速辦了婚禮参淹,結果婚禮上,老公的妹妹穿的比我還像新娘乏悄。我一直安慰自己浙值,他們只是感情好,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布纲爸。 她就那樣靜靜地躺著亥鸠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪识啦。 梳的紋絲不亂的頭發(fā)上负蚊,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音颓哮,去河邊找鬼家妆。 笑死,一個胖子當著我的面吹牛冕茅,可吹牛的內容都是我干的伤极。 我是一名探鬼主播,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼姨伤,長吁一口氣:“原來是場噩夢啊……” “哼哨坪!你這毒婦竟也來了?” 一聲冷哼從身側響起乍楚,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤当编,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后徒溪,有當地人在樹林里發(fā)現了一具尸體忿偷,經...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年臊泌,在試婚紗的時候發(fā)現自己被綠了鲤桥。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡渠概,死狀恐怖茶凳,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情高氮,我是刑警寧澤慧妄,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站剪芍,受9級特大地震影響塞淹,放射性物質發(fā)生泄漏。R本人自食惡果不足惜罪裹,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一饱普、第九天 我趴在偏房一處隱蔽的房頂上張望运挫。 院中可真熱鬧,春花似錦套耕、人聲如沸谁帕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匈挖。三九已至,卻和暖如春康愤,著一層夾襖步出監(jiān)牢的瞬間儡循,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工征冷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留择膝,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓检激,卻偏偏與公主長得像肴捉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子叔收,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,262評論 25 707
  • Android游戲開發(fā)實踐(1)之NDK與JNI開發(fā)02 承接上篇Android游戲開發(fā)實踐(1)之NDK與JNI...
    AlphaGL閱讀 3,755評論 0 24
  • 一齿穗、NDK產生的背景 Android平臺從誕生起,就已經支持C饺律、C++開發(fā)缤灵。眾所周知,Android的SDK基于J...
    Ten_Minutes閱讀 3,509評論 1 27
  • 前言 網上關于 Android 集成 FFmpeg 的文章很多蓝晒,但大多數都只介紹了步驟,沒有說明背后的原理帖鸦,若之前...
    王英豪閱讀 5,922評論 18 71
  • 我是喜歡熬夜的歡子芝薇,在忙碌的一天之后站在夜色里看著這個城市,聽著它的聲音作儿,我習慣了失眠洛二,并享受著這種無眠之夜的樂趣...
    向行閱讀 328評論 6 2