The introduction

Clone the Flutter Engine project or Dart SDK project and you will find a large number of build. gn files in the project. The build. gn file has the same properties as the build.gradle file in the Android project and is used to control the BUILD process. All GN files form a build system, the GN build system. The GN system generates the corresponding Ninja file through the build command, and the generated Ninja file is actually used to compile the project.

GN system construction process

  • Set the directory where the. Gn file resides to the “source root” directory.
  • Gn gets the configuration file buildconfig. gn from the. Gn file and reads it, which is used to set toolchain and Target defaults, etc.
  • Read the build. gn file and the build. gn file referenced therein from the “source root” directory.

GN Common commands

You can run the gn help command to learn all commands.

1. Add build parameters (the directive opens a file editor for configuration parameters, such as target_OS = “android”, and generates < out_DIR >/args.gn after configuration

gn args <out_dir>
Copy the code

2. View the build parameters

gn args --list <out_dir>
Copy the code

3. Generate ninja files based on BUILD parameters and project BUILD files (.gn, buildconfig. gn, build.gn)

gn gen <out_dir>
Copy the code

4. View all the targets in the build artifacts

gn ls <out_dir>
Copy the code

5. View xx Target details

gn desc <out_dir> xx
Copy the code

6. View the Target that depends on xx configuration

gn refs <out_dir> (<label_pattern>|<label>|<file>|@<response_file>)* [--all] [--all-toolchains] [--as=...]  [--testonly=...]  [--type=...]Copy the code

7. Clear all build caches

gn clean <out_dir>
Copy the code

###GN build file

Chromium.googlesource.com/chromium/sr…

GN Identity Rule

  • An identity is a string with a predefined format that depends on all elements in the diagram (targets, configurations, and toolchains) being uniquely identified by the identity, which in general looks like this. It consists of three parts: source-tree absolute path, colon, and name, which means to look for the identifier whose name is “test_support” in /base/test/ build.gn.
   //base/test:test_support
Copy the code
  • When loading the build file, GN will look for the secondary tree in build/ Secondary if the path given relative to source root does not exist. The secondary tree is just a standby, not an overwrite, so the file in the normal location always takes precedence.
  • The complete identity also includes the toolchain to work with that identity. Toolchains are usually specified by default in an inherited manner, although you can also display the specification. This tag will look up the toolchain definition named “MSVC” in the “//build/toolchain/win” file, and that definition will know how to handle the test_support tag.
  //base/test:test_support(//build/toolchain/win:msvc)
Copy the code
  • If the identity you point to is in the build file, you can omit the path and just start with the colon, “:base”.
  • You can specify the path relative to the current directory. As a standard, we recommend using an absolute path when referencing an identity other than that in this file, except that it runs in a different context. What does it mean to run in different contexts? For example, a project should be able to construct a standalone version, and may be a submodule of another project.
  • When writing, you can omit the second and third parts of the identifier, namely the colon and the name. By default, the name uses the last paragraph of the directory. In this case, it is recommended to omit the second and third parts. (The following “=” means equivalent)
`//net = //net:net //tools/gn = //tools/gn:gn
Copy the code

A practical case study of Flutter Engine

  • Build the Flutter Engine environment according to official guidance
  • Check the official guide to learn about the reprogramming engine process, which involves the following two commands:
Ninja ninja -c out/android_debug_unopt // Use ninja file build engine./flutter/tools/gn --android --unoptimizedCopy the code

.flutter/tools/gn (python file, not real GN)

. def main(argv): Exe = '.exe' if sys.platform.startswith(('cygwin', 'win')) else 'command = [' % s/flutter/third_party/designed.the gn/designed.the gn % s' % (SRC_ROOT, exe),' gen ', '- check,] / / add - ide parameters, Specify the type of project to build: xcode, vscode if args.ide! = '': command.append('--ide=%s' % args.ide) elif sys.platform == 'darwin': # On the Mac, generate an Xcode project by default. command.append('--ide=xcode') command.append('--xcode-project=flutter_engine') command.append('--xcode-build-system=new') elif sys.platform.startswith('win'): # On Windows, generate a Visual Studio project.command. Append ('--ide=vs') Gn_args = to_command_line(to_gn_args(args)) out_dir = get_out_dir(args) command.append(out_dir) command.append('--args=%s' % ' '.join(gn_args)) print("Generating GN files in: %s" % out_dir) try: / / designed.the gn command gn_call_result = subprocess. The call (the command, CWD = SRC_ROOT) except subprocess. CalledProcessError as exc: print("Failed to generate gn files: ", exc.returncode, exc.output) sys.exit(1) ... if __name__ == '__main__': sys.exit(main(sys.argv))Copy the code

Finally, the real gn command is called as follows:

/ Users/XXX/flutter - workspace/engine/SRC/flutter/third_party/designed.the gn/designed.the gn gen / / command designed.the gn gen - check - ide = xcode --xcode-project=flutter_engine --xcode-build-system=new //gn internal parameter out/android_debug_unopt // Specify the output directory //gn build parameter --args=skia_enable_pdf=false enable_lto=false full_dart_sdk=false use_clang_static_analyzer=false flutter_enable_skshaper=true skia_use_expat=true enable_bitcode=false skia_use_fontconfig=false skia_use_dng_sdk=false skia_enable_flutter_defines=true use_goma=false flutter_always_use_skshaper=false embedder_for_target=false is_official_build=true android_full_debug=true skia_use_icu=true is_clang=true stripped_symbols=true bssl_use_clang_integrated_as=true skia_use_sfntly=false dart_target_arch="arm" skia_gl_standard="gles" skia_use_wuffs=true flutter_use_fontconfig=false dart_component_kind="static_library" enable_desktop_embeddings=true flutter_runtime_mode="debug" goma_dir="None" dart_version_git_info=true target_os="android" skia_use_x11=false enable_coverage=false target_cpu="arm" dart_runtime_mode="develop" skia_enable_icu_ubrk_safeclone=true dart_lib_export_symbols=false is_debug=true'Copy the code

Generate Args. Gn file

skia_enable_pdf = false enable_lto = false full_dart_sdk = false use_clang_static_analyzer = false flutter_enable_skshaper = true skia_use_expat = true enable_bitcode = false skia_use_fontconfig = false skia_use_dng_sdk  = false skia_enable_flutter_defines = true use_goma = false flutter_always_use_skshaper = false embedder_for_target = false is_official_build = true android_full_debug = true skia_use_icu = true is_clang = true stripped_symbols = true bssl_use_clang_integrated_as = true skia_use_sfntly = false dart_target_arch = "arm" skia_gl_standard = "gles" skia_use_wuffs = true flutter_use_fontconfig = false dart_component_kind = "static_library" enable_desktop_embeddings = true flutter_runtime_mode = "debug" goma_dir = "None" dart_version_git_info = true target_os = "android" skia_use_x11 = false enable_coverage = false target_cpu = "arm" dart_runtime_mode = "develop" skia_enable_icu_ubrk_safeclone = true dart_lib_export_symbols = false is_debug = trueCopy the code

####.gn

. buildconfig = "//build/config/BUILDCONFIG.gn" ...Copy the code

BUILDCONFIG.gn

The entire buildConfig. gn file is divided into the following code blocks:

  • PLATFORM SELECTION: There are two main things to set: “os” and “cpu”
if (current_cpu == "") { current_cpu = target_cpu } if (current_os == "") { if (host_os == "win") { current_os = "win" }  else { current_os = target_os } }Copy the code
  • BUILD FLAGS: This block lists input arguments to the build, along with their default values.
declare_args() { symbol_level = -1 is_component_build = false is_official_build = false is_debug = true is_desktop_linux  = current_os == "linux" && current_os ! = "chromeos" is_clang = current_os == "mac" || current_os == "ios" || current_os == "linux" || current_os == "chromeos" is_asan = false is_lsan = false is_msan = false is_tsan = false is_ubsan = false if (current_os == "chromeos") { cros_use_custom_toolchain = false } }Copy the code
  • OS DEFINITIONS: We set these various is_FOO booleans for convenience in writing OS-based conditions.
. 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
  • BUILD OPTIONS: These Sanitizers all imply using the Clang compiler
if (! is_clang && (is_asan || is_lsan || is_tsan || is_msan)) { is_clang = true } use_flutter_cxx = is_clang && (is_linux || is_android || is_mac)Copy the code
  • TARGET DEFAULTS: Set up the default configuration for every build target of the given type
/ / set the compiler configuration _native_compiler_configs = [" / / build/config: feature_flags ", "/ / build/config/compiler, the compiler", "//build/config/compiler:cxx_version_default", "//build/config/compiler:compiler_arm_fpu", "//build/config/compiler:chromium_code", "//build/config/compiler:default_include_dirs", "//build/config/compiler:no_rtti", "//build/config/compiler:runtime_library", ] ... Executable_configs =_native_compiler_configs + ["//build/config:default_libs"]...Copy the code
  • TOOLCHAIN SETUP: Here we set the default 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") } ...Copy the code

source root

Group ("default") {testOnly = true deps = ["//flutter :flutter]}...Copy the code

####src/flutter/BUILD.gn

// Entry function group("flutter") {... }Copy the code

#### Call Ninja to generate the build product

Ninja -c out/android_debug_unopt // -c means switch the working directory to the specified directoryCopy the code