交叉编译 NodeJS v20.2.0 用于 Android 开发

0453a3438b284e1bb523131978e02230.png

 Ps:博主在知乎也有号,这个是同步发的

第一次写技术文章,可能表述不是很清楚,请见谅~

博主只是一个刚刚毕业的初中生,对 Linux 只能说略懂,如有错误请指出来,我将会改正~

1.编译环境

这里我原本是 Windows,通过 Windows Subsystem for Linux 和 Docker Desktop 去跑一个 Ubuntu Linux 环境

首先请先确保 Docker Service 处于可用(就是 Docker Desktop 成功启动)的情况下打开 PowerShell(我这里用的是 Fluent Terminal)

然后我们就可用拉取 Ubuntu 镜像了(这里用最新版本):

docker pull ubuntu:latest

然后就是开启一个容器,通过参数 -it 启动一个伪终端交互式界面

docker run -it ubuntu:latest

2.准备工作

接下来是进入 root 目录然后再更新 apt 包管理器了

cd root && apt update && apt-get update

弄完后我们要去安装一些用到的库

apt install -y wget vim binutils tar unzip python-is-python3 make file

这里我们使用 wget 去下载源码(这一步最好挂代理,否则下载有点慢)

wget https://nodejs.org/dist/v20.2.0/node-v20.2.0.tar.gz

使用 tar -xzf 进行解压,并删除 node-v20.2.0.tar.gz 这个压缩文件,

最后把解压出来的目录进行一个重命名, 方便使用

tar -xzf node-v20.2.0.tar.gz && rm node-v20.2.0.tar.gz && mv node-v20.2.0 node

接下来我们要去下载 Android NDK,这里我使用的版本是 NDK r25c,也就是最新 LTS 版本

同样,使用 wget 命令下载 NDK这一步一定一定要挂代理,因为这是 Google 仓库里的

wget https://dl.google.com/android/repository/android-ndk-r25c-linux.zip

