背景
最近基于libevent开发了一个端侧的缓存代理库,先是基于macOS编译开发的,基本0问题,后来移植到鸿蒙与android时遇到一些编译链接问题。
libevent版本如下:
软件版本号 | libevent-2.1.8 |
android编译
编译环境
android studio版本 | ndk编译链版本 | api级别 |
Android Studio Flamingo | 2022.2.1 Patch 2 Non-Bundled Plugins: | ~/Library/Android/sdk/ndk/22.1.7171670 | 28 |
问题现象
ld: error: undefined symbol: arc4random_addrandom
>>> referenced by evutil_rand.c
>>> evutil_rand.o:(evutil_secure_rng_add_bytes) in archive ./.libs/libevent.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [sample/dns-example] Error 1
make: *** [all] Error 2
/Applications/Xcode.app/Contents/Developer/usr/bin/make install-am
CCLD sample/dns-example
ld: error: undefined symbol: arc4random_addrandom
>>> referenced by evutil_rand.c
>>> evutil_rand.o:(evutil_secure_rng_add_bytes) in archive ./.libs/libevent.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[1]: *** [sample/dns-example] Error 1
make: *** [install] Error 2
解决办法
找到evutil_rand.c文件,将以下代码注释掉即可:
// void
// evutil_secure_rng_add_bytes(const char *buf, size_t n)
// {
// arc4random_addrandom((unsigned char*)buf,
// n>(size_t)INT_MAX ? INT_MAX : (int)n);
// }
贴出android下编译libevent为arm64和armv7a架构的shell脚本:
#!/bin/bash
# 根据实际ndk编译链位置修改
export ANDROID_NDK_HOME=/Users/mingo/Library/Android/sdk/ndk/22.1.7171670
export TOOLCHAIN_DIR=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64
export SYSROOT=$TOOLCHAIN_DIR/sysroot
export TARGET_ARCH=aarch64-linux-android
export TOOLCHAIN=$TOOLCHAIN_DIR
export API_LEVEL=28
TARGET=aarch64-linux-android${API_LEVEL}
export CLANG="$TOOLCHAIN/bin/aarch64-linux-android$API_LEVEL-clang"
export CLANGXX="$TOOLCHAIN/bin/aarch64-linux-android$API_LEVEL-clang++"
export AR="$TOOLCHAIN/bin/aarch64-linux-android-ar"
export LD="$TOOLCHAIN/bin/aarch64-linux-android-ld"
export RANLIB="$TOOLCHAIN/bin/aarch64-linux-android-ranlib"
export STRIP="$TOOLCHAIN/bin/aarch64-linux-android-strip"
# 根据实际openssl位置修改
OPENSSL_OUTPUT=/Users/mingo/Applications/workspace/opensrc/openssl-android/android
OPENSSL_DIR=${OPENSSL_OUTPUT}/aarch64
PKG_CONFIG_PATH="$OPENSSL_DIR/lib/pkgconfig"
CFLAGS="--sysroot=$SYSROOT -I$OPENSSL_DIR/include --target=$TARGET -fPIC -DEVUTIL_DISABLE_ARC4RANDOM"
LDFLAGS="--sysroot=$SYSROOT -L$OPENSSL_DIR/lib -lz"
OUTPUT_DIR=$(pwd)/android/$TARGET_ARCH
mkdir -p ${OUTPUT_DIR}
function build() {
./configure --host=$TARGET_ARCH --prefix=$OUTPUT_DIR \
--with-sysroot=${SYSROOT} \
--with-openssl=$OPENSSL_DIR \
--disable-shared \
--disable-arc4random \
CC=$CLANG \
CXX=$CLANGXX \
AR=$AR \
RANLIB=$RANLIB \
CFLAGS="$CFLAGS" \
LDFLAGS="$LDFLAGS"
make clean
make j8
make install
}
build
TARGET_ARCH=arm-linux-androideabi
TARGET=arm-linux-android${API_LEVEL}
OUTPUT_DIR=$(pwd)/android/$TARGET_ARCH
mkdir -p ${OUTPUT_DIR}
OPENSSL_DIR=${OPENSSL_OUTPUT}/armv7a
PKG_CONFIG_PATH="$OPENSSL_DIR/lib/pkgconfig"
CFLAGS="--sysroot=$SYSROOT -I$OPENSSL_DIR/include --target=$TARGET -fPIC -DEVUTIL_DISABLE_ARC4RANDOM"
LDFLAGS="--sysroot=$SYSROOT -L$OPENSSL_DIR/lib -lz"
build
鸿蒙编译
编译环境
DevEco版本 | 编译链版本 | api级别 |
DevEco Studio NEXT Developer Beta3 Build #DS-233.14475.28.36.503600 Build Version: 5.0.3.600, built on August 7, 2024 Runtime version: 17.0.10+1-b1087.17 aarch64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o. macOS 14.3.1 GC: G1 Young Generation, G1 Old Generation Memory: 2048M Cores: 10 Metal Rendering is ON Registry: idea.plugins.compatible.build=IC-233.14475.28 | ~/Library/OpenHarmony/Sdk/12 | 12 |
先是到华为官网下载DevEco IDE开发工具,ID安装好后,再安装鸿蒙编译链,选择api 12的ndk版本进行安装:
下载中心 | 华为开发者联盟-HarmonyOS开发者官网,共建鸿蒙生态
编译链安装完毕,本文默认安装在以下目录:
mingo@localhost:~/Library/OpenHarmony/Sdk/12$pwd
/Users/mingo/Library/OpenHarmony/Sdk/12
mingo@localhost:~/Library/OpenHarmony/Sdk/12$tree -L 2
.
├── native
│ ├── NOTICE.txt
│ ├── build
│ ├── build-tools
│ ├── llvm
│ ├── nativeapi_syscap_config.json
│ ├── ndk_system_capability.json
│ ├── oh-uni-package.json
│ └── sysroot
└── toolchains
├── NOTICE.txt
├── ark_disasm
├── configcheck
├── diff
├── hdc
├── hnpcli
├── id_defined.json
├── idl
├── lib
├── libusb_shared.dylib
├── modulecheck
├── oh-uni-package.json
├── restool
├── syscap_tool
└── syscapcheck
11 directories, 15 files
编译脚本
编译链安装完毕,便可以利用该工具链进行编译了,贴出完整编译脚本:
#!/bin/bash
set -e
# 根据实际位置修改
HARMONY_SDK_PATH=/Users/mingo/Library/OpenHarmony/Sdk/12
CLANG=$HARMONY_SDK_PATH/native/llvm/bin/clang
CLANGXX=$HARMONY_SDK_PATH/native/llvm/bin/clang++
AR=$HARMONY_SDK_PATH/native/llvm/bin/llvm-ar
RANLIB=$HARMONY_SDK_PATH/native/llvm/bin/llvm-ranlib
# compile for aarch64
TARGET_ARCH=aarch64-linux-gnu
TARGET=aarch64-linux-ohos
SYSROOT=$HARMONY_SDK_PATH/native/sysroot
ZLIB_ROOT_PATH=${HARMONY_SDK_PATH}/native/sysroot/usr
ZLIB_INCLUDE_PATH=${ZLIB_ROOT_PATH}/include
ZLIB_LIB_PATH=${ZLIB_ROOT_PATH}/lib/aarch64-linux-ohos
# 根据实际位置修改
OPENSSL_DIR=/Users/mingo/Applications/workspace/opensrc/openssl/hmos/aarch64
PKG_CONFIG_PATH="$OPENSSL_DIR/lib/pkgconfig"
CPPFLAGS="-I$OPENSSL_DIR/include -I${ZLIB_INCLUDE_PATH}"
SYSLIB_INCLUDE_DIR=${SYSROOT}/usr/include/aarch64-linux-ohos
echo "syslib=$SYSLIB_INCLUDE_DIR"
CFLAGS="--sysroot=$SYSROOT -I$SYSLIB_INCLUDE_DIR -I$OPENSSL_DIR/include -I$ZLIB_INCLUDE_PATH --target=$TARGET -fPIC"
#CFLAGS="--sysroot=$SYSROOT -I$SYSLIB_INCLUDE_DIR -I$ZLIB_INCLUDE_PATH --target=$TARGET -fPIC"
LDFLAGS="--sysroot=$SYSROOT -L$OPENSSL_DIR/lib -L$ZLIB_LIB_PATH -lz"
export CC=$CLANG
export CXX=$CLANGXX
export AR=$AR
export RANLIB=$RANLIB
export CFLAGS=$CFLAGS
export LDFLAGS=$LDFLAGS
# compile for libevent-2.1.8-stable
LIBEVENT_SRC_PATH=`pwd`/libevent-2.1.8-stable
cd $LIBEVENT_SRC_PATH
PREFIX=${LIBEVENT_SRC_PATH}/ohos/aarch64
mkdir -p ${PREFIX}
function build_event() {
make clean
make distclean
./configure --host=$TARGET_ARCH --prefix=$PREFIX \
--with-sysroot=${SYSLIB_INCLUDE_DIR} \
--with-openssl=$OPENSSL_DIR \
--with-zlib=$ZLIB_ROOT_PATH \
--disable-shared \
CC=$CLANG \
CXX=$CLANGXX \
AR=$AR \
RANLIB=$RANLIB \
CFLAGS="$CFLAGS" \
LDFLAGS="$LDFLAGS"
make verbose=1
make install
cd ..
}
build_event
提示:鸿蒙编译链编译libevent的时候,先是下载的api=10的编译链,但在找系统库文件的时候找不到,于是切到api=12级别的编译链,可顺利编译出所需静态库。