introduce

The concepts related to Flutter Engine have been learned from GNTools and Ninja compilation tools. Next, the commands, files and related logic used to execute compilation commands are analyzed. There are some problems with the length of Flutter Engine. Only the relevant logic and documentation of the build are presented (on paper, zhongjue Shallow,….) After getting through the whole mental framework, the only thing left is the question of time, which can be overcome…

The preparatory work

To begin our analysis of how GN generated the Ninja profile, we need to know more about it!! Info “advantages”

* 1. Better readability * 2. Faster * 3. Rely on clearCopy the code

!!!!!!!!! Info “Two file types”

Gn: the root directory usually has a build. gn file, which is the assembly of all code modules. Gni: generally used to add some parameter configuration, import these files or variable parameter values defined in the gn fileCopy the code

GNTools is a build system for compiling large-scale code to generate Ninja files

Ninja source code analysis, optimization and compilation system

Build the Flutter Engine Complie Engine

Preprocessing compiled file

Using different parameter specifies we prepare to build the flutter engine support platform (Windows, Linux, Mac, Android, IOS, Web, Embedder), Support for different modes (debug, Release,profile) on the same platform, how do we play with the system support libraries on different platforms, and different modes on the same platform

!!!!!!!!! Info “Preprocessing compilation files compilation scripts for different platforms”

* ./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 compiler tools [felt] (https://github.com/flutter/engine/blob/master/lib/web_ui/dev/README.md)Copy the code

Track the execution of the command by using the above commands :./flutter/tools/gn –android –unoptimized, participate in the compilation mode of the flutter Engine

  • flutter/tools/gnThe Python script has the following code
  • --androidSpecify the platform
  • --android-cpu x86The CPU architecture
  • --unoptimizedWhether optimization is needed

The following scripts are executed mainly in the build GN build script parameters:

SRC_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) /* Determine the output path of the platform based on the passed parameters */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] gncontents = 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))
Copy the code

Generated GN command parameters

./flutter/tools/gn --android --unoptimized

Start analyzing the dependency tree for the entire source project by calling the following command to find the.ng file in the current directory

command = [
    '%s/buildtools/%s/gn' % (SRC_ROOT, subdir),
    'gen',
    '--check',
  ]
Copy the code

Gn File search process

In the engine/ SRC directory, search for the. Gn file of the entry. Use the SRC /tools/gn tool to search for the source file tree in the root directory and start configuration data

# 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/*",
]
Copy the code

[1]. By viewing the generated command line parameters, you can understand the different modes mentioned in the build mode of the Flutter Engine, how to organize the code and related build files. After understanding the basic ideas and framework, Next, the GN tool calls the build.gn associated file, giving Ninja the commands to BUILD from the file [2] it compiled


['ninja', '-C', 'out/android_debug_unopt', '-t', 'compdb', 'cc', 'cxx', 'objc', 'objcxx', 'asm']
Copy the code

The GN path specified in the [1] build command ‘buildtools/mac-x64/ GN ‘will then be called to execute /engine/src# Gn file engine/ SRC/build. gn is configured to search for build. gn in the specified directory based on the build. gn file in the current directory. Each directory of the build. gn file defines the compilation rules and dependencies for the current directory If you need to add a new function module, reference the build. gn file at the next level in the upper module to contain the required file dependencies. The final ninja configuration file is generated.

