blob: 5cde1dd68191c37d107494b1b5362c4a5df6d078 [file] [log] [blame]
# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/dart/config.gni")
import("//build/dart/dart_library.gni")
import("//build/dart/toolchain.gni")
_gen_kernel_label = "//build/dart/kernel:gen_kernel($host_toolchain)"
_gen_kernel_path =
get_label_info(_gen_kernel_label, "root_out_dir") + "/dart-tools/gen_kernel"
flutter_platform_name = "flutter_runner"
dart_platform_name = "dart_runner"
# Converts the kernel manifest file from fini format to JSON format and
# registers the metadata for the fuchsia_package to pick up.
#
# Parameters
#
# manifest (required)
# Path to the kernel manifest
# Type: Path
template("_convert_kernel_manifest") {
assert(defined(invoker.manifest), "dart_kernel() requires a manifest")
action(target_name) {
forward_variables_from(invoker,
[
"deps",
"testonly",
"visibility",
])
_converted_file_name =
"${target_gen_dir}/${target_name}_kernel_manifest.json"
script = "//build/dart/kernel/convert_manifest_to_json.py"
args = [
"--input",
rebase_path(invoker.manifest, root_build_dir),
"--output",
rebase_path(_converted_file_name, root_build_dir),
]
sources = [ invoker.manifest ]
outputs = [ _converted_file_name ]
metadata = {
distribution_entries = [
{
file = rebase_path(_converted_file_name, root_build_dir)
label = get_label_info(target_name, "label_with_toolchain")
},
]
}
}
}
# Generates dill files for a Dart application.
#
# It is not likely that this target will be used directly. Instead, developers
# should use the dart_tool or dart/flutter_component targets which create a
# kernel for you.
#
# Parameters
#
# platform_name (required)
# The name of the platform, either "flutter_runner" or "dart_runner".
#
# packages_path (required)
# Path to the package_config.json file.
#
# main_dart (required, mutually exclusive)
# Path to Dart source file containing main(). Mutually exclusive with
# main_dart_file. This is relative to source_dir, should exist in the
# main_package, and uses a package: URI.
#
# main_package (required, mutually exclusive)
# The name of the package which contains main. Mutually exclusive with
# main_dart_file.
#
# main_dart_file (required, mutually exclusive)
# Path to Dart source file containing main(). Mutually exclusive with
# main_dart. This doesn't need to necessarily exist in main_package and uses
# a fuchsia-source: URI.
#
# product (required)
# Whether this should be built with the product runner.
#
# is_aot (required)
# Whether this kernel is an aot build.
#
# is_debug (optional)
# Whether this sources are embedded. Addiitonally, if is_debug, the dart VM
# will not run in profile mode.
#
# generate_manifest (optional)
# Whether the compiler should generate a kernel manifest containing the list
# of partial dill files in JIT builds. This flag is ignored in aot builds
# Default: false
#
# kernel_path (optional)
# The path to the kernel output. Defaults to target_gen_dir/${target_name}.dil
#
# kernel_target_name (optional)
# The name of the kernel target. This parameter is required if you are
# depending on the kernel_path for an input. This allows you to establish a
# dependency chain on the generated file.
#
# args (optional)
# A list of additional arguments to the compiler.dart program in this
# directory that generates the kernel files.
#
# link_platform (optional)
# Whether the kernel compiler should link the current platform.dill into
# the build. If false, the --no-link-platform flag will be passed to the
# compiler. Defaults to false
#
# null_safe (optional)
# If true, this program will be compiled with --sound-null-safety
template("dart_kernel") {
assert(defined(invoker.platform_name), "dart_kernel() requires platform_name")
assert(defined(invoker.packages_path),
"dart_kernel() requires the path to the package config")
assert(
(defined(invoker.main_dart) && defined(invoker.main_package)) !=
defined(invoker.main_dart_file),
"dart_kernel() requires either (main_dart and main_package) or main_dart_file")
assert(defined(invoker.product), "dart_kernel() requires product")
assert(defined(invoker.is_aot), "dart_kernel() requires is_aot")
_is_debug = is_debug
if (defined(invoker.is_debug)) {
_is_debug = invoker.is_debug
}
if (defined(invoker.kernel_target_name)) {
_kernel_target_name = invoker.kernel_target_name
} else {
_kernel_target_name = "${target_name}_kernel"
}
_group_deps = [ ":$_kernel_target_name" ]
_kernel_deps = []
if (defined(invoker.deps)) {
_kernel_deps += invoker.deps
}
_generate_manifest = false
if (invoker.is_aot) {
not_needed(invoker, [ "generate_manifest" ])
} else {
if (defined(invoker.generate_manifest) && invoker.generate_manifest) {
_generate_manifest = true
}
}
if (_generate_manifest) {
_kernel_manifest = "$target_gen_dir/${target_name}.dilpmanifest"
_convert_target_name = "${target_name}_convert_kernel_manifest"
_convert_kernel_manifest(_convert_target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
manifest = _kernel_manifest
# must depend on the kernel target so we have the kernel manifest
deps = [ ":$_kernel_target_name" ]
}
_group_deps += [ ":$_convert_target_name" ]
}
action(_kernel_target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
pool = "//build/config:local($default_toolchain)"
if (defined(invoker.kernel_path)) {
_kernel_path = invoker.kernel_path
} else {
_kernel_path =
"$target_gen_dir/__untraced_dart_kernel__/${target_name}.dil"
}
depfile = "${_kernel_path}.d"
_kernel_deps += [ _gen_kernel_label ]
if (invoker.platform_name == flutter_platform_name) {
_kernel_deps += [ "//build/flutter:platform_files" ]
_platform_path = "$root_out_dir/flutter_runner_patched_sdk"
} else if (invoker.platform_name == dart_platform_name) {
_kernel_deps += [ "//build/dart:platform_files" ]
_platform_path = "$root_out_dir/dart_runner_patched_sdk"
} else {
assert(false,
"platform_name must be either dart_runner or flutter_runner")
}
_platform_strong_dill = "${_platform_path}/platform_strong.dill"
inputs = [
_gen_kernel_path,
_platform_strong_dill,
invoker.packages_path,
]
outputs = [ _kernel_path ]
if (_generate_manifest) {
outputs += [
# Explicit output when using --manifest.
_kernel_manifest,
# Implicit output when using --manifest; see createManifest in compiler.dart.
_kernel_manifest + ".dilplist",
_kernel_manifest + ".frameworkversion",
]
}
_multi_root_scheme = "fuchsia-source"
# Rebase against // instead of root_build_dir since the package_config is
# relative to the sources.
_rebased_packages_path = rebase_path(invoker.packages_path, "//")
# gen_kernel writes absolute paths to depfiles, convert them to relative.
# See more information in https://fxbug.dev/75451.
script = "//build/depfile_path_to_relative.py"
args = [
"--depfile=" + rebase_path(depfile, root_build_dir),
"--",
rebase_path(_gen_kernel_path, root_build_dir),
]
if (defined(invoker.args)) {
args += invoker.args
}
args += [ "--verbosity=warning" ]
if (defined(invoker.null_safe) && invoker.null_safe) {
args += [ "--sound-null-safety" ]
} else {
args += [ "--no-sound-null-safety" ]
}
args += [
"--target",
invoker.platform_name,
"--platform",
rebase_path(_platform_strong_dill, root_build_dir),
"--filesystem-scheme",
_multi_root_scheme,
"--filesystem-root",
rebase_path("//", root_build_dir),
"--packages",
"$_multi_root_scheme:///$_rebased_packages_path",
# Repeating "--depfile" because the previous one is for
# `depfile_path_to_relative.py`, and this one is for `_gen_kernel_path`.
"--depfile",
rebase_path(depfile, root_build_dir),
"--output",
rebase_path(_kernel_path, root_build_dir),
]
if (_generate_manifest) {
args += [
"--split-output-by-packages",
"--manifest",
rebase_path(_kernel_manifest, root_build_dir),
]
}
if (_is_debug) {
args += [ "--embed-sources" ]
} else {
args += [ "--no-embed-sources" ]
}
if (invoker.is_aot) {
args += [
"--aot",
"--tfa",
]
} else if (!defined(invoker.link_platform) || !invoker.link_platform) {
args += [ "--no-link-platform" ]
}
if (invoker.product) {
# Setting this flag in a non-product release build for AOT (a "profile"
# build) causes the vm service isolate code to be tree-shaken from an app.
# See the pragma on the entrypoint here:
#
# This define excludes debugging and profiling code from Flutter.
args += [ "-Ddart.vm.product=true" ]
} else {
if (!_is_debug) {
# The following define excludes debugging code from Flutter.
args += [ "-Ddart.vm.profile=true" ]
}
}
if (defined(invoker.main_dart)) {
args += [ "package:${invoker.main_package}/${invoker.main_dart}" ]
} else {
rebased_main_dart = rebase_path(invoker.main_dart_file, "//")
args += [ "$_multi_root_scheme:///$rebased_main_dart" ]
}
deps = _kernel_deps
# rebased_main_dart includes the output dir name
no_output_dir_leaks = false
}
group(target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
deps = _group_deps
}
}