1. 介绍
本文打算从环境配置,获取源代码,编译,测试,使用五个方面初步描述了 LoongArch 架构下 Electron 的交叉编译。由于chromium版本更新速度极快,且对C++新特性的应用较激进,本文档使用的 clang/llvm 落后于官方所提供的版本,存在部分编译参数不兼容的问题。
本文主要参考Electron官方文档中 构建说明 和 构建步骤(Linux) 。
2. 编译环境准备
由于本地环境千差万别,Electron的编译所需依赖也比较复杂,为了不让Electron的编译大计毁于配置环境这一步,所以决定偷懒使用官方提供的docker镜像,这样可以避免编译过程中大部分环境上的问题,且不用当心依赖的版本问题,代价是需要学会几条 docker 命令。
Electron官方提供了编译环境的docker镜像:https://github.com/electron/build-images/pkgs/container/build
由于官方提供的clang/llvm 目前并不支持 LoongArch 架构,所以还得准备一套支持 LoongArch架构的编译工具。
LoongArch llvm-project源码仓库:https://github.com/loongson/llvm-project.git
2.1 安装docker
安装docker这一步,有大量优质且易懂的文章进行说明,可以参考以下链接中的安装方式,这里不再赘述。
docker安装参考:https://yeasy.gitbook.io/docker_practice/install
2.2 获取构建环境镜像
此镜像由Electron官方仓库中的 build-images 子项目提供
1 | $ docker pull ghcr.io/electron/build:latest |
接下来除了测试等操作,都编译过程都将在docker内完成
2.3 编译 clang/llvm
Electron目前默认使用clang/llvm进行编译,现在
1 | $ sudo apt update |
2.4 获取交叉工具链的链接器
由于系统的链接器无法链接loongarch64架构的二进制,手动制作一个交叉工具链比较麻烦,这里再次偷懒用 loongson/build-tools 里面带的交叉工具链的链接器。
1 | $ wget https://github.com/loongson/build-tools/releases/download/2022.05.29/loongarch64-clfs-5.0-cross-tools-gcc-glibc.tar.xz |
1 | # 查看动态库搜索路径 |
完成上面一步几个配置,基本上Electron的编译环境就已经搭建好了,接下来就可以拉取代码,然后编译Electron了。
3. 拉取代码
拉取代码可以通过官方文档提供的方法来获取,也可以使用Electron官方仓库中的 build-tools (此build-tools非上面那个下载交叉工具链和clfs系统的build-tools,虽然他们名字相同,是不同的项目)子项目中的工具来完成代码的获取。
既然有更好用的工具来获取代码,当然应该果断选择使用坑更少的路。接下来将使用build-tools 工具来拉取代码。
3.1 安装 build-tools
1 | #本地安装 build-tools |
3.2 设置代理
Electron本身代码托管于github上,但是Electron依赖 Chromium 源码,需要一个稳定的代理才能获取到源代码(第一次拉取代码大概需要 40G 左右流量)
1 | $ export ALL_PROXY="代理ip:端口" |
3.3 拉取代码
拉取 Electron 代码使用官方提供的 build-tools 工具,这个工具默认将 GIT_CACHE_PATH 环境变量设置到用户家目录的 .git_cache 目录(–> 参考build-tools实现代码)。如果需要将git_cache 缓存放在其他目录,只需要对 GIT_CACHE_PATH 进行设置即可。
使用 git_cache 只要完整获取一次代码后,后续其他版本也可以使用这个缓存,不用每次都要去上游完整拉取代码,大大节约了时间和流量。
以下提供简单使用方法,更详细参考官方仓库README
1 | # 第一次使用会去google拉取 depot_tools,需要代理,且需要较长时间 |
3.4 部分报错及解决方法
- 由于使用环境变量设置代理导致npm安装包报错 解决方法:
1
2
3
4
5________ running 'python3 -c import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python3", "script/lib/npx.py", "yarn@1.15.2", "install", "--frozen-lockfile"]);' in '/home/builduser/Electron_v19.x.y'
npm ERR! code ERR_INVALID_URL
npm ERR! Invalid URL
npm ERR! A complete log of this run can be found in:
npm ERR! /home/builduser/.npm/_logs/2022-06-20T09_37_12_695Z-debug-0.log1
2
3
4
5
6
7
8
9
10# 暂时取消代理,安装完依赖再配置依赖
$ pushd Electron_v19.x.y/src/electron/
$ unset http_proxy
$ unset https_proxy
$ python3 script/lib/npx.py yarn@1.15.2 install --frozen-lockfile
$ popd
# 重新设置代理,并重新执行sync获取代码,由于之前下载的代码都缓存到了.git_cache,速度会快很多
$ export http_proxy="ip:port"
$ export https_proxy="ip:port"
$ ./node_modules/.bin/e sync -vvvv
4. 编译及打包 Electron
成功使用docker配置好编译环境并且获取到完整的Electron源码及依赖后,接下来将对源码进行交叉编译。这里需要有几点进行说明:
- Electron中并非使用la64 或者loongarch64作为架构名称,而是 loong64,这个是由于v8源码进入上游时决定的。参考:https://chromium-review.googlesource.com/c/v8/v8/+/3089095
- 目前暂时没有合适的系统(debian/ubuntu系列)支持上游最新版本的内核,导致 clang/llvm 交叉编译使用的 sysroot 当前还无法通过官方方法制作,所以暂时使用 https://github.com/loongson/build-tools 提供的 loongarch64-clfs-system-5.0.tar.bz2 (不局限于这个版本,社区版本系统高速迭代中,尽可能使用最新clfs系统0.0)
- 交叉编译使用clang/llvm版本问题,目前 https://github.com/loongson/llvm-project 只提供了 llvm 11,Electron目前使用的版本是 llvm 15, Electron依赖的Chromium在C++新特性方面比较激进,这其中会有部分编译参数不支持和部分语法不支持的情况(类似constexpr相关)。
虽然有一些小问题,但是这些都是可以解决的,不过出现一些warning是不可避免的-_-。
接下来把工作目录切换到 Electron_v19.x.y/src 进行一些简单的配置即可开始编译了。
1 | # 切换到编译目录 |
编译配置electron/build/args/release.gn 如下所示
1 | $ cat electron/build/args/release.gn |
配置好编译参数后,开始编译
1 | $ export LC_ALL="C.UTF-8" |
编译过程到此就结束了,成功得到dist.zip, hunspell_dictionaries.zip,mksnapshot.zip, chromedriver.zip 和 ffmpeg.zip等几个包后,如何使用参考本文的第五部分Electron仓库制作和使用
5. 测试Electron
交叉编译完成后,到loongarch架构机器中,普通用户(非root用户)目录下创建如下结构形式的目录
1 | $ mkdir -pv electron_v19.x.y/out/Release |
将dist.zip 解压到 electron_v19.x.y/out/Release/ 目录下, 然后进入electron 目录,按照如下方式安装依赖:
1 | # 默认系统中的python是python3,安装测试软件 |
由于测试时自动安装的脚本存在一点问题,上面已经手动安装好了测试环境,测试时脚本会需要修改 script/spec-runner.js,需要注释掉安装依赖的两行,参照下面链接 https://github.com/electron/electron/issues/22432#issuecomment-593000264
去掉 installSpecModules 函数处理 spec 和 spec-main 目录的依赖安装。也就是上面手动进入到 spec和spec-main 里面执行yarn命令。
接下来是运行测试程序:
需要接入屏幕,远程通过ssh会 “[13035:1230/101247.042264:FATAL:ozone_platform_x11.cc(238)] Check failed: x11::Connection::Get()->Ready(). Missing X server or $DISPLAY” 报没有 X server
1 | $ export ELECTRON_SKIP_NATIVE_MODULE_TESTS=true |
设置 ELECTRON_SKIP_NATIVE_MODULE_TESTS 环境变量参考配置CI测试的 arm 架构 .circleci/build_config.yml 第1126 行,此环境变量可以跳过部分导致软件crash的测试项。
linux 中由于屏幕缩放问题导致较多测试不通过,不过并不影响使用。
由于浮点数精度误差,某些依赖于精确像素测量的测试可能无法正常在Hi-DPI屏幕的设备上工作。 为了使这些测试能正常运行,请确保设备的缩放比为100%。
参考:https://www.electronjs.org/zh/docs/latest/development/testing#pixel-measurements
6. Electron仓库制作和使用
通过上述方法编译完成Electron得到一堆zip包,而安装这些包需要一个还需要一点小小的配置。
- 需要一个存放Electron的zip包的仓库
- 需要在安装的机器上设置一些环境变量来指向我们自己的仓库
6.1 制作一个Electron二进制仓库
在交叉编译的src目录下执行如下脚本,即可在out/目录下得到一个v19.0.6的文件夹。实际上只是重命名了生成的包,然后生成sha256sum
1 | # 重命名生成的zip包,并生成文件哈希 |
执行完上面的脚本后,将out/目录下得到的v19.0.6文件夹放到一个http服务器上即可参照下面的配置进行安装了。
也可以按照 https://registry.npmmirror.com/binary.html?path=electron/&spm=a2c6h.24755359.0.0.6d444dcchV4p85 镜像仓库的结构制作即可
6.2 安装方法
安装自己的Electron需要设置两个变量
- ELECTRON_MIRROR: 用于指向存放二进制zip包的地址目录,最后的“/”不能去掉
- electron_use_remote_checksums:配置使用远程的 SHASUMS256.txt 进行校验还是使用npm包中自带的进行校验(由于npm包中自带的只有官方包的哈希值,自己搭建的镜像中只能使用远程SHASUMS256.txt进行校验),该环境变量是Electron v15开始引入。
6.2.1 不设置环境变量进行安装
1 | # 全局安装 |
6.2.2 设置环境变量进行安装
1 | $ export ELECTRON_MIRROR=http://xxx.xxx/xxx/ |