blob: dd5971fa2ba0184ddc4d1f84bbe9104d61c1813d [file] [log] [blame]
# Copyright 2017 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/dart_library.gni")
import("//build/dart/dart_package_config.gni")
import("//build/dart/toolchain.gni")
# Wraps a dart snapshot in a script to be invoked by dart
#
# Parameters
#
# dart (required)
# The path to the dart binary
#
# snapshot (required)
# The path to the dart snapshot
#
# deps (optional)
# Dependencies of this application
#
# output_name (optional)
# Name of the output file to generate. Defaults to $target_name.
template("_dart_snapshot_invocation") {
assert(defined(invoker.dart), "Must specify the path to the dart binary")
assert(defined(invoker.snapshot),
"Must specify the path to the dart snapshot")
if (defined(invoker.output_name)) {
app_name = invoker.output_name
} else {
app_name = target_name
}
# Builds a convenience script to invoke the app.
action(target_name) {
forward_variables_from(invoker,
[
"testonly",
"deps",
])
script = "//build/dart/gen_app_invocation.py"
app_path = "$root_out_dir/dart-tools/$app_name"
dart_binary = invoker.dart
snapshot = invoker.snapshot
inputs = [
dart_binary,
snapshot,
]
outputs = [ app_path ]
args = [
"--out",
rebase_path(app_path, root_build_dir),
"--dart",
rebase_path(dart_binary, root_build_dir),
"--snapshot",
rebase_path(snapshot, root_build_dir),
]
metadata = {
# Record metadata for the //:tool_paths build API.
tool_paths = [
{
cpu = current_cpu
label = get_label_info(":$target_name", "label_with_toolchain")
name = app_name
os = current_os
path = rebase_path(app_path, root_build_dir)
},
]
snapshot_path = [ rebase_path(snapshot, root_build_dir) ]
}
}
}
# Defines a Dart application that can be run on the host
#
# Parameters
#
# sources (optional)
# The list of public sources in this library, i.e. Dart files in lib/ but
# not in lib/src/. These sources must be within lib/.
#
# package_name (optional)
# Name of the dart package.
#
# main_dart (required)
# File containing the main function of the application.
#
# deps (optional)
# Dependencies of this application
#
# non_dart_deps (optional)
# List of labels this package depends on that are not Dart packages. It
# typically doesn't need to be set.
#
# output_name (optional)
# Name of the output file to generate. Defaults to $target_name.
#
# disable_analysis (optional)
# Prevents analysis from being run on this target.
template("dart_tool") {
assert(defined(invoker.main_dart), "Must specify main_dart file")
_dart_deps = []
if (defined(invoker.deps)) {
_dart_deps += invoker.deps
}
_tool_deps = []
if (defined(invoker.non_dart_deps)) {
_tool_deps += invoker.non_dart_deps
}
dart_library_target_name = target_name + "_dart_library"
if (defined(invoker.package_name)) {
package_name = invoker.package_name
} else if (!defined(invoker.infer_package_name) ||
invoker.infer_package_name) {
# Compute a package name from the label:
# //foo/bar --> foo.bar
# //foo/bar:blah --> foo.bar._blah
# Strip public directories.
full_dir = get_label_info(":$dart_library_target_name", "dir")
package_name = full_dir
package_name = string_replace(package_name, "//", "")
package_name = string_replace(package_name, "/", ".")
# If the last directory name does not match the target name, add the
# target name to the resulting package name.
name = get_label_info(":$dart_library_target_name", "name")
last_dir = get_path_info(full_dir, "name")
if (last_dir != name) {
package_name = "$package_name._$name"
}
} else {
assert(false, "Must specify either a package_name or infer_package_name")
}
package_root = "."
if (defined(invoker.package_root)) {
package_root = invoker.package_root
}
source_dir = "$package_root/lib"
if (defined(invoker.source_dir)) {
source_dir = "$package_root/${invoker.source_dir}"
}
dart_library(dart_library_target_name) {
forward_variables_from(invoker,
[
"disable_analysis",
"disable_metadata_entry",
"disable_source_verification",
"language_version",
"null_safe",
"testonly",
"visibility",
"options_file",
])
package_name = package_name
package_root = package_root
source_dir = source_dir
sources = []
if (defined(invoker.sources)) {
sources += invoker.sources
}
source_base = "lib"
if (defined(invoker.source_dir)) {
source_base = invoker.source_dir
}
sources += [ rebase_path(invoker.main_dart, source_base) ]
deps = _dart_deps
}
# We only need to make a library if we are specifying sources.
# If no sources are defined we still want to depend on the library
# so we can run analysis on the main file.
if (defined(invoker.sources)) {
_dart_deps += [ ":$dart_library_target_name" ]
} else {
_tool_deps += [ ":$dart_library_target_name" ]
}
dart_binary = prebuilt_dart
sdk_deps = []
snapshot_path = "$target_gen_dir/${target_name}.snapshot"
snapshot_target_name = target_name + "_snapshot"
_dart_package_config_target_name = "${target_name}_dart_package"
# Write output of this dart_package_config in a "packages" subdirectory so it
# doesn't conflict with another package config produced by the dart_library
# above. For example when dart analyzer runs in ${target_gen_dir} for the
# dart_library above, it can incorrectly read this package config if it's in
# the same directory.
_dart_package_config_output = "${target_gen_dir}/packages/${_dart_package_config_target_name}_package_config.json"
dart_package_config(_dart_package_config_target_name) {
forward_variables_from(invoker,
[
"testonly",
"visibility",
])
outputs = [ _dart_package_config_output ]
deps = _dart_deps
}
# Creates a snapshot file.
# The main advantage of snapshotting is that it sets up source dependencies
# via a depfile so that a Dart app gets properly rebuilt when one of its
# sources is modified.
action(snapshot_target_name) {
if (defined(invoker.testonly)) {
testonly = invoker.testonly
}
depfile = "${snapshot_path}.d"
outputs = [ snapshot_path ]
# Dart writes absolute paths to depfiles, convert them to relative.
# See more information in https://fxbug.dev/42155246.
script = "//build/depfile_path_to_relative.py"
main_uri = rebase_path(invoker.main_dart, root_build_dir)
# If we have sources defined we can check to see if the main file is included
# in the source list. If so, we want to call the snapshot generation with
# the `package:foo/main.dart` style. If not we want to pass in a file uri.
if (defined(invoker.sources)) {
package_relative = rebase_path(invoker.main_dart, source_dir)
# Approximation for source_dir contains main_dart.
if (get_path_info(get_path_info(package_relative, "dir"), "file") !=
"bin") {
main_uri = "package:" + package_name + "/" + package_relative
}
}
inputs = [ dart_binary ]
args = [
"--depfile=" + rebase_path(depfile, root_build_dir),
"--",
rebase_path(dart_binary, root_build_dir),
"--verbosity=warning",
]
if (defined(invoker.null_safe) && invoker.null_safe) {
args += [ "--sound-null-safety" ]
} else {
args += [ "--no-sound-null-safety" ]
}
args += [
"--snapshot=" + rebase_path(snapshot_path, root_build_dir),
"--snapshot-depfile=" + rebase_path(depfile, root_build_dir),
"--packages=" + rebase_path(_dart_package_config_output, root_build_dir),
main_uri,
]
deps = sdk_deps + [ ":$_dart_package_config_target_name" ]
metadata = {
rebased_snapshot_path = [ snapshot_path ]
rebased_snapshot_path_barrier = []
}
# snapshot file contains output dir name
no_output_dir_leaks = false
}
# Builds a convenience script to invoke the app.
_dart_snapshot_invocation(target_name) {
forward_variables_from(invoker,
[
"testonly",
"output_name",
])
dart = dart_binary
snapshot = snapshot_path
deps = sdk_deps + _tool_deps + [ ":$snapshot_target_name" ]
}
}
# Defines a Dart application that can be run on the host which is
# compiled from an existing snapshot
#
# Parameters
#
# snapshot (required)
# The path to the dart snapshot
#
# deps (optional)
# Dependencies of this application
#
# output_name (optional)
# Name of the output file to generate. Defaults to $target_name.
template("dart_prebuilt_tool") {
assert(defined(invoker.snapshot),
"Must specify the path to the dart snapshot")
_dart_snapshot_invocation(target_name) {
dart = prebuilt_dart
forward_variables_from(invoker, "*")
}
}