前言
近期項目要開始做鴻蒙版本,有一部分依賴native的代碼也需要遷移,某個native模塊依賴openssl,需要在鴻蒙下重新編譯openssl才行。一開始找了很多相關文檔都沒有得到方法,無奈只能自己憑經驗慢慢試,最后還是成功了。
鴻蒙NDK下載地址
https://gitee.com/openharmony/docs/tree/master/zh-cn/release-notes#openharmony-release-notes
需要單獨下載一份sdk,因為ide里面下載的sdk里面的ndk是不全的,缺少sysroot
如何編譯
使用Cmake
上面的下載地址其實包含了編譯三方庫的教程,但是只有基于Cmake的方式,而且非常簡陋,并沒有提供一個真實的三方庫編譯教程,而實際開發中通常要復雜很多,需要編譯的庫往往有許多配置,還有一些子依賴,比較難以處理。另外有些庫壓根沒有提供Cmake編譯的方式,比如OpenSSL。如果庫支持的話使用cmake編譯相對簡單一些,可以使用cmake-gui或者ide。
使用庫提供的其他編譯方式
大多數庫都會提供一個配置腳本(./Configure)讓使用者自定義進行編譯,通常只需要配置好一些必要參數,必要工具的路徑就可以比較輕松的完成,但是現在主流庫肯定是沒有鴻蒙支持的,所以需要自己額外配置的東西很多,接下來以編譯OpenSSL為例。
先定義一個比較通用的配置腳本build_config.sh,方便以后編譯其他庫也能用,鴻蒙的編譯器好像不像android那樣需要區分api和架構,全都在llvm目錄下,直接指定就可以了
另外還需要指定目標平臺target、sysroot、cflags這些,我在文檔里面沒有找到,按照慣例找到了sdk里面的ohos.toolchain.cmake文件,參考這個文件進行了定義
比較麻煩的是編譯openssl時需要指定的架構,openssl支持的架構配置在下圖這些文件里面給了定義,但是沒有鴻蒙的支持,那就只能選用linux的,linux-armv4、linux-aarch64這些。
build_config.sh
#NDK路徑export OHOS_NATIVE_HOME=/Users/admin/Downloads/ohos-sdk/darwin/nativeexport PATH=$OHOS_NATIVE_HOME/llvm/bin:$PATH#cpu架構if [ "$#" -lt 1 ]; thenTHE_ARCH=armv7elseTHE_ARCH=$(tr [A-Z] [a-z] <<< "$1")fiBASE_FLAGS="--sysroot=$OHOS_NATIVE_HOME/sysroot -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -Wa,--noexecstack -fPIC"#根據不同架構配置環境變量case "$THE_ARCH" inarmv7a|armeabi-v7a)OHOS_ARCH="armeabi-v7a"OHOS_TARGET="arm-linux-ohos"OPENSSL_ARCH="linux-armv4"FF_EXTRA_CFLAGS="--target=$OHOS_TARGET $BASE_FLAGS -march=armv7a"FF_CFLAGS="--target=$OHOS_TARGET $BASE_FLAGS -march=armv7a";;armv8|armv8a|aarch64|arm64|arm64-v8a)OHOS_ARCH="arm64"OHOS_TARGET="aarch64-linux-ohos"OPENSSL_ARCH="linux-aarch64"FF_EXTRA_CFLAGS="--target=$OHOS_TARGET $BASE_FLAGS"FF_CFLAGS="--target=$OHOS_TARGET $BASE_FLAGS";;x86_64|x64)OHOS_ARCH="x86_64"OHOS_TARGET="x86_64-linux-ohos"OPENSSL_ARCH="linux-x86_64"FF_EXTRA_CFLAGS="--target=$OHOS_TARGET $BASE_FLAGS"FF_CFLAGS="--target=$OHOS_TARGET $BASE_FLAGS";;*)echo "ERROR: Unknown architecture $1"[ "$0" = "$BASH_SOURCE" ] && exit 1 || return 1;;esac# 工具鏈TOOLCHAIN=$OHOS_NATIVE_HOME/llvm# 交叉編譯庫搜索路徑SYS_ROOT=$OHOS_NATIVE_HOME/sysroot# 編譯器CC=$TOOLCHAIN/bin/clangCXX=$TOOLCHAIN/bin/clang++# 鏈接器,將目標文件(包括靜態庫和共享庫)合并成一個可執行文件或共享庫LD=$TOOLCHAIN/bin/ld-lld# 匯編器,將匯編語言代碼轉換為機器代碼AS=$TOOLCHAIN/bin/llvm-as# 靜態庫管理工具,用于創建、修改和提取靜態庫中的目標文件AR=$TOOLCHAIN/bin/llvm-ar# 符號表工具,用于顯示目標文件中的符號(函數、變量等)信息NM=$TOOLCHAIN/bin/llvm-nm# 靜態庫索引工具,用于創建和更新靜態庫的索引,以提高庫的訪問速度RANLIB=$TOOLCHAIN/bin/llvm-ranlib# 剝離工具,用于從可執行文件或共享庫中去除調試信息,從而減小文件大小STRIP=$TOOLCHAIN/bin/llvm-strip
接下來就比較簡單了,再定義一個執行編譯的腳本build_openssl.sh,可選的編譯參數在configure文件里面,可以按需要配置
build_openssl.sh
#!/bin/bashARCH=$1source build_config.sh $ARCHLIBS_DIR=$(cd `dirname $0`; pwd)/libs/opensslPREFIX=$LIBS_DIR/$OHOS_ARCHecho "PREFIX"=$PREFIXexport CC="$CC"export CXX="$CXX"export CXXFLAGS=$FF_EXTRA_CFLAGSexport CFLAGS=$FF_CFLAGSexport AR="$AR"export LD="$LD"export AS="$AS"export NM="$NM"export RANLIB="$RANLIB"export STRIP="$STRIP"export LDFLAGS="--rtlib=compiler-rt -fuse-ld=lld"./Configure $OPENSSL_ARCH \--prefix=$PREFIX \no-engine \no-asm \no-threads \sharedmake cleanmake -j2make installcd ..
還有兩個比較坑的點
- armv7架構下openssl依賴了libatomic,但是鴻蒙sdk里面沒有提供這個庫,所以我直接去改了openssl里面的配置,linux-armv4配置原本繼承自linux-latomic,依賴了libatomic,直接改成繼承linux-generic32,libatomic是一個多線程下保持原子性的庫,所以需要加上no-threads禁用多線程。另外也可以自己去編譯一個libatomic出來一起鏈接,這樣就可以用多線程了。
- 默認配置編譯出來的so庫是帶軟鏈接,有so.x.y這種帶版本號的命名,也需要在配置里面改一下
最后把腳本文件放到openssl目錄下執行編譯就可以了,也可以再寫一個腳本方便一次性編譯所有架構
for arch in armeabi-v7a arm64-v8a
dobash build_openssl.sh $arch
done