Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 67 additions & 138 deletions build/dart/rules.gni
Original file line number Diff line number Diff line change
Expand Up @@ -10,115 +10,21 @@ import("//flutter/common/config.gni")
import("//third_party/dart/build/dart/dart_action.gni")
import("//third_party/dart/sdk_args.gni")

# Generates a Dart kernel snapshot using flutter_frontend_server.
#
# Arguments
# main_dart (required):
# The Dart entrypoint file.
#
# kernel_output (required):
# The path to the output kernel snapshot in the out directory.
#
# package_config (optional):
# The path to the package_config.json file.
#
# deps (optional):
# Additional dependencies. Dependencies on the frontend server and
# Flutter's platform.dill are included by default. This rule creates and
# uses a depfile, so listing all Dart sources is not necessary.
#
# extra_args (optional):
# Additional frontend server command line arguments.
template("flutter_frontend_server") {
assert(defined(invoker.main_dart), "The Dart test file must be specified.")
assert(defined(invoker.kernel_output),
"The Dart Kernel file location must be specified.")

kernel_output = invoker.kernel_output

common_deps = [
"//flutter/flutter_frontend_server:frontend_server",
"//flutter/lib/snapshot:strong_platform",
]
if (defined(invoker.deps)) {
common_deps += invoker.deps
}

extra_args = []
if (defined(invoker.extra_args)) {
extra_args += invoker.extra_args
}

packages_args = []
if (defined(invoker.package_config)) {
packages_args += [
"--packages",
rebase_path(invoker.package_config),
]
}

snapshot_depfile = "$kernel_output.d"

common_vm_args = [ "--disable-dart-dev" ]

flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk")

common_args = extra_args + packages_args + [
"--sdk-root",
flutter_patched_sdk,
"--target=flutter",
"--depfile",
rebase_path(snapshot_depfile),
"--output-dill",
rebase_path(invoker.kernel_output),
rebase_path(invoker.main_dart),
]

if (flutter_prebuilt_dart_sdk) {
action(target_name) {
forward_variables_from(invoker,
[
"visibility",
"testonly",
],
[ "pool" ])
deps = common_deps
pool = "//flutter/build/dart:dart_pool"
script = "//build/gn_run_binary.py"
inputs = [ invoker.main_dart ]
outputs = [ invoker.kernel_output ]
depfile = snapshot_depfile

ext = ""
if (is_win) {
ext = ".exe"
}
dart = rebase_path("$host_prebuilt_dart_sdk/bin/dart$ext", root_out_dir)
frontend_server =
rebase_path("$root_gen_dir/frontend_server.dart.snapshot")

args = [ dart ] + common_vm_args + [ frontend_server ] + common_args
}
} else {
dart_action(target_name) {
forward_variables_from(invoker,
[
"visibility",
"testonly",
],
[ "pool" ])
deps = common_deps
pool = "//flutter/build/dart:dart_pool"
script = "$root_gen_dir/frontend_server.dart.snapshot"
packages = rebase_path(invoker.package_config)
inputs = [ invoker.main_dart ]
outputs = [ invoker.kernel_output ]
depfile = snapshot_depfile
vm_args = common_vm_args
args = common_args
}
}
}
frontend_server_files =
exec_script("//third_party/dart/tools/list_dart_files.py",
[
"absolute",
rebase_path("//flutter/flutter_frontend_server"),
],
"list lines")

frontend_server_files +=
exec_script("//third_party/dart/tools/list_dart_files.py",
[
"absolute",
rebase_path("//third_party/dart/pkg"),
],
"list lines")

