当zig-lang构建系统遇上鸿蒙

409 阅读6分钟

本文我们将简单尝试下在鸿蒙上使用 zig 的构建系统来实现原生模块的构建。

重要:本文涉及的技术和能力均处于实验性质,没有经过任何严格测试,生产环境慎用!

本文示例代码在 github.com/richerfu/ha…

一、zig-lang

zig 作为一门新兴的语言,在很多地方都展现了其过人的设计之处,并且逐渐进入到大众视野中。其中现阶段最有名的莫过于使用 zig 编写的 Bun(JavaScript Runtime),以其丰富的能力和高性能逐渐被广大 JSer 所接受和使用。

而对于一些其他语言的开发来说,zig 最具有吸引力的则是它零依赖的,开箱即用的 C/C++ 交叉编译能力了,也就是我们在很多地方能够看到的:zig 构建系统

体会过 node-gyp 或者是 CGO 之类的需要编译原生 C/C++ 代码的读者都应该深有体会,当我们在不同的平台上面对 C/C++ 编译环境的痛苦之处。

比如在 Windows 系统上面编译很多语言或者项目的编译环境通常需要我们安装宇宙最强 IDE -- Visual Studio 或者安装其专用构建工具:Microsoft C++ Build Tools。

而安装过的同学都应该知道,这个 IDE 一旦安装之后想要完全卸载的最好选择是:重装系统。因此对于我们非 C/C++ 专业开发同学来说,一个干净、即装即用、无依赖的构建工具或者环境成为了一个非常迫切的需求。

二、体验 zig 构建系统

这一部分我们将基于 Rust 来简单体验下 zig 给我们带来的便捷交叉编译体验。

笔者的本机设备为 Mac(M2 Max) ,后续相关的代码或者例子均在该设备确保能够运行。其他环境可以自行编译尝试

我们新建一个最简单的打印Hello world的 Rust 项目,我们将在 mac 设备上面尝试交叉编译到 arm64 位的 linux 平台下。

首先我们需要为 Rust 安装对应的目标产物。

rustup target add aarch64-unknown-linux-gnu

紧接着我们直接通过 cargo 尝试编译该项目。

cargo build --target aarch64-unknown-linux-gnu

我们会发现编译是不会成功的,我们看到了如下的报错:

17208366000869.jpg

很明显,我们当前环境并没有能够提供给该目标产物的构建工具或者环境。通常来说,我们的解决方案是在本机安装一些目标平台的构建工具或者环境,比如这里我们可能需要安装 arm64 版本 Linux 下的 gcc 来提供给 rustc 以构建对应平台的产物。

比如在 mac 上面我们可以通过brew进行安装:

brew tap messense/macos-cross-toolchains
# install aarch64-unknown-linux-gnu toolchain
brew install aarch64-unknown-linux-gnu

当然这样能解决问题是完全 ok 的,但是我们会遇到一个问题,随着我们需要编译的目标平台越来越多,我们需要安装的环境也越来越多。且不说环境安装对本机空间的占用,各个环境之间的隔离也变得难以把控。

我们迫切的希望有一个 all in one 的解决方案,我们刚才已经讲过了 zig 的构建系统能够为我们带来更加方便快捷的构建能力,而在 Rust 生态中则有 cargo-zigbuild 基于 zig 为我们提供了上层优秀的交叉编译能力。

现在我们基于 cargo-zigbuild 来体验 zig 带来的优秀编译能力。当然在此之前,我们需要安装 zig-lang 到我们的系统中来。在 mac 上面可以直接使用brew进行安装,其他平台的安装可以参考官方文档即可。

brew install zig

然后我们只需要通过 cargo 安装 zigbuild 提供的命令行工具即可。

cargo install cargo-zigbuild

紧接着着我们只需要将构建命令从原来的cargo build --target xxx修改成如下所示即可:

cargo zigbuild --target aarch64-unknown-linux-gnu

现在我们发现一件很神奇的事情,我们在没有安装任何 arm64 位 Linux 所需的工具或者包就完成了该平台的交叉编译。

17208373281412.jpg

这就是 zig 为我们带来的神奇魔法,接下来我们将会尝试将这个神奇的魔法带入到鸿蒙的生态中来尝试改善我们的一些日常开发体验。

三、zig for harmony

笔者在之前的一篇文章中有讲到,zig 在 0.13 的版本中已经增加了对 OpenHarmony 的支持,不过那个支持只允许我们构建可执行文件等到 OpenHarmony 系统,对于我们前文中提到的 zig 交叉编译能力支持性可能并没有那么好(主要在 zig cc 能力上)。

我们参考 zig 官网的例子来创建一个项目并且将其构建为动态链接库,当构建当前设备产物时完全没有任何问题。

17208379877707.jpg

已经构建成了 mac 系统上面动态链接库的产物,我们尝试构建成 OpenHarmony 的产物时,发现也是可以正常编译了。

17208390658377.jpg

到这里是不是你跟我一样以为 zig 支持性这么好,完全可以直接拿来用了,正当我们满心欢喜准备使用 zigbuild 来构建鸿蒙的时候,我们将会迎来当头一棒。

17208393463718.jpg

什么?居然构建失败了?疯狂报错?

是的,目前我们没办法直接使用 zig 做为交叉编译的工具,因为 zig 的交叉编译实际上执行的命令是zig cc而该命令目前并没有对鸿蒙进行适配,因为会报错说找不到对应的 libc 目标。

这也是笔者近两个月的一些适配工作,具体可以参照该 PR

目前只能通过源码构建出当前平台的方式来实验性的使用该能力,笔者提供了一个 Mac M 芯片的构建产物压缩包在示例代码仓库中可以找到。

本机构建可以参考官网的 指导 ,这里不再做过多赘述。

构建完成或者下载压缩包之后,我们只需要放在任何我们想要放的位置,然后将 zig 配置到我们的环境变量中即可。

比如在我的设备上,其目录结构和环境变量设置如下所示:

17208399181753.jpg

现在我们再尝试来使用 zigbuild 构建下。

17208399753098.jpg

将构建产物在系统中调用验证,可以看到已经完全正常运行了。

17208401635322.jpg

四、尾

本文主要是简单讲解和演示如何使用 zig 来简化我们的交叉编译等工作,并且简单介绍了下在鸿蒙平台上面的一些适配工作和使用。

目前相关的工作仍然在进行之后,随着越来越多的语言或者生态适配鸿蒙,能够给开发者带来更多的想象力,以及提升效率和开发舒适度的空间。

有兴趣的读者可以自行进行一些尝试,感谢阅读~