1. 程式人生 > >Ubuntu 交叉編譯 OpenSSL,並在 Android 中使用

Ubuntu 交叉編譯 OpenSSL,並在 Android 中使用

編譯環境是Ubuntu,寫這個說明的時刻,最新的 NDK 版本是 15,OpenSSL 版本是 1.1.1e

1. 準備編譯指令碼

我們用得到的是 _shared.sh 和 build-openssl4android.sh

build-openssl4android.sh 中,預設的OpenSSL 版本是 1.0.2k,改成最新的1.1.1e

-LIB_NAME="openssl-1.0.2k"
-LIB_NAME="openssl-1.1.1e"

指令碼會自動下載 openssl 1.1.1e,需要有curl

替換掉這個檔案中所有的 android-armv7,替換為 android-armeabi


預設只編譯靜態庫,如果想要動態庫,修改下面這裡,刪掉 no-shared \

  ./Configure $ARCH \
              --prefix=${LIB_DEST_DIR}/${ABI} \
              --with-zlib-include=$SYSROOT/usr/include \
              --with-zlib-lib=$SYSROOT/usr/lib \
              zlib \
              no-asm \
              no-shared \
              no-unit-test

2. 配置NDK

修改環境變數

sudo gedit /etc/profile

新增

export ANDROID_NDK=/home/yangming/Develop/Android/Sdk/ndk-bundle

使之生效

source /etc/profile

非常關鍵的一點,開啟 NDK 路徑中 ndk-bundle/build/tools/make-standalone-toolchain.sh,找到

run python `dirname $0`/make_standalone_toolchain.py \
    --arch $ARCH $PLATFORM_ARG --stl $STL $INSTALL_ARG $FORCE_ARG

在結尾加上一句 –deprecated-headers

run python `dirname $0`/make_standalone_toolchain.py \
    --arch $ARCH $PLATFORM_ARG --stl $STL $INSTALL_ARG $FORCE_ARG --deprecated-headers

如果使用 NDK15,不加這句話就會在編譯的時候失敗,輸出如下

...
./libcrypto.so: error: undefined reference to 'stderr'
./libcrypto.so: error: undefined reference to 'stdin'
./libcrypto.so: error: undefined reference to 'signal'
./libcrypto.so: error: undefined reference to 'tcsetattr'
./libcrypto.so: error: undefined reference to 'tcgetattr'
collect2: error: ld returned 1 exit status
make[2]: *** [link_app.gnu] Error 1
make[2]: Leaving directory `/home/yangming/Develop/Projects/openssl_for_ios_and_android/tools/openssl-1.1.0e`
make[1]: *** [fuzz/asn1-test] Error 2
make[1]: *** Waiting for unfinished jobs....
...

3. 生成 android-toolchain

實際上 _shared.sh就會自動生成 android-toolchain,但是我們不使用指令碼生成的,終端進入 openssl_for_ios_and_android/tools,輸入

$ANDROID_NDK/build/tools/make-standalone-toolchain.sh --platform=android-14 --toolchain=arm-linux-androideabi-4.9 --install-dir=`pwd`/armeabi-v7a-android-toolchain

生成 armeabi-v7a-android-toolchain 資料夾

4. 編譯

終端輸入

./build-openssl4android.sh android-armeabi

編譯結束後會看到生成了 libs 資料夾,標頭檔案在 /openssl_for_ios_and_android/tools/libs/armeabi-v7a/include,庫檔案在 /openssl_for_ios_and_android/tools/libs/armeabi-v7a/lib/

5. 建立 Android 工程

android studio 新建 Android 工程 OpenSSLDemo,勾選 “Include C++ support”

將剛剛生成的靜態連結庫 libcrypto.alibssl.a 拷到 /OpenSSLDemo/app/src/main/jniLibs/armeabi-v7a

標頭檔案 include 拷到 /OpenSSLDemo/app/src/main/cpp/include

6. 修改 CMakeLists.txt

宣告標頭檔案位置

include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)

新增靜態連結庫,並宣告庫位置

add_library(crypto STATIC IMPORTED)
set_target_properties(crypto
  PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libcrypto.a)

add_library(ssl STATIC IMPORTED)
set_target_properties(ssl
  PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libssl.a)

連結

target_link_libraries( # Specifies the target library.
                       openssl-jni
                       z
                       ssl
                       crypto

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

注意那個 z,libz 是必須的依賴