/* 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", ] }Copy the code

How to configureOS.CPU.Compilation tool chain

In engine/SRC/build/config/BUILDCONFIG designed.the gn files in the main content of the configuration:

    1. Specifies the Flutter source directory
    1. Specify platform architecture
    1. Specify some build identifiers
    1. Specify system (Windows, Mac, Linux, Android, ios)
    1. Specifies the use of toolchains
    1. Use of third-party open source libraries

Specifies the root directory of a FLUTTER

# Set the root of the engine project.
flutter_root = "//flutter"
Copy the code

Specify the platform

Variables used

- host_os, host_cpu, host_toolchain
- target_os, target_cpu, default_toolchain
- current_os, current_cpu, current_toolchain.
Copy the code

build Flag

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.
}
Copy the code

Specify the platform

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
}
............

Copy the code

Toolchain Settings

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" ] } } } } }Copy the code

COMPONENT configuration

Specify the need to rely on the Shared libraries and source files directory, all depend on the top-level configuration file file directory / / 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 designed.the gn designated third party libraries depend on...
# 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" ]
  }
}
Copy the code

The compiled manifest file is generated after using the GN command and parameters

['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" # Compile host architecture 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 "# Generated target platform mac_sdk_path="" SKIA_use_X11 =false enabLE_COVERAGE =false Skia_use_expat =true dart_lib_export_symbols=false is_debug=true # debug mode flutter_aot=false' # no need to optimize]Copy the code

‘# 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", ] }Copy the code

Ninja Profile

After generating the configuration file using the GN tool, the relevant Ninja configuration file will be generated in the OUT directory

!!!!!!!!! Info “Description of files generated by the GN”

Gn # build with the 'gn' tool is a generated configuration parameter that can verify that the configuration parameters are correct * build.ninja # Ninja configuration file, which is also the default compilation script * build.ninjaCopy the code
After compiling, we'll look at the contents of the directory, the contents of the compiled file in detail, ➜ android_debug_unopt_x86 git:(master) qualify tree -L 3.├ ─ all.xcworkspace │ ├─ content.xcworkspacedata ├── Build ninja # ├── args. Gn # ├─ build ninja # Is also the default build script ├ ─ ─ the build. The ninja. The d # designed.the GN produce build file search the file path ├ ─ ─ clang_x64 │ ├ ─ ─ obj │ │ └ ─ ─ third_party │ └ ─ ─ toolchain. The ninja ├ ─ ─ ├─ ├─ unbreak.txt, unbreak.txt, unbreak.txt, unbreak.txt, unbreak.txt, unbreak.txt, unbreak.txt, unbreak.txt, unbreak.txt ├ ─ ─ obj │ ├ ─ ─ flutter │ │ ├ ─ ─ assets │ │ ├ ─ ─ collected │ │ ├ ─ ─ common │ │ ├ ─ ─ flow │ │ ├ ─ ─ FML │ │ ├ ─ ─ lib │ │ ├ ─ ─ ├─ Exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises, exercises Android_tools │ ├ ─ ─ benchmark │ ├ ─ ─ boringssl │ ├ ─ ─ CPU - the features │ ├ ─ ─ the dart │ ├ ─ ─ the expat │ ├ ─ ─ freetype2 │ ├ ─ ─ Googletest │ ├ ─ ─ harfbuzz │ ├ ─ ─ icu │ ├ ─ ─ libcxx │ ├ ─ ─ libcxxabi │ ├ ─ ─ libjpeg - turbo │ ├ ─ ─ libpng │ ├ ─ ─ libwebp │ ├ ─ ─ Rapidjson │ ├ ─ ─ skia │ ├ ─ ─ tonic │ └ ─ ─ zlib ├ ─ ─ products. Xcodeproj │ └ ─ ─ project. Pbxproj └ ─ ─ toolchain. The ninja 45 directories, 9 filesCopy the code

args.gn

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 = falseCopy the code

build.ninja

Record the time stamp of the compiled related files to track changes in the source code

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 defaultCopy the code

build.ninja.d

This file records the path of the build file saved by the GN file. The files generated in the file dependent path after the GN is completed can be found in the file. This file records all files compiled will be searched from the path of these files

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.gnCopy the code

conclusion

We analyzed the use of the GN tool to set the relevant source files and configuration parameters. Different platform versions and different modes of compilation depend on different files. Finally, we generated the required configuration files for the Ninja compiler in the OUT directory. We can better understand the directory structure of the source code under the FlutterEngine directory and the content dependencies used, configuration parameters and generated manifest files. Then we need to learn how to use the compile commands and parameters, and what contents the generated files contain. We will learn more about Flutter compilation products and their effects in the next chapter.

Execute compile command

NinjaComplie ninja -C Out /android_debug_unopt_x86 The system starts compiling the source file associated with the build file generated by the GN in the android_debug_unopt_x86 directory, and reads the engine/ SRC /out/and file in the android_debug_unopt_x86 directory Roid_debug_unopt_x86 /build.ninja starts with this file