当前位置: 首页 > news >正文

在Ubuntu 20.04上为Android ARM64编译LLVM 15.0.7的保姆级避坑指南(附NDK 24配置)

在Ubuntu 20.04上为Android ARM64编译LLVM 15.0.7的保姆级避坑指南(附NDK 24配置)

当Android NDK官方预编译的工具链无法满足特定需求时,自行编译LLVM成为解决定制化问题的终极方案。本文将带您从零开始,在Ubuntu 20.04系统上为ARM64架构的Android设备编译LLVM 15.0.7,并详细解决编译过程中可能遇到的各种"坑"。

1. 环境准备与源码获取

1.1 系统与工具要求

确保您的Ubuntu 20.04系统已安装以下基础工具:

sudo apt update && sudo apt install -y \ git cmake ninja-build \ python3 python3-pip \ g++ make zlib1g-dev

注意:建议使用物理机而非虚拟机进行编译,LLVM编译过程对CPU和内存资源消耗较大。

1.2 获取LLVM源码

使用git克隆LLVM项目源码并切换到15.0.7版本:

git clone --depth 1 --branch llvmorg-15.0.7 https://github.com/llvm/llvm-project.git cd llvm-project

提示:添加--depth 1参数可以显著减少下载时间,但会丢失历史提交记录。

1.3 Android NDK配置

下载NDK 24并设置环境变量:

wget https://dl.google.com/android/repository/android-ndk-r24-linux-x86_64.zip unzip android-ndk-r24-linux-x86_64.zip export ANDROID_NDK=$(pwd)/android-ndk-r24

2. 关键CMake脚本修改

LLVM源码中有几个模块在Android环境下会导致编译失败,需要进行针对性修改。

2.1 修改LLVMHello模块

编辑llvm/lib/Transforms/CMakeLists.txt文件:

# 原始内容 add_llvm_library(LLVMHello MODULE BUILDTREE_ONLY Hello.cpp DEPENDS intrinsics_gen PLUGIN_TOOL opt ) # 修改为 if(NOT ANDROID) add_llvm_library(LLVMHello MODULE BUILDTREE_ONLY Hello.cpp DEPENDS intrinsics_gen PLUGIN_TOOL opt ) endif()

2.2 修改BugpointPasses模块

编辑llvm/tools/bugpoint-passes/CMakeLists.txt

# 原始内容 add_llvm_library(BugpointPasses MODULE BUILDTREE_ONLY TestPasses.cpp DEPENDS intrinsics_gen bugpoint ) # 修改为 if(NOT ANDROID) add_llvm_library(BugpointPasses MODULE BUILDTREE_ONLY TestPasses.cpp DEPENDS intrinsics_gen bugpoint ) endif()

2.3 修改Bye示例模块

编辑llvm/examples/Bye/CMakeLists.txt

# 原始内容 add_llvm_pass_plugin(Bye Bye.cpp DEPENDS intrinsics_gen BUILDTREE_ONLY ) install(TARGETS ${name} RUNTIME DESTINATION "${LLVM_EXAMPLES_INSTALL_DIR}") set_target_properties(${name} PROPERTIES FOLDER "Examples") # 修改为 if(NOT WIN32 AND NOT ANDROID) add_llvm_pass_plugin(Bye Bye.cpp DEPENDS intrinsics_gen BUILDTREE_ONLY ) install(TARGETS ${name} RUNTIME DESTINATION "${LLVM_EXAMPLES_INSTALL_DIR}") set_target_properties(${name} PROPERTIES FOLDER "Examples") endif()

3. 编译配置与执行

3.1 创建编译脚本

创建build_android.sh文件,内容如下:

#!/bin/bash # 设置路径变量 build_dir=$(pwd)/build-android install_dir=$(pwd)/install-android llvm_dir=$(pwd)/llvm-project # 创建构建目录 mkdir -p $build_dir mkdir -p $install_dir # 配置CMake cmake -G Ninja -S $llvm_dir/llvm -B $build_dir \ -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" \ -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \ -DANDROID_ABI="arm64-v8a" \ -DANDROID_PLATFORM=android-24 \ -DCMAKE_INSTALL_PREFIX=$install_dir \ -DLLVM_INCLUDE_TESTS=OFF \ -DLLVM_BUILD_TESTS=OFF \ -DLLVM_INCLUDE_BENCHMARKS=OFF \ -DCMAKE_BUILD_TYPE=Release # 开始编译 ninja -C $build_dir install -j$(nproc)

3.2 执行编译

给脚本添加执行权限并运行:

chmod +x build_android.sh ./build_android.sh

编译过程可能需要数小时,具体时间取决于您的硬件配置。建议:

  • 使用高性能CPU(至少8核)
  • 分配足够的内存(建议16GB以上)
  • 使用SSD存储加速编译

4. 部署与测试

4.1 将编译结果推送到Android设备

adb connect <设备IP> adb push ./install-android /data/local/tmp/llvm

4.2 解决头文件缺失问题

在Android设备上编译时,可能会遇到标准库头文件缺失的问题。解决方法:

# 从NDK中复制必要的头文件 cp -r $ANDROID_NDK/sysroot/usr/include $install_dir/usr/

然后在编译时添加包含路径:

./bin/clang++ main.cc \ -I include/c++/v1 \ -I usr/include \ -I usr/local/include \ -I usr/include/aarch64-linux-android

4.3 解决链接器缺失问题

Android设备上可能缺少必要的链接器工具,解决方案:

  1. 编译ARM64版本的binutils工具链
  2. 将编译好的ld工具复制到Android设备的/data/local/tmp/llvm/bin目录
  3. 设置环境变量:
export PATH=$PATH:/data/local/tmp/llvm/bin

5. 常见问题与解决方案

5.1 编译过程中内存不足

如果遇到内存不足导致编译失败,可以尝试:

  • 减少并行编译任务数:将-j$(nproc)改为-j4
  • 增加系统交换空间:
sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile

5.2 CMake配置错误

如果CMake配置阶段失败,检查:

  • NDK路径是否正确设置
  • 系统是否安装了所有依赖项
  • CMake版本是否足够新(至少3.13.4)

5.3 运行时符号找不到

在Android设备上运行时如果遇到symbol not found错误,可能需要:

  • 设置正确的LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=/data/local/tmp/llvm/lib:$LD_LIBRARY_PATH
  • 静态链接相关库:
./bin/clang++ -static main.cc

6. 性能优化与高级配置

6.1 启用LTO(链接时优化)

在CMake配置中添加:

-DLLVM_ENABLE_LTO=Thin

这可以显著提高生成代码的性能,但会增加编译时间和内存消耗。

6.2 选择性编译组件

如果只需要特定组件,可以修改-DLLVM_ENABLE_PROJECTS参数。例如,仅编译Clang:

-DLLVM_ENABLE_PROJECTS="clang"

6.3 交叉编译其他Android架构

要编译其他架构(如armeabi-v7a),只需修改-DANDROID_ABI参数:

-DANDROID_ABI="armeabi-v7a"

7. 实际应用案例

7.1 使用自定义LLVM编译Android NDK项目

在Android.mk或CMakeLists.txt中指定自定义工具链:

set(CMAKE_C_COMPILER /data/local/tmp/llvm/bin/clang) set(CMAKE_CXX_COMPILER /data/local/tmp/llvm/bin/clang++)

7.2 启用实验性功能

如果需要使用LLVM中的实验性功能(如新的优化pass),可以在编译时启用:

-DLLVM_ENABLE_EXPERIMENTAL=ON

7.3 调试信息生成

为了便于调试,可以生成调试信息:

-DCMAKE_BUILD_TYPE=RelWithDebInfo

8. 维护与更新

8.1 更新LLVM版本

要更新到新版本LLVM:

git fetch --tags git checkout llvmorg-16.0.0 # 示例:切换到16.0.0版本 git submodule update --init --recursive

然后重新执行编译流程。

8.2 创建补丁文件

对源码的修改可以保存为补丁文件,方便后续使用:

git diff > android_arm64.patch

应用补丁:

git apply android_arm64.patch

8.3 二进制分发

可以将编译好的工具链打包分发:

tar -czvf llvm-15.0.7-android-arm64.tar.gz install-android
http://www.jsqmd.com/news/677299/

相关文章:

  • 正交信号原理与应用:从复数基础到通信系统实现
  • STM32实战:手把手教你用CubeMX和HAL库搞定RS485 Modbus从机(附避坑指南)
  • 从原理到代码:手把手拆解GEE中OTSU算法实现MNDWI水体分割的全过程
  • TI C2000开发避坑指南:当SysConfig生成的board.c太大,导致CC8编译报错怎么办?
  • 无细胞膜蛋白表达与合成系统(eProtein Discovery)|Cell free system|膜蛋白
  • Linux命令:ping6
  • 如何快速部署AI短视频自动化生成系统
  • 技术排障笔记:图书馆WiFi无法SSH登录云服务器,一招搞定
  • 京东股权曝光:刘强东控制12.7%股权有73%投票权 获1亿美元股息
  • Desktop Postflop:免费开源德州扑克GTO求解器实战指南
  • 2026年山东广告投流与短视频代运营深度横评:GEO推广、腾讯广告、AI智能体全景对比 - 年度推荐企业名录
  • YOLO11涨点优化:注意力机制 | 基于频域的FcaNet多光谱通道注意力接入,打破传统GAP信息丢失魔咒
  • 终极桌面监控神器:TrafficMonitor插件完整指南,打造个性化系统仪表盘
  • WebLogic 10.3.6漏洞修复踩坑实录:从补丁下载到bsu.sh内存调整,一篇讲透
  • Fastboot Enhance:3步解决Android设备刷机难题的可视化工具指南
  • Neat Bookmarks:Chrome书签管理的终极免费解决方案
  • STM32新手避坑指南:用CubeMX和HAL库搞定VESC串口通信(附完整工程)
  • 用Cesium实现一个可拖拽的3D标记点:从屏幕点击到WGS84坐标的全流程解析
  • 2026水果店加盟哪家最专业?行业深度解析与选择指南 - 品牌排行榜
  • 哪个厂家生产的不锈钢板框过滤器质量好?一线用户口碑盘点 - 品牌推荐大师
  • 30天小白逆袭!收藏这份AI大模型学习计划,快速掌握前沿技术
  • 2026年羊奶粉OEM供应商横评:奶源布局、生产能力与品控体系全对比 - 科技焦点
  • 静电控制洁净工程:从洁净环境到ESD防护的系统解析
  • 如何用JD-GUI轻松破解Java字节码:Java反编译终极指南
  • 26年团队的需求管理怎么做?高性价比工具他们是怎么做的?
  • 如何一键将AnyFlip在线翻页书变成永久收藏的PDF电子书
  • 手把手教你用TIA Portal配置PROFIdrive通信:以S7-1200控制STOBER驱动器为例
  • 虚幻引擎串口通信插件深度解析:连接虚拟世界与物理硬件的终极方案
  • 抖音内容批量下载工具:轻松获取无水印视频素材的完整指南
  • FME批量建库实战:手把手教你用PythonCaller搞定复杂schema,支持自定义坐标系