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.a 和 libssl.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 是必須的依賴