Flutter你想要的热更新之编译构建 engine
本章目的是构建获得一个上一章节中修改后的 Flutter.framework 。
1. Flutter.framework
在 iOS 的 Flutter 项目中 Flutter.framework 是 Flutter 应用执行的基础。
1.1 本地 Flutter.framework
通常情况下在创建 Flutter 项目不需要自己构建 Flutter.framework,因为 Flutter 环境中自带了各种模式(debug,release,profile)下需要的 Flutter.framework ,这些 framework 位于本地环境:
1
$FLUTTER_ROOT/bin/cache/artifacts/engine
在 iOS App 构建时,会执行 xcode_backend.sh 根据构建类型将对应的 framework 拷贝到当前工程。xcode_backend.sh 位于本地环境:
1
$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh。
1.2 构建 Flutter.framework
Flutter.framework 是通过构建 engine 后的生成的。但是普通 Flutter 项目是不包含 engine 构建部分的,两者是分开的,也就是说要获得修改后的 Flutter.framework,需要先自行构建 engine,然后再将其集成到现有的 Flutter 工程中。
2. engine 的构建
2.1 构建环境的搭建
Flutter 官方 wiki 提供了各个平台搭建构建 engine 环境的详细文档。
因为本文主题是 Flutter 在 iOS 上的热更新,所本节主要介绍在 Mac 上 engine 构建环境的搭建及常见的问题。
2.1.1 依赖工具
- git:源代码管理( 2.x.x 以上版本,gclient 源码同步工具中使用到的部分 git 命令 1.x.x 不支持 )。
- ssh:Mac 系统自带。
- Python:用于源码同步及构建( 作者使用 2.7.x )。
- unzip:解压工具。
- curl:文件下载工具。
- depot_tools:gclient 工具,安装方式:
1 2
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git echo 'export PATH=$PATH:"替换成本地克隆的depot_tools仓库路径"' >> ~/.bashrc
确认 depot_tools 环境:
1
gclient --version
- Xcode:最新版本的 Xcode
- IDE(可选):开发调试用,官方推荐 Android Studio with the Flutter plugin,或者其他 IDE(Emacs,Vim,Neovim,Visual Studio Code,Nuclide) + cquery 代码自动不全插件。
2.1.2 设置并同步构建环境
- fork engine 仓库: 在自己 github 账户中 fork https://github.com/flutter/engine ,如果自己的 github 仓库中已有 frok 的 engine 仓库,请确保主分支与官方同步。
- 配置 github ssh 访问: 配置自己 github 账户的 ssh 访问,确保自己的 github 账户及本地主机已经设置了 ssh 密钥。如果没有设置,参考 generating-ssh-keys 。
- 创建
engine文件夹: 创建一个空文件夹并命名为engine,用来存放下载的源码和工具仓库。为了简单起见,最好不要使用其他名称。 - 创建
.gclient文件: 在engine目录下创建一个.gclient文件:,.gclient文件内容如下:1 2 3 4 5 6 7 8 9 10
solutions = [ { "managed": False, "name": "src/flutter", "url": "[email protected]:替换成你的githua账户/engine.git", "custom_deps": {}, "deps_file": "DEPS", "safesync_url": "", }, ] - 执行
gclient sync: 在engine目录中(也就是.gclient文件所在的目录),执行gclient sync。
- 国内
gclient sync需要 vpn,这个过程取决于网络环境,时间可能会比较长,gclient sync -v打印详细同步信息。 - 整个源码体积很大,环境同步前磁盘剩余空间最好在 20G 以上。
- 官文提示:命令将获取 Flutter 依赖的所有源文件。避免中断这个命令,中断命令可能会使存储仓库处于一个不稳定的状态,清理这个不稳定状态会非常繁琐。(,这个过程会自动执行
git clone等操作)。作者中断了几次也没出现什么问题。
- 国内
- (可选)本地 engine 添加 upstream 为官方仓库: 添加 upstream 为官方仓库后,通过
git fetch命令就会拉去官方最新版本代码,而不是自己 github 中 fork 的 engine 代码。在engine/src/flutter目录中执行:1
git remote add upstream [email protected]:flutter/engine.git
- (可选)安装 Oracle 的 Java JDK:用于 Android Flutter engine 构建。
- (可选)安装 ant:用于 Android Flutter engine 构建。
1
brew install ant
2.1.3 构建环境目录说明
- engine/src:构建工具根路径,是一个 git 仓库,对应远程仓库
https://github.com/flutter/buildroot.git。 - engine/src/flutter:Flutter engine 源码仓库,对应自己 github 账户上 fork 的 engine 仓库。
这就是我们要修改并构建获得 Flutter.framework 的 engine 仓库。
2.1.4 构建环境搭建的常见问题
- 国内如果使用
gclient sync同步构建环境失败,尝试使用 vpn ,并设置终端 http 代理。
使用 socket 作为 http 代理时,会遇到下面的错误:1
[P18720 13:37:26.485 client.go:310 W] RPC failed transiently. Will retry in 1s {"error":"failed to send request: Post https://chrome-infra-packages.appspot.com/prpc/cipd.Repository/ResolveVersion: dial tcp 173.252.100.21:443: i/o timeout", "host":"chrome-infra-packages.appspot.com", "method":"ResolveVersion", "service":"cipd.Repository", "sleepTime":"1s"}这是因为在
gclient sync同步中部分工具无法通过 socket 代理下载,请参考 用 polipo 把 shadowsocks 转为 http 代理 。安装并开启 polipo 后,设置 polipo 作为终端 http 代理
1
export http_proxy=http://localhost:8123
用 polipo 把 shadowsocks 转为 http 代理
#### 1. polipo 和 shadowsocks 简介
shadowsocks代理我想大家是耳熟能详了,在这里就不作过多的讲述.
不过有一点是需要指出的是,shadowsocks的1080代理端口的代理服务类型是传输层的socks代理.有些时候我们需要利用shadowsocks这个科学上网的隧道,同时需要HTTP代理的时候,我们就不得不想办法了.
我在这里就介绍另一款开源软件--polipo,一个小型快速的HTTP Web缓存代理服务器,还可以指定上级代理为socks类型.我们就利用这一点功能来实现我们的需求:
把shadowsocks的代理转换为http代理,让socks代理和http代理并行为我们提供科学上网服务.
这样尤其使得在unix-like系统中,很多命令行网络程序默认只能支持通过指定http_proxy环境变量来设置网络代理.这样利用polipo就把我们人人喜欢的shadowsocks服务科学上网功能扩展到http代理服务了.
#### 2. socks 转 http 代理需求和动机
这个功能在今天我更新WebRTC最新代码的时候,执行gclient sync命令的时候中间会有一部分网络下载不是通过git来更新的,所以设置git的socks代理也无效,那一部分是执行download_from_google_storage下载更新的,他是python的boto代码,不支持一般的代理环境变量http_proxy设置方法.只能在$HOME/.boto文件中定义HTTP代理配置.
先运行shadowsocks服务的客户端,开启科学上网功能,自动和全局无所谓.
#### 3. 安装 polipo
- Mac OS X平台安装
请确保您系统安装了brew,然后用brew命令来安装polipo软件包:
```bash
$ brew install polipo
```
就这样一条命令就可以安装好.
- Ubuntu 平台安装
Ubuntu Linux系统下安装方法如下:
```bash
$ apt-get install polipo
$ service polipo stop
```
安装好之后,就可以运行polipo并设置上级socks代理为shadowsocks端口,就成功把socks转换为http代理.如shadowsocks的本地端口一般为localhost:1080:
```bash
$ polipo socksParentProxy=localhost:1080
Established listening socket on port 8123.
```
#### 4. 设置 boto 配置文件
用户目录下新建文件$HOME/.boto,内容如下命令所示:
```bash
$ cat $HOME/.boto
[Boto]
proxy = 127.0.0.1
proxy_port = 8123
```
127.0.0.1:8123是polipo命令在本地运行的HTTP代理服务默认IP端口.
#### 5. 更新 WebRTC 代码
上面配置了boto的配置文件后,我们还需要导出一个环境变量,使该配置文件可以被识别生效:
```bash
$ export NO_AUTH_BOTO_CONFIG=$HOME/.boto
```
到这个时候,我们就可以继续执行gclient sync来更新WebRTC的所需chromium代码仓库了.
如果不导出这个NO_AUTH_BOTO_CONFIG环境变量指向.boto配置文件的位置的话,就会在更新WebRTC代码的中间download_from_google_storage时出现如下警告提示:
```
________ running 'download_from_google_storage --no_resume --platform=darwin --no_auth --bucket chromium-gn -s src/buildtools/mac/gn.sha1' in '/Users/apple/opensource/webrtc_build/webrtc2016/src/chromium'
NOTICE: You have PROXY values set in your environment, but gsutil in depot_tools does not (yet) obey them.
Also, --no_auth prevents the normal BOTO_CONFIG environment variable from being used.
To use a proxy in this situation, please supply those settings in a .boto file pointed to by the NO_AUTH_BOTO_CONFIG environment var.
```
#### 6. 其他 polipo 转 http 代理的使用
```
http_proxy=http://localhost:8123 apt-get update
http_proxy=http://localhost:8123 curl www.google.com
http_proxy=http://localhost:8123 wget www.google.com
git config --global http.proxy 127.0.0.1:8123
git clone https://github.com/xxx/xxx.git
git config --global --unset-all http.proxy
```
- 整个源码体积很大,环境同步前磁盘剩余空间最好在 20G 以上。
2.2 本地构建 engine
- 切换 engine 版本:切换到 Flutter 1.0.0 对应的 engine 版本。
1 2 3 4
#进入 engine 仓库目录 cd engine/src/flutter #切换 engine 版本 git checkout 7375a0f414bde4bc941e623482221db2fc8c4ab5
- 同步构建环境
1 2 3 4
#进入构建环境目录 cd engine #同步构建环境 gclient sync
- 生成构建文件
1 2 3 4
#进入 src 目录 cd engine/src #生成构建文件(分别生成真机构建文件,模拟器构建文件和服务端构建文件) ./flutter/tools/gn --ios --unoptimized && ./flutter/tools/gn --ios --simulator --unoptimized && ./flutter/tools/gn --unoptimized
- 编译
1 2 3 4
#进入 src 目录 cd engine/src #编译(分别编译真机文件,模拟器文件和服务端文件) ninja -C out/ios_debug_unopt && ninja -C out/ios_debug_sim_unopt && ninja -C out/host_debug_unopt
3.使用本地构建的 engine
- 创建 Flutter App
1
flutter create myapp
- 修改 myapp/pubspec.yaml 文件
在文件末尾追加:1 2 3 4 5
dependency_overrides: sky_engine: path: /path/to/flutter/engine/out/host_debug/gen/dart-pkg/sky_engine sky_services: path: /path/to/flutter/engine/out/host_debug/gen/dart-pkg/sky_services
修改
path:为 ios_debug_sim_unopt (真机为 ios_debug_unopt) 中 sky_engine 和 sky_services 的路径,如:1 2 3 4 5
dependency_overrides: sky_engine: path: /Users/guhaijun/Desktop/flutter_engine/engine/src/out/ios_debug_sim_unopt/gen/dart-pkg/sky_engine sky_services: path: /Users/guhaijun/Desktop/flutter_engine/engine/src/out/ios_debug_sim_unopt/gen/dart-pkg/sky_services
- 设置 FLUTTER_ENGINE 环境变量
在终端执行或修改XCode工程在XCode —> TARGETS -> Runner -> Build Phases -> Run Script的首行插入1
export FLUTTER_ENGINE=/path/to/engine/src
环境变量 FLUTTER_ENGINE 为
engine/src路径,根据当前环境路径修改,如:1
export FLUTTER_ENGINE=/Users/guhaijun/Desktop/flutter_engine/engine/src
flutter_tool 的一个
bug:在使用本地engine时,XCode工程缺少对--local-engine-src-path或$FLUTTER_ENGINE的获取和处理,导致 Flutter 的Xcode工程构建失败。
错误提示:
```
Launching lib/main.dart on iPhone XR in debug mode...
Starting Xcode build...
├─Assembling Flutter resources... 0.7s
Xcode build done. 2.7s
Failed to build iOS app
Error output from Xcode build:
↳
** BUILD FAILED **
Xcode's output:
↳
=== BUILD TARGET Runner OF PROJECT Runner WITH CONFIGURATION Debug ===
Unable to detect local Flutter engine build directory.
Either specify a dependency_override for the sky_engine package in your pubspec.yaml and ensure --package-root is set if necessary,
or set the $FLUTTER_ENGINE environment variable, or use --local-engine-src-path to specify the path to the root of your
flutter/engine repository.
Failed to package /Users/guhaijun/Desktop/flutter/engine_test/myapp.
Command /bin/sh failed with exit code 255
Could not build the application for the simulator.
Error launching application on iPhone XR.
2.0s
``` - 运行 Flutter App
1
flutter run --local-engine-src-path=/path/to/engine/src --local-engine=ios_debug_sim_unopt
–local-engine-src-path 为
engine/src路径,根据当前环境路径修改,如:1
flutter run --local-engine-src-path=/Users/guhaijun/Desktop/flutter_engine/engine/src --local-engine=ios_debug_sim_unopt




近期评论