mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Snapshots compiled with sound null-safety enabled require changes to the way in which isolates are launched. Specifically, the `Dart_IsolateFlags::null_safety` field needs to be known upfront. The value of this field can only be determined once the kernel snapshot is available. This poses a problem in the engine because the engine used to launch the isolate at shell initialization and only need the kernel mappings later at isolate launch (when transitioning the root isolate to the `DartIsolate::Phase::Running` phase). This patch delays launch of the isolate on the UI task runner till a kernel mapping is available. The side effects of this delay (callers no longer having access to the non-running isolate handle) have been addressed in this patch. The DartIsolate API has also been amended to hide the method that could return a non-running isolate to the caller. Instead, it has been replaced with a method that requires a valid isolate configuration that returns a running root isolate. The isolate will be launched by asking the isolate configuration for its null-safety characteristics. A side effect of enabling null-safety is that Dart APIs that work with legacy types will now terminate the process if used with an isolate that has sound null-safety enabled. These APIs may no longer be used in the engine. This primarily affects the Dart Convertors in Tonic that convert certain C++ objects into the Dart counterparts. All known Dart Converters have been updated to convert C++ objects to non-nullable Dart types inferred using type traits of the corresponding C++ object. The few spots in the engine that used the old Dart APIs directly have been manually updated. To ensure that no usage of the legacy APIs remain in the engine (as these would cause runtime process terminations), the legacy APIs were prefixed with the `DART_LEGACY_API` macro and the macro defined to `[[deprecated]]` in all engine translation units. While the engine now primarily works with non-nullable Dart types, callers can still use `Dart_TypeToNonNullableType` to acquire nullable types for use directly or with Tonic. One use case that is not addressed with the Tonic Dart Convertors is the creation of non-nullable lists of nullable types. This hasn’t come up so far in the engine. A minor related change is reworking tonic to define a single library target. This allows the various tonic subsystems to depend on one another. Primarily, this is used to make the Dart convertors use the logging utilities. This now allows errors to be more descriptive as the presence of error handles is caught (and logged) earlier. Fixes https://github.com/flutter/flutter/issues/59879
266 lines
7.6 KiB
Plaintext
266 lines
7.6 KiB
Plaintext
# Copyright 2013 The Flutter 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/compiled_action.gni")
|
|
import("//flutter/common/config.gni")
|
|
import("//third_party/dart/build/dart/dart_action.gni")
|
|
|
|
is_aot_test =
|
|
flutter_runtime_mode == "profile" || flutter_runtime_mode == "release"
|
|
|
|
# Unit tests targets are only enabled for host machines and Fuchsia right now
|
|
declare_args() {
|
|
enable_unittests = current_toolchain == host_toolchain || is_fuchsia
|
|
}
|
|
|
|
# Creates a translation unit that defines the flutter::testing::GetFixturesPath
|
|
# method that tests can use to locate their fixtures.
|
|
#
|
|
# Arguments
|
|
# assets_dir (required): The assets directory
|
|
template("fixtures_location") {
|
|
testonly = true
|
|
|
|
assert(defined(invoker.assets_dir), "The assets directory.")
|
|
|
|
location_path = rebase_path(invoker.assets_dir)
|
|
|
|
# Array of source lines. We use a list to ensure a trailing newline is
|
|
# emitted by write_file() to comply with -Wnewline-eof.
|
|
location_source = [ "namespace flutter {namespace testing {const char* GetFixturesPath() {return \"$location_path\";}}}" ]
|
|
location_source_path = "$target_gen_dir/_fl_$target_name.cc"
|
|
|
|
write_file(location_source_path, location_source)
|
|
|
|
source_set(target_name) {
|
|
public = []
|
|
sources = [ location_source_path ]
|
|
}
|
|
}
|
|
|
|
# Generates the Dart kernel snapshot.
|
|
#
|
|
# Arguments
|
|
# dart_main (required): The Main Dart file.
|
|
#
|
|
# dart_kernel (required): The path to the ouput kernel snapshot in the out
|
|
# directory.
|
|
template("dart_snapshot_kernel") {
|
|
testonly = true
|
|
|
|
assert(defined(invoker.dart_main), "The Dart Main file must be specified")
|
|
assert(defined(invoker.dart_kernel),
|
|
"The Dart Kernel file location must be specified")
|
|
|
|
dart_action(target_name) {
|
|
testonly = true
|
|
|
|
deps = [
|
|
# This generates the Frontend server snapshot used in this Dart action as
|
|
# well as the patched SDK.
|
|
"//third_party/dart/utils/kernel-service:frontend_server",
|
|
]
|
|
|
|
if (is_aot_test) {
|
|
deps += [ "//flutter/lib/snapshot:strong_platform" ]
|
|
}
|
|
|
|
script = "$root_out_dir/frontend_server.dart.snapshot"
|
|
|
|
inputs = [ invoker.dart_main ]
|
|
|
|
outputs = [ invoker.dart_kernel ]
|
|
|
|
snapshot_depfile = "$target_gen_dir/snapshot_$target_name.depfile.d"
|
|
depfile = snapshot_depfile
|
|
|
|
args = [
|
|
"--sdk-root",
|
|
rebase_path("$root_out_dir/flutter_patched_sdk"),
|
|
"--target",
|
|
"flutter",
|
|
"--enable-experiment=non-nullable",
|
|
"--output-dill",
|
|
rebase_path(invoker.dart_kernel, root_out_dir),
|
|
"--depfile",
|
|
rebase_path(snapshot_depfile),
|
|
]
|
|
|
|
if (flutter_runtime_mode == "release" ||
|
|
flutter_runtime_mode == "jit_release") {
|
|
args += [ "-Ddart.vm.product=true" ]
|
|
}
|
|
|
|
if (is_aot_test) {
|
|
args += [
|
|
"--aot",
|
|
|
|
# type flow analysis
|
|
"--tfa",
|
|
]
|
|
}
|
|
|
|
args += [ rebase_path(invoker.dart_main) ]
|
|
}
|
|
}
|
|
|
|
# Generates an AOT snapshot from a kernel snapshot.
|
|
#
|
|
# Arguments:
|
|
#
|
|
# dart_kernel (required): The path to the kernel snapshot.
|
|
template("dart_snapshot_aot") {
|
|
testonly = true
|
|
|
|
assert(defined(invoker.dart_kernel),
|
|
"The Dart Kernel file location must be specified")
|
|
|
|
compiled_action(target_name) {
|
|
testonly = true
|
|
|
|
tool = "//third_party/dart/runtime/bin:gen_snapshot"
|
|
|
|
inputs = [ invoker.dart_kernel ]
|
|
|
|
# Custom ELF loader is used for Mac and Windows.
|
|
elf_object = "$target_gen_dir/assets/app_elf_snapshot.so"
|
|
|
|
outputs = [ elf_object ]
|
|
|
|
args = [
|
|
"--causal_async_stacks",
|
|
"--deterministic",
|
|
"--snapshot_kind=app-aot-elf",
|
|
"--elf=" + rebase_path(elf_object),
|
|
rebase_path(invoker.dart_kernel),
|
|
]
|
|
|
|
forward_variables_from(invoker, [ "deps" ])
|
|
}
|
|
}
|
|
|
|
# Generates a kernel or AOT snapshot as necessary from the main Dart file.
|
|
# Other Dart dependencies referenced by that main Dart file will be tracked.
|
|
#
|
|
# Arguments:
|
|
#
|
|
# dart_main (required): The path to the main Dart file.
|
|
template("dart_snapshot") {
|
|
assert(defined(invoker.dart_main), "The main Dart file must be specified.")
|
|
|
|
testonly = true
|
|
|
|
dart_snapshot_kernel_target_name = "_dsk_$target_name"
|
|
dart_snapshot_kernel_path = "$target_gen_dir/assets/kernel_blob.bin"
|
|
dart_snapshot_kernel(dart_snapshot_kernel_target_name) {
|
|
dart_main = invoker.dart_main
|
|
dart_kernel = dart_snapshot_kernel_path
|
|
}
|
|
|
|
snapshot_deps = []
|
|
snapshot_public_deps = [ ":$dart_snapshot_kernel_target_name" ]
|
|
|
|
if (is_aot_test) {
|
|
dart_snapshot_aot_target_name = "_dsa_$target_name"
|
|
dart_snapshot_aot(dart_snapshot_aot_target_name) {
|
|
dart_kernel = dart_snapshot_kernel_path
|
|
deps = [ ":$dart_snapshot_kernel_target_name" ]
|
|
}
|
|
snapshot_deps += [ ":$dart_snapshot_aot_target_name" ]
|
|
}
|
|
|
|
group(target_name) {
|
|
testonly = true
|
|
deps = snapshot_deps
|
|
public_deps = snapshot_public_deps
|
|
}
|
|
}
|
|
|
|
# Copies a (potentially empty) list of fixtures to the fixtures directory for
|
|
# the unit test.
|
|
#
|
|
# Arguments:
|
|
#
|
|
# fixtures (required): The list of fixtures to copy.
|
|
template("copy_fixtures") {
|
|
testonly = true
|
|
|
|
assert(defined(invoker.fixtures), "The test fixtures must be specified.")
|
|
|
|
has_fixtures = false
|
|
foreach(fixture, invoker.fixtures) {
|
|
has_fixtures = true
|
|
}
|
|
|
|
if (has_fixtures) {
|
|
copy(target_name) {
|
|
sources = invoker.fixtures
|
|
outputs = [ "$target_gen_dir/assets/{{source_file_part}}" ]
|
|
}
|
|
} else {
|
|
group(target_name) {
|
|
# The copy target cannot accept an empty list.
|
|
}
|
|
}
|
|
}
|
|
|
|
# Specifies the fixtures to copy to a location known by the specific unit test.
|
|
# Test executable can only depend on one such target. You can use either one of
|
|
# both arguments to expand this template. If you have none, then you'll see the
|
|
# unused invoker scope error. In such cases specify the fixtures using an empty
|
|
# array.
|
|
#
|
|
# The targets which generate the outputs from these test fixtures (e.g. the
|
|
# Dart kernel snapshot) are exposed as public dependencies of the test fixture
|
|
# target. This is so that users can depend on the test fixture target directly
|
|
# and be able to access the generated outputs without needing to know about the
|
|
# internal dependency structure generated by this template.
|
|
#
|
|
# Arguments:
|
|
#
|
|
# fixtures (optional): The list of test fixtures. An empty list may be
|
|
# specified.
|
|
#
|
|
# dart_main (optional): The path to the main Dart file. If specified, it is
|
|
# snapshotted.
|
|
template("test_fixtures") {
|
|
# Even if no fixtures are present, the location of the fixtures directory
|
|
# must always be known to tests.
|
|
fixtures_location_target_name = "_fl_$target_name"
|
|
fixtures_location(fixtures_location_target_name) {
|
|
if (is_fuchsia) {
|
|
assets_dir = "/pkg/data/assets"
|
|
} else {
|
|
assets_dir = "$target_gen_dir/assets"
|
|
}
|
|
}
|
|
test_deps = [ ":$fixtures_location_target_name" ]
|
|
test_public_deps = []
|
|
|
|
# If the fixtures are specified, copy them to the assets directory.
|
|
if (defined(invoker.fixtures)) {
|
|
copy_fixtures_target_name = "_cf_$target_name"
|
|
copy_fixtures(copy_fixtures_target_name) {
|
|
fixtures = invoker.fixtures
|
|
}
|
|
test_public_deps += [ ":$copy_fixtures_target_name" ]
|
|
}
|
|
|
|
# If a Dart file is specified, snapshot it and place it in the generated
|
|
# assets directory.
|
|
if (defined(invoker.dart_main)) {
|
|
dart_snapshot_target_name = "_ds_$target_name"
|
|
dart_snapshot(dart_snapshot_target_name) {
|
|
dart_main = invoker.dart_main
|
|
}
|
|
test_public_deps += [ ":$dart_snapshot_target_name" ]
|
|
}
|
|
|
|
group(target_name) {
|
|
testonly = true
|
|
deps = test_deps
|
|
public_deps = test_public_deps
|
|
}
|
|
}
|