1. 前言
flutter的下载参考前一篇文章,flutter源码下载。
源码下载结束后,最好使用gclient切换stable版本,比较稳定,这样使用自定义编译器修改的缺陷最少。
2. 准备编译环境
2.1 确定sysroot
sysroot是指你的编译器的sysroot,编译器的sysroot可以通过命令打印出来:
arm-linux-gnueabihf-gcc --print-sysroot
到时候编译不过,可能需要在sysroot路径的下的lib中新增内容,这里不建议直接修改sysroot,影响原生编译器运行,所以拷贝一份sysroot进行备份。
cp `arm-linux-gnueabihf-gcc --print-sysroot` ~/sysroot/arm-linux-gnueabihf
如果你的编译器运行 使用参数--print-sysroot
没有打印,可以使用 -v
找找--sysroot=dir
对应的dir,如果还是没有,可以直接找到编译器的安装目录,去查找类似linux根目录(路径下包含bin, lib, usr等目录)的路径。如编译器gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf.tar.gz,我安装在toolchains(相对路径)目录,那么他的sysroot就是:toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc
.
2.2 创建clang软连接
直接修改 src/build/toolchain/custom/BUILD.gn最终还是编译不过,使用软连接方式即可
直接修改 src/build/toolchain/custom/BUILD.gn最终还是编译不过,使用软连接方式即可
直接修改 src/build/toolchain/custom/BUILD.gn最终还是编译不过,使用软连接方式即可
要么直接创建clang/clang++的软连接
ln -sf \
toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabih/bin/arm-linux-gnueabihf-gcc \
toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabih/bin/clang
ln -sf \
toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabih/bin/arm-linux-gnueabihf-g++ \
toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabih/bin/clang++
3. 编译
3.1 生成ninja编译脚本
进入到flutter引擎目录下的src目录,执行如下命令:
./flutter/tools/gn --target-os linux --linux-cpu arm \
--target-toolchain toolchains/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf \
--target-sysroot sysroot/gcc-linaro-12.0.1-2022.02-x86_64_arm-linux-gnueabihf \
--target-triple arm-linux-gnueabihf --runtime-mode release --arm-float-abi hard \
--embedder-for-target --disable-desktop-embeddings --no-build-embedder-examples \
--no-goma --no-clang --no-prebuilt-dart-sdk --no-build-glfw-shell \
--disable-desktop-embeddings
--target-os linux
表示目标系统是Linux
--target-cpu arm
表示目标板子的cpu是arm,如果是64位系统,则使用--target-cpu arm64
--target-toolchain
表示工具链的安装路径
--target-sysroot
表示编译器的sysroot,不同编译器的sysroot相对于编译器的相对路径不一样,所以需要额外指定
--target-tripple
表示编译器命令的前缀,编译结束后会使用 arm-linux-gnueabihf-strip
命令去掉libflutter_engine.so的符号表
--runtime-mode
表示运行模式,调试或者发布
--arm-float-abi hard
表示浮点运算使用硬浮点方式,性能比较高
--embedder-for-target
表示支持embedder嵌入式模式
--disable-desktop-emddings
表示不存在桌面系统,如果是移植到树莓派这种自带X11,wayland桌面图形的系统,开启该选项(个人猜测)
--no-build-embedder-examples
表示不编译相关的用例,如果没有--disable-desktop-emddings
选项,则可以删除该选项。(个人猜测)
--no-goma
表示google内部使用的分布式编译,我们没有,不需要
--no-clang
表示不用clang
--no-prebild-dart-sdk
表示没有预编译dart-sdk,所以本次编译会编译dartsdk
--no-build-glfw-shell
表示不编译glfw,因为没有用到
3.2 ninja编译
ninja -j16 -C out/linux_release_arm
3.3 编译报错处理
3.3.1 找不到freetype2和zlib依赖
具体报错信息忘了,看见类似的可以参考如下内容。
该错误需要在sysroot的/usr/lib/pkgconfig
目录中创建对应的freetype2.pc
和zlib.pc
。这是因为flutter用到了pkg-config
这个工具,pkg-config
工具能够直接生成编译依赖参数。比如pkg-config --cflag --libs freetype2
会直接生成 -I${freetype头文件路径} -L${libfreetype2.so所在路径} -L${依赖libz.so所在路径} -lz -lfreetype2
这样的cflags参数。至于pkg-config
为什么知道freetype2
依赖于zlib
,则是因为pkg-cofnig
会到/usr/lib/pkgconfig/
目录下解析freetype2.pc
文件,文件中会声明freetype2
依赖的库以及其头文件安装路径和库安装路径。
如果没有${sysroot}/usr/lib/pkgconfig
目录,则手动创建一个。
freetype2.pc内容如下,复制自flutter源码中的freetype2.pc并做修改:
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=/usr/include
Name: FreeType 2
URL: https://freetype.org
Description: A free, high-quality, and portable font engine.
Version: 23.1.17
Requires:
Requires.private: zlib, libpng
Libs: -L${libdir} -lfreetype
Libs.private:
Cflags: -I${includedir}/freetype2
zlib.pc如下,复制自flutter源码中的freetype2.pc并做修改:
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
sharedlibdir=${libdir}
includedir=${prefix}/include
Name: zlib
Description: zlib compression library
Version: 1.2.11
Requires:
Libs: -L${libdir} -L${sharedlibdir} -lz
Cflags: -I${includedir}
3.3.2 不识别编译参数
如:
-Wno-c99-designator
-Wno-implicit-int-float-conversion
-Wno-deprecated-copy
-Wno-non-c-typedef-for-linkage
-Wno-range-loop-construct
参数不识别导致编译报错,
修改flutter/src/build/config/compiler/BUILD.gn
文件, 注释不支持的编译参数
if (!use_xcode) {
default_warning_flags += [
"-Wno-unused-but-set-parameter",
"-Wno-unused-but-set-variable",
#"-Wno-implicit-int-float-conversion",
#"-Wno-c99-designator",
#"-Wno-deprecated-copy",
# Needed for compiling Skia with clang-12
"-Wno-psabi",
]
if (!is_fuchsia) {
default_warning_flags += [
#"-Wno-non-c-typedef-for-linkage",
#"-Wno-range-loop-construct",
]
}
}
3.3.3 编译警告导致编译报错
如果设置了-Werror
选项,所有编译警告都会报错,因此直接关了该选项,并设置-Wno-error
,同样修改flutter/src/build/config/compiler/BUILD.gn
文件,修改如下:
default_warning_flags += [
# Enables.
"-Wendif-labels", # Weird old-style text after an #endif.
#"-Werror", # Warnings as errors.
"-Wno-error",
# Disables.
"-Wno-missing-field-initializers", # "struct foo f = {0};"
"-Wno-unused-parameter", # Unused function parameters.
]
3.3.4 不支持-stdlib=libstdc++参数
修改flutter/src/build/config/compiler/BUILD.gn
文件,修改如下:
if (is_linux) {
if (!use_flutter_cxx) {
#cflags_cc += [ "-stdlib=libstdc++" ]
#ldflags += [ "-stdlib=libstdc++" ]
libs += [ "gcc" ]
}
}
其他编译错误:
unqualified call to std::move [-Wunqualified-std-cast-call]
解决:修改代码,将move替换为std:move- 一些未知未定义
解决:包含对应的头文件#include <memory>
,#include <cstring>
等等,都比较简单。 - constexpr造成的错误
解决:直接删除constexpr的错误