交叉编译clang/llvm for android armeabi

Clang是一个C语言、C++、Objective-C语言的轻量级编译器。源代码发布于BSD协议下。Clang将支持其普通lambda表达式、返回类型的简化处理以及更好的处理constexpr关键字。

那么,该如何在android平台上生成clang的可执行代码呢?


编译准备

  • 电脑最少8G内存空闲
  • 准备SDK

这里是SDK下载地址,由于官方需要翻墙,这里放的是第三方下载站
PS:这里还有其他的工具,比如NDK

  • 准备LLVM源码

这里是LLVM官方地址
下载最新版本的『LLVM源码』和『Clang源码』
这里演示的版本为7.0.0

  • 准备Python

因为编译时需要Python2.7,所以请在编译前安装Python2.7

1
sudo apt install python2.7


开始编译

1

解压刚刚下载好的llvm-7.0.0.src.tar.xz,放在一个你喜欢的路径
假设我放在$HOME
此时应该是$HOME/llvm-7.0.0/

2

解压刚刚下载好的sdk
我还是放在文档里
取名为android-sdk-linux
sdk里必须下载ndk-bundle和cmake
此时应该是$HOME/android-sdk-linux/

3

解压cfe-7.0.0.src.tar.xz,重命名为clang,并移到llvm源码下的tools文件夹内
此时应该是$HOME/llvm-7.0.0/tools/clang/

4

在llvm的同一级下新建一个文件夹,取名为build
此时应该是$HOME/build/

5

在一切都准备好之后,就可以开始写cmake参数了
在llvm同一级下创造一个文件,取名为llvm.sh

1
chmod +x llvm.sh

使这个文件可以被执行

6

打开llvm.sh
接下来划重点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/home/android-sdk-linux/cmake/3.6.4111459/bin/cmake \
-G "Ninja" \
-Bbuild "$PWD/../llvm-7.0.0" \
-DANDROID_PLATFORM="android-23" \
-DANDROID_STL="c++_shared" \
-DANDROID_CPP_FEATURES="rtti exceptions" \
-DANDROID_ARM_MODE="arm" \
-DANDROID_NDK="$HOME/android-sdk-linux/ndk-bundle" \
-DANDROID_TOOLCHAIN="clang" \
-DANDROID_NATIVE_API_LEVEL=23 \
-DANDROID_ALLOW_UNDEFINED_SYMBOLS=TRUE \
-DANDROID_ARM_NEON=TRUE \
-DANDROID_DISABLE_FORMAT_STRING_CHECKS=FALSE \
-DANDROID_PIE=ON \
-DANDROID_ABI="arm64-v8a" \
-DCMAKE_SYSTEM_NAME="Android" \
-DCMAKE_BUILD_TYPE="Release" \
-DCMAKE_TOOLCHAIN_FILE="$HOME/android-sdk-linux/ndk-bundle/build/cmake/android.toolchain.cmake" \
-DCMAKE_MAKE_PROGRAM="$HOME/android-sdk-linux/cmake/3.6.4111459/bin/ninja" \
-DCMAKE_C_FLAGS="-std=c11" \
-DCMAKE_CXX_FLAGS="-std=c++14 -D_LIBCPP_STD_VER=14"

必须运行sdk里的cmake,因为google对其修改了源码
位置在$SDK/cmake/3.6.4111459/bin/cmake

  • 指定用Ninja编译器 使用Make工具编译LLVM是非常耗时的 往往需要三四个小时 但是使用google开源的Ninja编译LLVM只需要10到20分钟

  • Build 后面写的是需要编译的源码位置

  • ANDROID_PLATFORM 指定目标Android平台的名称

  • ANDROID_STL 指定应使用的STL CMake 参数如下

参数 作用
none No C++ Support
system Minimal C++ without STL
gabi++_static GAbi++ Static
gabi++_shared GAbi++ Shared
gnustl_static GNU libstdc++ Static
gnustl_shared GNU libstdc++ Shared
c++_static LLVM libc++ Static
c++_shared LLVM libc++ Shared
stlport_static STLport Static
stlport_shared STLport Shared

官方默认的是c++_static

  • ANDROID_CPP_FEATURES 指定CMake在编译本机库时需要使用的某些C++特性 参数只有两个
参数 作用
rtti 表明代码使用RTTI
exceptions 表明代码使用C++异常
  • ANDROID_ARM_MODE 指定是否以arm或thumb模式生成ARM目标二进制文件

  • ANDROID_ARM_NEON 指定CMake是否应构建具有NEON支持的本机库 API23以上填TRUE,以下填FALSE

  • ANDROID_NDK 指定NDK安装的绝对路径 这里SDK已经自带了NDK了 填sdk文件夹里的ndk-bundle就好了

  • ANDROID_NATIVE_API_LEVEL 指定CMake编译的Android API级别

  • ANDROID_ALLOW_UNDEFINED_SYMBOLS 指定如果CMake在构建本机库时遇到未定义的引用 是否抛出未定义的符号错误 禁用为TRUE

  • ANDROID_DISABLE_FORMAT_STRING_CHECKS 指定是否使用格式字符串保护编译源代码 启用后 如果在printf-style函数中使用非常量格式字符串 则编译器将引发错误 所以这里填FALSE

  • ANDROID_PIE 指定是否使用与位置无关的可执行文件 API16以上需要ON 否则OFF

  • ANDROID_ABI 指定CMake编译的目标ABI 参数如下

参数
armeabi
armeabi-v7a
armeabi-v7a with NEON
arm64-v8a
x86
x86_64
  • CMAKE_SYSTEM_NAME 指定CMake编译的名称 填Android就好了

  • CMAKE_BUILD_TYPE 编译的类型 Release和Debug 选一个喜欢的

  • CMAKE_TOOLCHAIN_FILE 指定CMake用于Android交叉编译的文件的路径

  • CMAKE_MAKE_PROGRAM 用于启动本机构建系统的工具 因为我们使用Ninja编译器 所以必须要指定ninja位置
    位置在$SDK/cmake/3.6.4111459/bin/ninja

  • CMAKE_C_FLAGS和CMAKE_CXX_FLAGS作用我就不说了 表明一个用c11一个用c++14

7

进入之前新建的build文件夹

1
cd $HOME/build

在build文件夹里执行llvm.sh

1
./../llvm.sh

等出现Build files have been written to: xxxxxxx就是成功了

8

1
$HOME/android-sdk-linux/cmake/3.6.4111459/bin/ninja -jn

开始编译 n写的是你的cpu核数

9

1
$HOME/android-sdk-linux/cmake/3.6.4111459/bin/ninja install -j2

这个时候clang就差不多编译完了
最后生成的文件很大 请务必strip一下

1
$HOME/android-sdk-linux/cmake/3.6.4111459/bin/strip clang-7

如有错误 请联系qaralotte@gmail.com
敬请雅正:)