Mac上如何编译Android可用的V8

上篇文章我们尝试在Mac上成功编译了V8,不过编译生成的d8只能运行在Mac主机上运行,具体请参考「Mac上如何编译V8」。如果想要编译出能在Android上运行的d8该怎么做呢?这就要用到传说中的cross compile了。

V8交叉编译

请参考官方文档https://v8.dev/docs/cross-compile-arm

修改gclient配置文件

在.gclient文件里添加target_os=['android'],问题来了,这个.gclient文件在哪,笔者在V8源码文件夹下一顿找,居然没找到这货。假设你源码路径为/path/to/v8/v8,这货在/path/to/v8下,改完之后应该类似下图

下载Android相关依赖

在/path/to/v8下执行gclient sync命令

生成ninja文件

执行tools/dev/v8gen.py list,结果如下

这里我选择arm64架构的,执行tools/dev/v8gen.py arm64.release,会生成out.gn/arm64.release文件夹,目录结构如下图

执行gn args out.gn/arm64.release查看生成的默认参数配置,可根据需要修改默认参数,笔者的配置如下图

执行gn args out.gn/arm64.release/ --list命令可以查看支持的所有参数及每个参数的说明,如果只想看某个参数的说明,例如只想看symbol_level参数的说明可执行gn args out.gn/arm64.release/ --list=symbol_level,结果如下图

编译

执行ninja -C out.gn/arm64.release/ d8,即可启动编译。

编译过程碰到的问题

1. fatal error: 'features.h' file not found

我们搜下v8源码目录下是否有features.h文件,find . -name features.h,可以看到toolchains下只有linux-x86_64,但编译用的确是third_party/android_ndk/toolchains/llvm/prebuilt/darwin-x86_64/sysroot

解决方法

1. 先看下v8里的ndk的版本,cat third_party/android_ndk/source.properties

2. 下载这个版本的ndk(如果本地有其他版本的ndk可先尝试),并在ndk目录下搜索features.h,find . -name features.h

3. 把红框拷贝到v8下的ndk里,执行cp -rv 20.0.5594570/toolchains/llvm/prebuilt/darwin-x86_64/ /path/to/v8/v8/third_party/android_ndk/toolchains/llvm/prebuilt/darwin-x86_64/,darwin-x86_64已经有了

4. 再启动编译

2. llvm-ar: No such file or directory

报错是因为llvm-ar这个文件不存在

解决方法

1. 同上一个问题,在ndk目录下搜索llvm-ar,find . -name llvm-ar

2. 把红框文件拷贝过去,cp ./20.0.5594570/toolchains/llvm/prebuilt/darwin-x86_64/bin/llvm-ar /path/to/v8/v8/third_party/llvm-build/Release+Asserts/bin/

3. 再启动编译

3. invalid linker name in argument '-fuse-ld=lld'

解决方法

参考https://lld.llvm.org/

猜测应该是因为ld.lld这个文件找不到,在v8源码目录下执行find . -name ld.lld

尝试拷贝这个文件,执行cp ./third_party/android_ndk/toolchains/llvm/prebuilt/darwin-x86_64/bin/ld.lld third_party/llvm-build/Release+Asserts/bin/

再启动编译

4. OSError: [Errno 8] Exec format error

解决方法

1. 调试gcc_link_wrapper.py发现是执行strip的时候出错了,错误显示「Exec format error」

2. 看下eu-strip文件的格式,执行file buildtools/third_party/eu-strip/bin/eu-strip,可以看到这个文件是Linux上的可执行格式,Mac的可执行文件格式应该是「Mach-O」这种格式的。

3. 在third_party/android_ndk/toolchains/llvm/prebuilt/darwin-x86_64下搜索stripe命令,find . -name *strip*

4. 尝试把eu-strip换成llvm-strip试下,v8源码目录下搜索eu-strip,grep -nr 'eu-strip' *,strip工具应该是在build/toolchain/android/BUILD.gn里配置的。

4. 修改build/toolchain/android/BUILD.gn,替换eu-strip为llvm-strip

5. 再启动编译,终于编译成功。

运行

cd out.gn/arm64.release

adb push d8 /data/local/tmp/v8/bin/,android上成功运行

总结

编译过程中碰到了4个问题,可以看到都是环境问题,而且网上相关的资料比较少,笔者在这里还折腾了不少时间,好在最终都成功解决了。难怪网上很多人都推荐用Linux去编译V8,如果用Linux编译的话应该不会有这些问题吧,但笔者手上只有Mac环境,也不想倒腾虚拟机,就硬着头皮在Mac上开干了。人生在于折腾,一分折腾一分收获,谨以此与大家共勉。

你可能感兴趣的:(Mac上如何编译Android可用的V8)