blob: e59c435501d648a01c07de7ab92dccd593ba156a [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/toolchain.gni")
# 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.
#
# force_prebuilt_dart (optional)
# Forces using the prebuilt Dart binary even when use_prebuilt_dart_sdk is
# false. Defaults to true in a cross-build, and false otherwise.
template("dart_tool") {
assert(defined(invoker.main_dart), "Must specify main_dart file")
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
# //garnet/public/foo/bar --> foo.bar
# Strip public directories.
full_dir = get_label_info(":$dart_library_target_name", "dir")
foreach(sdk_dir, sdk_dirs) {
full_dir = string_replace(full_dir, "$sdk_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,
[
"deps",
"disable_analysis",
])
package_name = package_name
package_root = package_root
source_dir = source_dir
sources_required = false
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) ]
}
# Avoid using a custom-built Dart VM in a cross-build. The Dart VM would run
# the Dart code and front-end in a simulator, and it would be prohibitively
# slow.
force_prebuilt_dart = host_cpu != target_cpu
if (defined(invoker.force_prebuilt_dart)) {
force_prebuilt_dart = invoker.force_prebuilt_dart
}
if (force_prebuilt_dart) {
dart_binary = prebuilt_dart
sdk_deps = []
} else {
dart_binary = "$dart_sdk/bin/dart"
sdk_deps = dart_sdk_deps
}
snapshot_path = "$target_gen_dir/${target_name}.snapshot"
depfile_path = "${snapshot_path}.d"
dart_target_gen_dir =
get_label_info(":bogus($dart_toolchain)", "target_gen_dir")
packages_path = "$dart_target_gen_dir/$dart_library_target_name.packages"
snapshot_target_name = target_name + "_snapshot"
# 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 = depfile_path
outputs = [
snapshot_path,
]
script = dart_binary
# The snapshot path needs to be rebased on top of the root build dir so
# that the resulting depfile gets properly formatted.
rebased_snapshot_path = rebase_path(snapshot_path, root_build_dir)
rebased_depfile_path = rebase_path(depfile_path)
rebased_packages_path = rebase_path(packages_path)
main_uri = rebase_path(invoker.main_dart)
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
}
args = [
"--snapshot=$rebased_snapshot_path",
"--snapshot-depfile=$rebased_depfile_path",
"--packages=$rebased_packages_path",
main_uri,
]
deps = sdk_deps + [ ":$dart_library_target_name" ]
}
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) {
script = "//build/dart/gen_app_invocation.py"
app_path = "$root_out_dir/dart-tools/$app_name"
inputs = [
dart_binary,
snapshot_path,
]
outputs = [
app_path,
]
args = [
"--out",
rebase_path(app_path),
"--dart",
rebase_path(dart_binary),
"--snapshot",
rebase_path(snapshot_path),
]
deps = sdk_deps + [ ":$snapshot_target_name" ]
if (defined(invoker.non_dart_deps)) {
deps += invoker.non_dart_deps
}
}
}