在前面編譯環境安裝,GNTools工具原理,Ninja編譯工具原理的理解,已經瞭解了Flutter Engine相關的一下概念,接下來,繼續分析執行編譯命令調用的命令,文件,和相關的邏輯,有與篇幅問題,只介紹相關的這些邏輯和構建的文件說明(紙上得來終覺淺,....),整個思惟架構打通了以後,剩下的就是時間問題,這個能夠克服。。。。。。。html
在開始分析GN
是怎麼產生Ninja
配置文件的流程,須要對一下的內容有一個加單的瞭解 !!! info "優勢"python
* 1.可讀性好
* 2.速度更快
* 3.修改gn 以後 構建ninja文件時候會自動更新
* 4.依賴分明
複製代碼
!!! info "兩種文件類型"linux
* BUILID.gn : 採用層級結構 文件根目錄下一般有一個BUILD.gn文件,該文件是全部的代碼模塊組裝的集合
* .gni :通常用來添加一些參數的配置,在gn文件中import這些文件或者裏面定義的變量參數值
複製代碼
GNTools 是一款構建系統,用於編譯大規模代碼生成ninja文件android
Ninja源代碼分析、優化、編譯系統ios
Flutter Engine Complie Engine編譯官方教程c++
使用不一樣的參數指定咱們準備要構建的flutter引擎支持的平臺(Windows,Linux,Mac,Android,IOS,Web,Embedder),在同一個平臺上支持不一樣的模式(debug,release,profile),接下來咱們怎麼玩這個系統在不一樣平臺上的支持庫,和同一平臺上的不一樣模式git
!!! info "預處理編譯文件不一樣平臺的編譯腳本"es6
* ./flutter/tools/gn --android --unoptimized for device-side executables.
* ./flutter/tools/gn --android --android-cpu x86 --unoptimized for x86 emulators.
* ./flutter/tools/gn --android --android-cpu x64 --unoptimized for x64 emulators.
* ./flutter/tools/gn --unoptimized for host-side executables, needed to compile the code.
* ./flutter/tools/gn --ios --unoptimized
* ./flutter/tools/gn --ios --simulator --unoptimized
* ./flutter/tools/gn --unoptimized
* python .\flutter\tools\gn --unoptimized
* web編譯[felt工具](https://github.com/flutter/engine/blob/master/lib/web_ui/dev/README.md)
複製代碼
經過這些上述的命令,跟蹤命令的執行過程:./flutter/tools/gn --android --unoptimized
,參加Flutter Engine 編譯模式github
flutter/tools/gn
python腳本下列代碼--android
指定平臺--android-cpu x86
cpu架構--unoptimized
是否須要優化執行下列腳本主要是在構建GN
構建腳本參數:web
SRC_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
/* 根據傳入的參數判斷平臺的輸出路徑 */
def get_out_dir(args):
if args.target_os is not None:
target_dir = [args.target_os]
else:
target_dir = ['host']
........
return os.path.join(args.out_dir, 'out', '_'.join(target_dir))
def to_command_line(gn_args):
def merge(key, value):
if type(value) is bool:
return '%s=%s' % (key, 'true' if value else 'false')
return '%s="%s"' % (key, value)
return [merge(x, y) for x, y in gn_args.iteritems()]
def cpu_for_target_arch(arch):
if arch in ['ia32', 'arm', 'armv6', 'armv5te', 'mips',
'simarm', 'simarmv6', 'simarmv5te', 'simmips', 'simdbc',
'armsimdbc']:
return 'x86'
if arch in ['x64', 'arm64', 'simarm64', 'simdbc64', 'armsimdbc64']:
return 'x64'
def to_gn_args(args):
gn_args = {}
# Skia GN args.
gn_args['skia_enable_flutter_defines'] = True # Enable Flutter API guards in Skia.
gn_args['skia_use_dng_sdk'] = False # RAW image handling.
gn_args['skia_use_sfntly'] = False # PDF handling depedency.
...............
return gn_args
def parse_args(args):
args = args[1:]
parser = argparse.ArgumentParser(description='A script run` gn gen`.')
parser.add_argument('--unoptimized', default=False, action='store_true')
parser.add_argument('--runtime-mode', type=str, choices=['debug', 'profile', 'release'], default='debug')
..........
return parser.parse_args(args)
def main(argv):
args = parse_args(argv)
if sys.platform.startswith(('cygwin', 'win')):
subdir = 'win'
elif sys.platform == 'darwin':
subdir = 'mac-x64'
elif sys.platform.startswith('linux'):
subdir = 'linux-x64'
else:
raise Error('Unknown platform: ' + sys.platform)
command = [
'%s/buildtools/%s/gn' % (SRC_ROOT, subdir),
'gen',
'--check',
]
if sys.platform == 'darwin':
# On the Mac, also generate Xcode projects for ease of editing.
command.append('--ide=xcode')
if sys.platform.startswith('win'):
# On Windows, also generate Visual Studio project for ease of editing.
command.append('--ide=vs')
gn_args = to_command_line(to_gn_args(args))
out_dir = get_out_dir(args)
print "gn gen --check in %s" % out_dir
command.append(out_dir)
command.append('--args=%s' % ' '.join(gn_args))
gn_call_result = subprocess.call(command, cwd=SRC_ROOT)
print command [1]
if gn_call_result == 0:
# Generate/Replace the compile commands database in out.
compile_cmd_gen_cmd = [
'ninja',
'-C',
out_dir,
'-t',
'compdb',
'cc',
'cxx',
'objc',
'objcxx',
'asm',
]
print compile_cmd_gen_cmd [2]
調用`GN`生成構建文件
contents = subprocess.check_output(compile_cmd_gen_cmd, cwd=SRC_ROOT)
compile_commands = open('%s/out/compile_commands.json' % SRC_ROOT, 'w+')
compile_commands.write(contents)
compile_commands.close()
return gn_call_result
if __name__ == '__main__':
sys.exit(main(sys.argv))
複製代碼
./flutter/tools/gn --android --unoptimized
經過調用下面的命令查找當前目錄下的.ng
文件開始分析整個源碼項目的依賴樹
command = [
'%s/buildtools/%s/gn' % (SRC_ROOT, subdir),
'gen',
'--check',
]
複製代碼
在引擎的目錄下engine/src
查找入口的.gn
文件,使用src/tools/gn
工具查找根目錄樹下的源文件樹和開始配置數據
# The location of the build configuration file.
buildconfig = "//build/config/BUILDCONFIG.gn"
# The secondary source root is a parallel directory tree where
# GN build files are placed when they can not be placed directly
# in the source tree, e.g. for third party source trees.
secondary_source = "//build/secondary/"
# The set of targets known to pass 'gn check'. When all targets pass, remove
# this.
check_targets = [
"//dart/*",
"//flow/*",
"//flutter/*",
"//glue/*",
"//mojo/*",
"//skia/*",
"//sky/*",
]
複製代碼
[1] 處使用打印命令輸出這些構建命令生成的參數類型,經過查看生成的命令行參數,就可以理解在Flutter Engine 編譯模式提到的不一樣模式,是怎麼組織代碼和相關的編譯文件相關的內容,基本的思路和框架理解了以後,接下來就是GN
工具調用BUILD.gn
相關的文件,提供給Ninja去編譯的文件 [2] 處構建的命令
['ninja', '-C', 'out/android_debug_unopt', '-t', 'compdb', 'cc', 'cxx', 'objc', 'objcxx', 'asm']
複製代碼
在[1]構建的命令中指定使用的GN
路徑'buildtools/mac-x64/gn'
接着會調用執行/engine/src# ./flutter/tools/gn
的Build.gn文件engine/src/BUILD.gn
,會根據當前目錄中的BUILD.gn
文件配置一層一層的目錄去查找指定的目錄中的BUILD.gn
,文件每個目錄中都會定義當前目錄編譯的規則和依賴參數,因此能夠理解爲一顆倒掛的樹:從葉子結點開始配置,配置父節點,若是須要添加新的功能模塊,就在上一級模塊中把下一級的BUILD.gn
文件引用就可以向下包含須要的文件依賴。最終生成ninja
的配置文件。
/* This target will be built if no target is specified when invoking ninja. */
group("default") {
testonly = true
deps = [
"//flutter",
]
}
group("dist") {
testonly = true
deps = [
"//flutter:dist",
]
}
複製代碼
OS
,CPU
,編譯工具鏈
在engine/src/build/config/BUILDCONFIG.gn
文件中主要配置內容:
# Set the root of the engine project.
flutter_root = "//flutter"
複製代碼
使用的變量
- host_os, host_cpu, host_toolchain
- target_os, target_cpu, default_toolchain
- current_os, current_cpu, current_toolchain.
複製代碼
declare_args() {
# How many symbols to include in the build. This affects the performance of
# the build since the symbols are large and dealing with them is slow.
# 2 means regular build with symbols.
# 1 means minimal symbols, usually enough for backtraces only.
# 0 means no symbols.
# -1 means auto-set (off in release, regular in debug).
symbol_level = -1
# Component build.
is_component_build = false
# Official build.
is_official_build = false
# Debug build.
is_debug = true
# Whether we're a traditional desktop unix.
is_desktop_linux = current_os == "linux" && current_os != "chromeos"
# Set to true when compiling with the Clang compiler. Typically this is used
# to configure warnings.
is_clang = current_os == "mac" || current_os == "ios" ||
current_os == "linux" || current_os == "chromeos"
# Compile for Address Sanitizer to find memory bugs.
is_asan = false
# Compile for Leak Sanitizer to find leaks.
is_lsan = false
# Compile for Memory Sanitizer to find uninitialized reads.
is_msan = false
# Compile for Thread Sanitizer to find threading bugs.
is_tsan = false
# Compile for Undefined Behavior Sanitizer.
is_ubsan = false
if (current_os == "chromeos") {
# Allows the target toolchain to be injected as arguments. This is needed
# to support the CrOS build system which supports per-build-configuration
# toolchains.
cros_use_custom_toolchain = false
}
# DON'T ADD MORE FLAGS HERE. Read the comment above.
}
複製代碼
Windows,Linux,Mac,Android,IOS,Web,embedder
f (current_os == "mac") {
is_android = false
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = true
is_posix = true
is_win = false
} else if (current_os == "android") {
is_android = true
is_chromeos = false
is_fuchsia = false
is_fuchsia_host = false
is_ios = false
is_linux = false
is_mac = false
is_posix = true
is_win = false
}
............
複製代碼
import("//build/toolchain/custom/custom.gni")
# Define this to allow Fuchsia's fork of harfbuzz to build.
# shlib_toolchain is a Fuchsia-specific symbol and not used by Flutter.
shlib_toolchain = false
if (custom_toolchain != "") {
assert(custom_sysroot != "")
assert(custom_target_triple != "")
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
set_default_toolchain("//build/toolchain/custom")
} else if (is_win) {
# On windows we use the same toolchain for host and target by default.
host_toolchain = "//build/toolchain/win:$current_cpu"
set_default_toolchain("$host_toolchain")
} else if (is_android) {
if (host_os == "linux") {
# Use clang for the x86/64 Linux host builds.
if (host_cpu == "x86" || host_cpu == "x64") {
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
} else {
host_toolchain = "//build/toolchain/linux:$host_cpu"
}
} else if (host_os == "mac") {
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
} else if (host_os == "win") {
host_toolchain = "//build/toolchain/win:$current_cpu"
} else {
assert(false, "Unknown host for android cross compile")
}
if (is_clang) {
set_default_toolchain("//build/toolchain/android:clang_$current_cpu")
} else {
set_default_toolchain("//build/toolchain/android:$current_cpu")
}
} else if (is_linux) {
if (is_clang) {
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
set_default_toolchain("//build/toolchain/linux:clang_$current_cpu")
} else {
host_toolchain = "//build/toolchain/linux:$host_cpu"
set_default_toolchain("//build/toolchain/linux:$current_cpu")
}
if (is_chromeos && cros_use_custom_toolchain) {
set_default_toolchain("//build/toolchain/cros:target")
}
} else if (is_mac) {
host_toolchain = "//build/toolchain/mac:clang_x64"
set_default_toolchain(host_toolchain)
} else if (is_ios) {
import("//build/config/ios/ios_sdk.gni") # For use_ios_simulator
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
if (use_ios_simulator) {
set_default_toolchain("//build/toolchain/mac:ios_clang_x64")
} else {
set_default_toolchain("//build/toolchain/mac:ios_clang_arm")
}
} else if (is_fuchsia) {
if (host_os == "mac") {
host_toolchain = "//build/toolchain/mac:clang_$host_cpu"
} else {
host_toolchain = "//build/toolchain/linux:clang_$host_cpu"
}
set_default_toolchain("//build/toolchain/fuchsia")
} else {
assert(false, "Toolchain not set because of unknown platform.")
}
# Sets default dependencies for executable and shared_library targets.
#
# Variables
# no_default_deps: If true, no standard dependencies will be added.
if (is_android || (is_linux && current_cpu != "x86")) {
foreach(_target_type,
[
"executable",
"loadable_module",
"shared_library",
]) {
template(_target_type) {
target(_target_type, target_name) {
forward_variables_from(invoker, "*", [ "no_default_deps" ])
if (!defined(deps)) {
deps = []
}
if (!defined(invoker.no_default_deps) || !invoker.no_default_deps) {
deps += [ "//third_party/libcxx" ]
}
}
}
}
}
複製代碼
指定須要依賴的共享庫和源文件目錄,全部的依賴配置文件頂層文件目錄 //build/config/sanitizers:deps
//build/config/sanitizers:deps
if (is_component_build) {
component_mode = "shared_library"
} else {
component_mode = "source_set"
}
if (defined(invoker.deps)) {
deps = invoker.deps + [ "//build/config/sanitizers:deps" ]
} else {
deps = [
"//build/config/sanitizers:deps",
]
}
....engine/src/build/config/sanitizers/BUILD.gn 指定第三方庫的依賴....
# Contains the dependencies needed for sanitizers to link into executables and
# shared_libraries. Unconditionally depend upon this target as it is empty if
# |is_asan|, |is_lsan|, |is_tsan|, |is_msan| and |use_custom_libcxx| are false.
group("deps") {
deps = [
"//third_party/instrumented_libraries:deps",
]
if (is_asan || is_lsan || is_tsan || is_msan) {
public_configs = [ ":sanitizer_options_link_helper" ]
deps += [ ":options_sources" ]
}
if (use_custom_libcxx) {
deps += [ "//buildtools/third_party/libc++:libcxx_proxy" ]
}
}
複製代碼
['buildtools/mac-x64/gn', 'gen', '--check', '--ide=xcode',
'out/android_debug_unopt', '--args=skia_enable_pdf=false enable_lto=false
use_clang_static_analyzer=false
full_dart_sdk=false
dart_runtime_mode="develop"
skia_use_fontconfig=false
skia_use_dng_sdk=false
skia_enable_flutter_defines=true
use_goma=false
dart_custom_version_for_pub="flutter"
embedder_for_target=false
is_official_build=true
host_cpu="x86" # 編譯主機架構
is_clang=true
skia_use_sfntly=false
dart_target_arch="arm"
flutter_runtime_mode="debug"
goma_dir="None"
android_full_debug=true
target_os="android" # 生成的目標平臺
mac_sdk_path=""
skia_use_x11=false
enable_coverage=false
target_cpu="arm" # 目標cpu架構
skia_use_expat=true
dart_lib_export_symbols=false
is_debug=true # debug模式
flutter_aot=false' # 不須要優化
]
複製代碼
接着進入 //Flutter
目錄查找`# Copyright 2013 The Flutter Authors. All rights reserved.
import("$flutter_root/common/config.gni")
import("//third_party/dart/build/dart/dart_action.gni")
<!-- # Temporary snapshot copy rules until we can use the full SDK. -->
_flutter_sdk_snapshots = [
[
"dart2js",
"//third_party/dart/utils/compiler:dart2js",
],
[
"kernel_worker",
"//third_party/dart/utils/bazel:kernel_worker",
],
]
group("flutter") {
testonly = true
public_deps = [
"$flutter_root/lib/snapshot:generate_snapshot_bin",
"$flutter_root/lib/snapshot:kernel_platform_files",
"$flutter_root/shell/platform/embedder:flutter_engine",
"$flutter_root/sky",
]
if (current_toolchain == host_toolchain) {
public_deps += [ "$flutter_root/shell/testing" ]
}
if (!is_fuchsia && !is_fuchsia_host) {
if (current_toolchain == host_toolchain) {
public_deps += [
"$flutter_root/frontend_server",
"//third_party/dart:create_sdk",
"$flutter_root/lib/stub_ui:stub_ui",
":dart2js_platform_files",
":flutter_dartdevc_kernel_sdk",
]
foreach(snapshot, _flutter_sdk_snapshots) {
public_deps += [ ":copy_flutter_${snapshot[0]}_snapshot" ]
}
}
}
<!-- # If on the host, compile all unittests targets. -->
if (current_toolchain == host_toolchain) {
if (is_mac) {
public_deps +=
[ "$flutter_root/shell/platform/darwin:flutter_channels_unittests" ]
}
public_deps += [
"$flutter_root/flow:flow_unittests",
"$flutter_root/fml:fml_unittests",
"$flutter_root/runtime:runtime_unittests",
"$flutter_root/shell/common:shell_unittests",
"$flutter_root/shell/platform/embedder:embedder_unittests",
"$flutter_root/shell/platform/embedder:embedder_a11y_unittests", # TODO(cbracken) build these into a different kernel blob in the embedder tests and load that in a test in embedder_unittests
"$flutter_root/synchronization:synchronization_unittests",
"$flutter_root/third_party/txt:txt_unittests",
]
if (!is_win) {
public_deps += [ "$flutter_root/shell/common:shell_benchmarks" ]
}
}
}
config("config") {
include_dirs = [ ".." ]
}
group("dist") {
testonly = true
deps = [
"$flutter_root/sky/dist",
]
}
foreach(snapshot, _flutter_sdk_snapshots) {
copy("copy_flutter_${snapshot[0]}_snapshot") {
deps = [
snapshot[1],
]
sources = [
"$root_gen_dir/${snapshot[0]}.dart.snapshot",
]
outputs = [
"$root_out_dir/dart-sdk/bin/snapshots/flutter_{{source_file_part}}",
]
}
}
copy("dart2js_platform_files") {
deps = [
"//third_party/dart/utils/compiler:compile_dart2js_platform"
]
sources = [
"$root_out_dir/dart2js_outline.dill",
"$root_out_dir/dart2js_platform.dill",
]
outputs = [
"$root_out_dir/flutter_patched_sdk/{{source_file_part}}",
]
}
prebuilt_dart_action("flutter_dartdevc_kernel_sdk") {
deps = [
"//third_party/dart:create_sdk",
]
packages = "//third_party/dart/.packages"
script = "//third_party/dart/pkg/dev_compiler/tool/kernel_sdk.dart"
inputs = [
"//third_party/dart/pkg/dev_compiler/tool/kernel_sdk.dart",
]
outputs = [
"$target_gen_dir/kernel/amd/dart_sdk.js",
"$target_gen_dir/kernel/amd/dart_sdk.js.map",
"$target_gen_dir/kernel/common/dart_sdk.js",
"$target_gen_dir/kernel/common/dart_sdk.js.map",
"$target_gen_dir/kernel/es6/dart_sdk.js",
"$target_gen_dir/kernel/es6/dart_sdk.js.map",
"$target_gen_dir/kernel/legacy/dart_sdk.js",
"$target_gen_dir/kernel/legacy/dart_sdk.js.map",
]
libraries_path = rebase_path("$flutter_root/lib/snapshot/libraries.json")
output_path = rebase_path("$target_gen_dir/kernel/flutter_ddc_sdk.dill")
args = [
"--output=$output_path",
"--libraries=$libraries_path",
]
}
複製代碼
經過GN
工具生成配置文件以後會在out
目錄中生成相關的Ninja
配置文件
!!! info "GN產生的文件說明"
* args.gn # 使用`GN`工具構建是生成的配置參數,能夠驗證配置參數是否正確
* build.ninja # Ninja 配置文件,也是默認的編譯腳本
* build.ninja.d # GN 產生構建文件查找的文件路徑
複製代碼
編譯完成以後,咱們來了解一下目錄的內容,詳細的編譯文件的內容,咱們在下一篇中在進行詳細說明
➜ android_debug_unopt_x86 git:(master) ✗ tree -L 3
.
├── all.xcworkspace
│ └── contents.xcworkspacedata
├── args.gn # 使用`GN`工具構建是生成的配置參數,能夠驗證配置參數是否正確
├── build.ninja # Ninja 配置文件,也是默認的編譯腳本
├── build.ninja.d # GN 產生構建文件查找的文件路徑
├── clang_x64
│ ├── obj
│ │ └── third_party
│ └── toolchain.ninja
├── clang_x86
│ ├── obj
│ │ └── third_party
│ └── toolchain.ninja
├── dart-sdk
│ └── bin
│ └── snapshots
├── gyp-mac-tool
├── obj
│ ├── flutter
│ │ ├── assets
│ │ ├── benchmarking
│ │ ├── common
│ │ ├── flow
│ │ ├── fml
│ │ ├── lib
│ │ ├── runtime
│ │ ├── shell
│ │ ├── synchronization
│ │ ├── testing
│ │ ├── third_party
│ │ └── vulkan
│ └── third_party
│ ├── android_tools
│ ├── benchmark
│ ├── boringssl
│ ├── cpu-features
│ ├── dart
│ ├── expat
│ ├── freetype2
│ ├── googletest
│ ├── harfbuzz
│ ├── icu
│ ├── libcxx
│ ├── libcxxabi
│ ├── libjpeg-turbo
│ ├── libpng
│ ├── libwebp
│ ├── rapidjson
│ ├── skia
│ ├── tonic
│ └── zlib
├── products.xcodeproj
│ └── project.pbxproj
└── toolchain.ninja
45 directories, 9 files
複製代碼
skia_enable_pdf = false
enable_lto = false
use_clang_static_analyzer = false
full_dart_sdk = false
dart_runtime_mode = "develop"
skia_use_fontconfig = false
skia_use_dng_sdk = false
skia_enable_flutter_defines = true
use_goma = false
dart_custom_version_for_pub = "flutter"
embedder_for_target = false
is_official_build = true
host_cpu = "x86"
is_clang = true
skia_use_sfntly = false
dart_target_arch = "x86"
flutter_runtime_mode = "debug"
goma_dir = "None"
android_full_debug = true
target_os = "android"
mac_sdk_path = ""
skia_use_x11 = false
enable_coverage = false
target_cpu = "x86"
skia_use_expat = true
dart_lib_export_symbols = false
is_debug = true
flutter_aot = false
複製代碼
記錄編譯的相關連文件的時間戳來跟蹤源代碼的變化信息
ninja_required_version = 1.7.2
rule gn
command = ../../buildtools/mac-x64/gn --root=../.. -q --check --ide=xcode gen .
description = Regenerating ninja files
build build.ninja: gn
generator = 1
depfile = build.ninja.d
subninja toolchain.ninja
subninja clang_x64/toolchain.ninja
subninja clang_x86/toolchain.ninja
build default: phony obj/default.stamp
build dist: phony obj/dist.stamp
build flutter: phony obj/flutter/flutter.stamp
build _http: phony obj/flutter/sky/packages/sky_engine/_http.stamp
build android: phony obj/flutter/shell/platform/android/android.stamp
build android_arch_lifecycle_common: phony obj/flutter/shell/platform/android/android_arch_lifecycle_common.stamp
build all: phony $
obj/default.stamp $
obj/dist.stamp $
...........
obj/third_party/zlib/libzlib_x86_simd.a
default default
複製代碼
該文件中記錄了GN
文件保存的構建文件的路徑,在GN完成以後生成的文件依賴路徑中的文件能夠在文件中找到,這個文件記錄了編譯是的全部文件會從這些文件的路徑中注意查找
build.ninja: ../../BUILD.gn
../../build/compiled_action.gni
../../build/config/BUILD.gn
.........
../../third_party/tonic/scopes/BUILD.gn
../../third_party/tonic/typed_data/BUILD.gn
../../third_party/zlib/BUILD.gn
複製代碼
咱們分析了使用GN
工具對相關的源文件和配置參數進行設置,不一樣平臺版本,統一平臺的不一樣模式的編譯依賴文件有所不一樣,最終最在out目錄中生成給ninja
編譯器須要的配置文件,經過源文件的學習,咱們更可以理解FlutterEngine目錄下的源代碼的目錄結構和使用到的內容依賴,配置參數和生成的清單文件,接下了就須要學習如何使用編譯命令和參數,以及生成的文件包含哪些內容,咱們將經過下一篇的學習來讀Flutter編譯產物和做用有一個更加深刻的瞭解。
NinjaComplie ninja -C out/android_debug_unopt_x86
開始編譯android_debug_unopt_x86
目錄下GN
生成的構建文件關聯的源文件,讀取android_debug_unopt_x86
目錄下的engine/src/out/android_debug_unopt_x86/build.ninja
從該文件開始查找