接下来也是一样的步骤,进行解压,删除、重命名(区别在于解压使用的是 unzip

unzip -q android-ndk-r25c-linux.zip && rm android-ndk-r25c-linux.zip && mv android-ndk-r25c ndk

3.编译源码

从这一步开始就让人紧张了,毕竟编译总会出现奇奇怪怪的错误,不过还好我们跑的是 docker 容器,

所以你遇到的问题博主应该也都遇到了(

先进入 node 目录,这里我们是要得到动态链接库,所以使用 vim 修改 android_configure.py 文件

cd node && vim android_configure.py

什么都不要做,点击键盘上的 "i" 键进入插入模式

然后按住键盘的 "↓" 翻到最后(也可以用 PageDown 键,更快)

这里你会看到:

if os.path.exists("./configure"):
    os.system("./configure --dest-cpu=" + DEST_CPU + " --dest-os=android --openssl-no-asm --cross-compiling")

我们只需要在 --cross-compiling 参数的后面加上 --shared 参数

这个参数是表明,我们要编译成动态链接库(如下)

if os.path.exists("./configure"):
    os.system("./configure --dest-cpu=" + DEST_CPU + " --dest-os=android --openssl-no-asm --cross-compiling --shared")

修改完成后点击键盘上的 Esc 键,输入 :wq 后回车

这里 :wq 的意思是保存并退出文件(w 是 write,q 是 quit)

接下来我们要对源码进行一些修改(ps:否则肯定会报错的)

如果你直接配置并编译,遇到的第一个问题如图:

v2-0e06e3a837952974ca5ecff86441edb9_720w.png?source=d16d100b

出现这个错误的原因是缺少头文件,不过博主翻了下源码找到了,上传到了服务器里

我们先进入那个目录,再直接使用 wget 去下载即可(别挂代理)

cd deps/zlib
wget http://sumucheng.mucute.cn/libandroid-node-support/cpu-features.h
wget http://sumucheng.mucute.cn/libandroid-node-support/cpu-features.c

然后我们使用 vim 修改 cpu_features.c ,也就是刚刚报错的那个源文件

vim cpu_features.c

在第 42 行,如下:

#include <cpu-features.h>

将以上代码修改成

#include "cpu-features.c"

然后保存并退出,返回编译目录

cd /root/node

接下来如果直接配置并编译,会遇到第二个问题如图:

v2-d3d542843b618dbe3f179899c7820e5b_720w.png?source=d16d100b

这里的 "backtrace_symbols" 和 "backtrace" 是在 glibc 中定义的,其实 Android 也有,只不过没有暴露出来

这里我们还是一样(别挂代理)

cd deps/v8/src/base/debug
wget http://sumucheng.mucute.cn/libandroid-node-support/execinfo.h
wget http://sumucheng.mucute.cn/libandroid-node-support/execinfo.cc

然后使用 vim 编辑 stack_trace_posix.cc 源文件

vim stack_trace_posix.cc

在第 34 行,如下:

#include <execinfo.h>

将以上代码修改成

#include "execinfo.cc"

然后保存并退出,返回编译目录

cd /root/node

第三个问题如图:

v2-55a09d026c772f9a63fe7142d90ec81e_720w.png?source=d16d100b

这里你如果编译的是 32 位的架构,那就是无法打开 /system/bin/linker

出现这个问题其实不难解决,我们可以先来想一想它为什么会调用 qemu 并且是 aarch64 系架构

很简单,因为我们是交叉编译,而且目标平台就是 aarch64,然后的话仔细观察它调用了 /root/node/out/Release/icupkg 但是!我们可以用 file 命令去看一下文件类型,如图

file /root/node/out/Release/icupkg

v2-61ac950fb334fbcd3c5ac0e717553563_720w.png?source=d16d100b

难怪呢,所以我们只需要一个 linker64 文件,当然还有它所依赖的动态链接库

这里的 linker64 是我从我手机的根目录(也就是 /system/bin)里面复制出来的

当然我也一起上传到服务器了,我们继续使用 wget 下载

这里先解释下,链接器(linker)依赖于 libc++_shared.solibc.solibdl.solibm.so 这四个动态链接库

然后我们先创建 /system/bin 和 /system/lib 目录,使用 mkdir -p 可用创建多级目录

(别挂代理)

如果要编译 64 位:

cd ..
mkdir -p /system/bin && mkdir -p /system/lib
cd /system/bin
wget http://sumucheng.mucute.cn/libandroid-node-support/bin/linker64
cd /system/lib
wget http://sumucheng.mucute.cn/libandroid-node-support/lib64/libc++_shared.so
wget http://sumucheng.mucute.cn/libandroid-node-support/lib64/libc.so
wget http://sumucheng.mucute.cn/libandroid-node-support/lib64/libdl.so
wget http://sumucheng.mucute.cn/libandroid-node-support/lib64/libm.so

如果要编译 32 位:

cd ..
mkdir -p /system/bin && mkdir -p /system/lib
cd /system/bin
wget http://sumucheng.mucute.cn/libandroid-node-support/bin/linker
cd /system/lib
wget http://sumucheng.mucute.cn/libandroid-node-support/lib/libc++_shared.so
wget http://sumucheng.mucute.cn/libandroid-node-support/lib/libc.so
wget http://sumucheng.mucute.cn/libandroid-node-support/lib/libdl.so
wget http://sumucheng.mucute.cn/libandroid-node-support/lib/libm.so

做完了这一步后,我们要将链接器所需要的动态链接库加入环境变量中,然后返回编译目录

export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/system/lib"
cd /root/node

第四个问题如图:

v2-719a88ec7df22f52166a3b0192e89edb_720w.png?source=d16d100b

这个错误是因为找不到库,不过其实问题不大,-lrt 是告诉编译器去查找这个库

rt.soglibcreal-time 的支持,Android 其实也有,不过还是被隐藏了(但是是可用的)

所以我们只需要把这个编译参数干掉,这里我们使用 grep 去查找包含这个字符串的文件与其行数

grep -nr "\-lrt" tools/*

v2-463c3a19772e7de93685662d718979db_720w.png?source=d16d100b

可以看到这就找出来了,我们使用 vim 去编辑

vim tools/v8_gypfiles/v8.gyp

(ps:Esc 后输入行数 + G,可用快速跳转到这一行)

最终我们在 1244 行找到了,因为上面写的很清楚,包含在 'is_android' 中(不要改错了)

我们将

'libraries': [
  '-ldl',
  '-lrt'
]

改成

'libraries': [
  '-ldl'
]

然后保存并退出

第五个问题如图:

v2-3ef42e363c06847c86e07adf9ec943ea_720w.png?source=d16d100b

这里是在跑测试的时候报错了,我们只需要把这个文件改成空文件即可

这并不影响 nodejs 的运行,这个测试的是 crypto

echo "" > test/cctest/test_crypto_clienthello.cc

下一步我们要运行配置生成,也就是调用 android-configure 文件

./android-configure /root/ndk 24 aarch64

这里的参数分别进行解释:

第一个参数是 Android NDK 文件夹的路径

第二个参数是目标版本(targetSdkVersion),不能低于 24

第三个参数是目标平台,可选 aarch64(arm64) arm x86 x86_64

下一步就是编译源码了(

我们通过 make 进行编译,-j 参数指定线程数(一般设置成 8 就行了)

make -j8

编译完成后会在 /root/node/out/Release 里面生成一些文件

我们只需要 nodelibnode.so/system/lib/libc++_shared.so 这三个文件即可

我们先退出容器

exit

使用 docker ps -a 查看下这个容器的 id

docker ps -a

v2-86191d10731dbc1133324b015de49631_720w.png?source=d16d100b

使用 docker cp 将容器中的的文件复制到本地

docker cp 容器ID:/root/node/out/Release/node .
docker cp 容器ID:/root/node/out/Release/libnode.so .
docker cp 容器ID:/system/lib/libc++_shared.so .
# 可选 torque
docker cp 容器ID:/root/node/out/Release/torque .

本章所用到的 libandroid-node-support 我也放到了 Github

libandroid-node-support 到此本篇文章就结束了~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值