# Creates a dart kernel (dill) file suitable for use with gen_snapshot, as well
# as the app-jit, aot-elf, or aot-assembly snapshot for targeting Flutter on
Expand All @@ -142,38 +48,61 @@ template("flutter_snapshot") {

kernel_output = "$target_gen_dir/kernel_blob.bin"

extra_frontend_server_args = []
if (is_aot) {
extra_frontend_server_args += [
"--aot",
"--tfa",
prebuilt_dart_action(kernel_target) {
script = "//flutter/flutter_frontend_server/bin/starter.dart"

main_dart = rebase_path(invoker.main_dart)
package_config = rebase_path(invoker.package_config)
flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk")

deps = [ "//flutter/lib/snapshot:strong_platform" ]

inputs = [
main_dart,
package_config,
] + frontend_server_files

outputs = [ kernel_output ]

depfile = "$kernel_output.d"
abs_depfile = rebase_path(depfile)
vm_args = [ "--disable-dart-dev" ]

args = [
"--depfile=$abs_depfile",
"--packages=" + rebase_path(package_config),
"--target=flutter",
"--sdk-root=" + flutter_patched_sdk,
"--output-dill=" + rebase_path(kernel_output, root_build_dir),
]
} else {
# --no-link-platform is only valid when --aot isn't specified
extra_frontend_server_args += [ "--no-link-platform" ]
}

if (defined(invoker.product) && 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:
#
# https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/bin/vmservice_io.dart#L240
#
# Also, this define excludes debugging and profiling code from Flutter.
extra_frontend_server_args += [ "-Ddart.vm.product=true" ]
} else {
if (flutter_runtime_mode == "profile") {
# The following define excludes debugging code from Flutter.
extra_frontend_server_args += [ "-Ddart.vm.profile=true" ]
if (is_aot) {
args += [
"--aot",
"--tfa",
]
} else {
# --no-link-platform is only valid when --aot isn't specified
args += [ "--no-link-platform" ]
}

if (defined(invoker.product) && 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:
#
# https://github.com/dart-lang/sdk/blob/main/sdk/lib/_internal/vm/bin/vmservice_io.dart#L240
#
# Also, this define excludes debugging and profiling code from Flutter.
args += [ "-Ddart.vm.product=true" ]
} else {
if (flutter_runtime_mode == "profile") {
# The following define excludes debugging code from Flutter.
args += [ "-Ddart.vm.profile=true" ]
}
}
}

flutter_frontend_server(kernel_target) {
main_dart = invoker.main_dart
package_config = invoker.package_config
kernel_output = kernel_output
extra_args = extra_frontend_server_args
args += [ rebase_path(main_dart) ]
}

compiled_action(snapshot_target) {
Expand Down Expand Up @@ -342,7 +271,7 @@ template("application_snapshot") {
# Ensure the compiled appliation (e.g. frontend-server, ...) will use this
# Dart SDK hash when consuming/producing kernel.
#
# (Instead of ensuring every user of the "application_snapshot" passes its
# (Instead of ensuring every user of the "application_snapshot" passes it's
# own)
snapshot_vm_args += [ "-Dsdk_hash=$sdk_hash" ]

Expand Down
19 changes: 5 additions & 14 deletions common/config.gni
Original file line number Diff line number Diff line change
Expand Up @@ -113,27 +113,18 @@ if (flutter_prebuilt_dart_sdk) {
_host_os_name = "windows"
}

# When building 32-bit Android development artifacts for Windows host (like
# gen_snapshot), the host_cpu is set to x86. However, the correct prebuilt
# Dart SDK to use during this build is still the 64-bit one.
_host_cpu = host_cpu
if (host_os == "win" && host_cpu == "x86") {
_host_cpu = "x64"
}

_target_prebuilt_dart_sdk_config = "$_target_os_name-$target_cpu"
_host_prebuilt_dart_sdk_config = "$_host_os_name-$_host_cpu"
_host_prebuilt_dart_sdk_config = "$_host_os_name-$host_cpu"

target_prebuilt_dart_sdk =
"//flutter/prebuilts/$_target_prebuilt_dart_sdk_config/dart-sdk"
host_prebuilt_dart_sdk =
"//flutter/prebuilts/$_host_prebuilt_dart_sdk_config/dart-sdk"

# There is no prebuilt Dart SDK targeting Fuchsia, iOS, and Android, but we
# also don't need one, so even when the build is targeting one of these
# platforms, we use the prebuilt Dart SDK for the host.
if (current_toolchain == host_toolchain || target_os == "android" ||
target_os == "fuchsia" || target_os == "ios" || target_os == "wasm") {
# There is no prebuilt Dart SDK targeting Fuchsia, but we also don't need
# one, so even when the build is targeting Fuchsia, use the prebuilt
# Dart SDK for the host.
if (current_toolchain == host_toolchain || is_fuchsia || is_wasm) {
prebuilt_dart_sdk = host_prebuilt_dart_sdk
prebuilt_dart_sdk_config = _host_prebuilt_dart_sdk_config
} else {
Expand Down
25 changes: 13 additions & 12 deletions flutter_frontend_server/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//flutter/common/config.gni")
import("//flutter/build/dart/rules.gni")

copy("frontend_server") {
if (flutter_prebuilt_dart_sdk) {
snapshot =
"$host_prebuilt_dart_sdk/bin/snapshots/frontend_server.dart.snapshot"
} else {
deps = [ "//flutter/build/dart:dart_sdk" ]
snapshot =
"$root_out_dir/dart-sdk/bin/snapshots/frontend_server.dart.snapshot"
}
application_snapshot("frontend_server") {
main_dart = "bin/starter.dart"
deps = [ "//flutter/lib/snapshot:kernel_platform_files" ]

sources = [ snapshot ]
outputs = [ "$root_gen_dir/frontend_server.dart.snapshot" ]
package_config = rebase_path(".dart_tool/package_config.json")
flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk")
training_args = [
"--train",
"--sdk-root=$flutter_patched_sdk",
rebase_path(main_dart),
]

inputs = frontend_server_files
}
71 changes: 71 additions & 0 deletions flutter_frontend_server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Frontend Server

Frontend server is simple wrapper around Dart Frontend. It is a Dart application
that compiles Dart source into Dart Kernel binary (.dill-file).
Documentation on Dart Kernel (semantic, binary format, etc) can be found here:
https://github.com/dart-lang/sdk/wiki/Kernel-Documentation.

Frontend server runs in two modes:
- immediate mode, where Dart source file name is provided as command line
argument;
- interactive mode, where communication is happening over stdin/stdout.

## Interactive mode instructions

### Compile/Recompile
```
compile <input.dart>
```
Compiles <input.dart> Dart source file with Dart Frontend. Replies with `result` response.

```
recompile <boundary-key>
<path/to/updated/file1.dart>
<path/to/updated/file2.dart>
...
<boundary-key>
```
Incrementally recompiles Dart program previously compiled in current session, taking into account
changes in the listed files. Replies with `result` response.

Relative paths should be relative to current working directory for the shell that launched
Frontend Server.

### Accept/Reject
```
accept
```
Accepts results of incremental compilation, so that on next recompilation request Dart Frontend
will not include these recompiled files.
```
reject
```
Rejects results of incremental compilation, so that on next recompilation request Dart Frontend
will include compilation results from previously rejected recompilation in addition to what it
will recompile based on newly changed files.
Small technical detail is that Dart Frontend will not recompile files from previously rejected
recompilation attempts (unless they were changed since then), it will just include appropriate
kernel binaries it kept around from those previously rejected compilation requests.

One use of `accept` and `reject` instructions is in the context of Dart VM hot-reload. Dart VM can
reject user-provided incremental change to what is currently running. It could happen for variety
of Dart VM internal reasons. For example, if incremental update changes some `class` to `enum`,
such update can not be hot-reloaded by VM at this point, will be rejected.

### Quit
```
quit
```
Stops the server.

## Response from the server

```
result <boundary-key>
<compiler output>
<boundary-key> [<output.dill>]
```
Response from the Dart Frontend compiler is bracketed by `<boundary-key>` tags. If the compiler
was able to produce a Dart Kernel file, the name of this file `<output.dill>` is provided too.
If the compiler encountered unrecoverable errors, there will be no output file name provided.

15 changes: 15 additions & 0 deletions flutter_frontend_server/bin/starter.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// 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 'dart:io';

import 'package:flutter_frontend_server/server.dart';

Future<void> main(List<String> args) async {
final int exitCode = await starter(args);
if (exitCode != 0) {
exit(exitCode);
}
}
Loading