【android】静态链接器/加载器(ld) 动态加载器(/system/bin/linker)+动态加载接口(dlopen)

本文将深入探讨Android系统中动态连接器linker与静态连接器ld的工作原理及它们之间的区别。通过对这些核心组件的理解,读者可以更好地掌握Android应用程序的加载过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C/C++: ld: error: found local symbol '_edata' in global part of symbol table in file D:/AndroidProject/Application_721_rknn/app_rknn_face_demp/src/main/jniLibs/arm64-v8a\librknn_sunchip.so 我编译出来的库为什么会出现这种情况,我的编译指令是: cmake_minimum_required(VERSION 3.4.1) project(RKFace VERSION 1.0.0) # 设置 C++ 标准 set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 基本编译选项 set(CMAKE_C_FLAGS "-Wall -fPIC -O2") set(CMAKE_CXX_FLAGS "-Wall -fPIC -O2") # Android 平台配置 if(CMAKE_SYSTEM_NAME STREQUAL "Android") add_definitions(-DANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") endif() # 包含目录 include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/include ) # 源文件 set(main_source src/main.cc) # 库文件路径 set(LIBPATH ${CMAKE_CURRENT_SOURCE_DIR}/libs/android) # 链接库 set(LINKS ${LIBPATH}/libRKFace.so ${LIBPATH}/libnva.so ${LIBPATH}/librknnrt.so ) # Android 特定库 if(CMAKE_SYSTEM_NAME STREQUAL "Android") list(APPEND LINKS log c++_shared) endif() # 标准库 list(APPEND LINKS c m dl) # 生成可执行文件 add_executable(rkface.demo ${main_source}) # 链接库 target_link_libraries(rkface.demo ${LINKS}) # 设置安装目录为当前目录下的 install set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/install) #生成库 add_library(rknn_sunchip SHARED src/rknn_sunchip.cc) target_include_directories(rknn_sunchip PRIVATE include) target_link_libraries(rknn_sunchip ${LINKS}) # 安装到ABI分层目录 install(TARGETS rknn_sunchip LIBRARY DESTINATION ${LIBPATH}/install/libs/${ANDROID_ABI} ) # 安装可执行文件到 install/bin install(TARGETS rkface.demo RUNTIME DESTINATION bin) # 安装库文件到 install/lib install(FILES ${LIBPATH}/libRKFace.so ${LIBPATH}/libnva.so ${LIBPATH}/librknnrt.so DESTINATION lib ) # 安装头文件到 install/include (如果需要) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/ DESTINATION include FILES_MATCHING PATTERN "*.h" PATTERN "*.hpp" ),编译脚本是:#!/bin/bash # 编译NVA库为Android .so文件的脚本(优化版本) # 使用方法: ./build_android_optimized.sh [目标ABI] # 检查参数 if [ $# -lt 1 ]; then echo "用法: $0 <目标ABI>" echo "例如: $0 arm64-v8a" echo "支持的ABI: armeabi-v7a, arm64-v8a" exit 1 fi # 参数设置 NDK_PATH=/home/share/work/YML/android-ndk-r19c SRC_PATH=./ TARGET_ABI=$1 BUILD_DIR="${SRC_PATH}/build_android_${TARGET_ABI}" API_LEVEL=24 # 可根据需要调整API级别 PROJECT_ROOT=$(pwd) THIRD_PARTY_PATH="${PROJECT_ROOT}/../000_3rdParty" # OPENCV_PATH="${THIRD_PARTY_PATH}/libopencv/opencv-android-sdk-build" OPENCV_PATH="${THIRD_PARTY_PATH}/libopencv/opencv_android_4.6.0/" # 检查NDK路径是否存在 if [ ! -d "$NDK_PATH" ]; then echo "错误: NDK路径不存在: $NDK_PATH" exit 1 fi # 检查目标ABI是否有效 case $TARGET_ABI in armeabi-v7a) ABI="armeabi-v7a" ARCH_FLAGS="-march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard" ;; arm64-v8a) ABI="arm64-v8a" ARCH_FLAGS="-march=armv8-a" ;; *) echo "错误: 不支持的ABI: $TARGET_ABI" echo "支持的ABI: armeabi-v7a, arm64-v8a" exit 1 ;; esac # 设置优化标志 - 与Linux版本一致 # 设置更保守的优化标志,避免过度优化导致的问题 OPT_FLAGS="-O2 -fno-strict-aliasing -fwrapv -fno-omit-frame-pointer" SECURITY_FLAGS="-fstack-protector-strong -D_FORTIFY_SOURCE=2" VISIBILITY_FLAGS="-fvisibility=hidden -fvisibility-inlines-hidden" # 移除可能导致问题的标志 # EXTRA_FLAGS="-fno-common" # 这个可能在Android上有问题 EXTRA_FLAGS="-fno-common -Wno-unused-command-line-argument" # Android特定的标志 ANDROID_FLAGS="-fPIC -fdata-sections -ffunction-sections" # 链接器标志 - 更保守的设置 LINKER_FLAGS="-Wl,--gc-sections,--as-needed,--no-undefined" # 组合所有标志 ALL_FLAGS="$ARCH_FLAGS $OPT_FLAGS $SECURITY_FLAGS $VISIBILITY_FLAGS $EXTRA_FLAGS $ANDROID_FLAGS" echo "====== 配置信息 ======" echo "NDK路径: $NDK_PATH" echo "源码路径: $SRC_PATH" echo "目标ABI: $TARGET_ABI" echo "构建目录: $BUILD_DIR" echo "API级别: $API_LEVEL" echo "第三方库路径: $THIRD_PARTY_PATH" echo "OpenCV库路径: $OPENCV_PATH" echo "编译优化标志: $ALL_FLAGS" echo "链接器标志: $LINKER_FLAGS" echo "======================" # 创建构建目录 mkdir -p $BUILD_DIR cd $BUILD_DIR # 设置CMake工具链文件路径 TOOLCHAIN_FILE="${NDK_PATH}/build/cmake/android.toolchain.cmake" if [ ! -f "$TOOLCHAIN_FILE" ]; then echo "错误: 无法找到Android CMake工具链文件: $TOOLCHAIN_FILE" exit 1 fi # API级别检查函数 check_api_compatibility() { case $TARGET_ABI in armeabi-v7a) MIN_API=24 ;; arm64-v8a) MIN_API=24 ;; esac if [ $API_LEVEL -lt $MIN_API ]; then echo "错误: OpenCV要求${TARGET_ABI}的最低API级别为${MIN_API}" exit 1 fi } # 在参数检查之后调用 check_api_compatibility # 设置OpenCV配置路径 OPENCV_CONFIG_LOCATIONS=( "${OPENCV_PATH}/sdk/native/jni/abi-${TARGET_ABI}" "${OPENCV_PATH}/sdk/native/jni" "${OPENCV_PATH}/sdk/native" "${OPENCV_PATH}/share/OpenCV" "${OPENCV_PATH}/lib/cmake/opencv4" ) OPENCV_CONFIG_PATH="" for location in "${OPENCV_CONFIG_LOCATIONS[@]}"; do if [ -f "${location}/OpenCVConfig.cmake" ]; then OPENCV_CONFIG_PATH="${location}" echo "找到OpenCV配置文件: ${location}/OpenCVConfig.cmake" break fi done if [ -z "$OPENCV_CONFIG_PATH" ]; then echo "警告: 无法找到OpenCVConfig.cmake文件, 请检查OpenCV路径" echo "将尝试继续配置,但可能会失败..." OPENCV_CONFIG_PATH="${OPENCV_PATH}" fi echo "使用OpenCV配置路径: $OPENCV_CONFIG_PATH" echo "使用CMake工具链文件: $TOOLCHAIN_FILE" # 运行CMake配置 echo "正在配置CMake..." export OpenCV_DIR=$OPENCV_CONFIG_PATH cmake -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN_FILE \ -DANDROID_ABI=$ABI \ -DANDROID_PLATFORM=android-$API_LEVEL \ -DANDROID_STL=c++_shared \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_FLAGS="$ALL_FLAGS" \ -DCMAKE_CXX_FLAGS="$ALL_FLAGS" \ -DCMAKE_SHARED_LINKER_FLAGS="$LINKER_FLAGS" \ -DCMAKE_EXE_LINKER_FLAGS="$LINKER_FLAGS" \ -DOpenCV_DIR=$OPENCV_CONFIG_PATH \ -DBUILD_SHARED_LIBS=ON \ -DENABLE_LTO=OFF \ -DCMAKE_VERBOSE_MAKEFILE=ON \ -DANDROID_NATIVE_API_LEVEL=$API_LEVEL \ .. # 检查CMake配置是否成功 if [ $? -ne 0 ]; then echo "错误: CMake配置失败" # 提供调试信息 echo "" echo "======= 调试信息 =======" echo "请检查以下几点:" echo "1. OpenCV安装是否完整,确认OpenCV Android SDK路径是否正确" echo "2. 在CMakeLists.txt中,确认OpenCV_DIR路径设置正确" echo "3. 尝试手动查找OpenCVConfig.cmake位置:" echo " find $OPENCV_PATH -name OpenCVConfig.cmake -o -name opencv-config.cmake" echo "4. 确认opencv库对应的ABI版本是否存在:" if [ -d "${OPENCV_PATH}/sdk/native/libs/${ABI}" ]; then echo " ABI库文件存在: ${OPENCV_PATH}/sdk/native/libs/${ABI}" ls -la "${OPENCV_PATH}/sdk/native/libs/${ABI}" else echo " 警告: 没有找到对应ABI的OpenCV库: ${OPENCV_PATH}/sdk/native/libs/${ABI}" fi echo "========================" exit 1 fi # 编译 echo "正在编译..." cmake --build . --config Release -- -j$(nproc) # 检查编译是否成功 if [ $? -ne 0 ]; then echo "错误: 编译失败" exit 1 fi # 创建输出目录 INSTALL_DIR="${BUILD_DIR}/../../install" mkdir -p $INSTALL_DIR/lib/$ABI # 复制生成的库文件 echo "正在安装..." cmake --install . --prefix "$INSTALL_DIR" # 使用strip进一步精简库文件 echo "正在精简库文件..." find $INSTALL_DIR -name "*.so" -exec ${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip --strip-all {} \; echo "编译完成!" echo "库文件位置: $INSTALL_DIR/lib/" ls -la $INSTALL_DIR/lib/ echo "头文件位置: $INSTALL_DIR/include/" ls -la $INSTALL_DIR/include/ echo "生成的库文件列表:" find $INSTALL_DIR -name "*.so" -o -name "*.a" # 显示库文件大小 echo "" echo "库文件大小信息:" find $INSTALL_DIR -name "*.so" -exec du -h {} \;
最新发布
06-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值