blob: 08b6a9a66349bfeedc96392397f2a4d73af5996c [file] [log] [blame]
# Copyright 2025 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/bazel/bazel_action.gni")
import("//build/testing/test_spec.gni")
import("//src/sys/pkg/bin/package-tool/package-tool.gni")
# Build several Bazel test packages with a single GN > Bazel boundary
# transition. This can be considerably faster than building
# them through separate bazel_fuchsia_test_package() targets, because
# these must always be serialized. Using a bazel_test_package_group()
# allows Bazel to parallelize more work at the same time,
# and avoids repeating the analysis phase on each call.
#
# However, this also means that *all* Bazel targets are re-built
# it any of a single tests's dependency changes.
#
# Arguments:
# tests: (required)
# A list of test, each one describing the content of a given
# Bazel test package to build and corresponding test components. Each item
# in the list follows the following schema:
#
# test_package_target (required)
# A GN target name. It usually should be a
# bazel_fuchsia_test_package target so the proper test_spec target
# will be defined.
#
# test_package_name: (optional)
# The `package_name` of the wrapped `fuchsia_test_package`.
#
# test_component_names (required)
# The `name`s of components in the wrapped `fuchsia_test_package`.
# This should match what you defined in the corresponding
# `bazel_fuchsia_test_package` target.
#
# deps:
# Usual meaning, but all deps for all subtargets are
# forwarded to the group target.
#
# metadata, visibility:
# Usual meaning, but these values are _not_ forwarded
# to the group target.
#
# metadata: (optional)
# Metadata that is _only_ applied to the group target itself, not to
# its sub-targets.
#
# testonly (optional)
# Usual GN meaning, but applies to each subtarget as well as the group.
#
# visibility (optional)
# Usual GN meaning. A value provided here applies to the group target
# and also to each subtarget that does not have its own visibility definition.
#
template("bazel_test_package_group") {
_bazel_targets = []
_deps = []
_package_outputs = []
_extract_targets = []
_main_target = target_name
_build_action_target = "${_main_target}.bazel_build"
foreach(test, invoker.tests) {
assert(defined(test.test_component_names),
"Must define `test_component_names`")
_bazel_targets += [ test.test_package_target ]
_package_output_dir =
get_label_info(test.test_package_target, "target_out_dir") + "/" +
get_label_info(test.test_package_target, "name")
if (defined(test.test_package_name)) {
package_name = test.test_package_name
} else {
package_name = get_label_info(test.test_package_target, "name")
}
foreach(test_component_name, test.test_component_names) {
test_spec_target = "${package_name}.${test_component_name}"
_extract_target_name = "${package_name}.extract"
# Test metadata for `fx test` / test infra integration
test_spec(test_spec_target) {
if (defined(test.test_specs)) {
forward_variables_from(test.test_specs, "*")
}
package_url = "fuchsia-pkg://fuchsia.com/${package_name}#meta/${test_component_name}.cm"
target =
get_label_info(":${_extract_target_name}", "label_with_toolchain")
package_label =
get_label_info(":${_extract_target_name}", "label_with_toolchain")
package_manifests =
rebase_path([ "${_package_output_dir}/package_manifest.json" ],
root_build_dir)
build_rule = "bazel_test_package_group"
}
_deps += [ ":${test_spec_target}" ]
}
_package_outputs += [
{
package_label = test.test_package_target
archive = "${package_name}.far"
copy_debug_symbols = true
},
]
if (defined(test.deps)) {
# Loop over the deps individually, because the += / -= pattern doesn't
# work correctly if used with a list that contains duplicates (the -=
# step will fail with a "trying to remove X, but it wasn't there error")
foreach(dep, test.deps) {
_deps += [ dep ]
_deps -= [ dep ]
_deps += [ dep ]
}
}
package_tool_package_archive_extract(_extract_target_name) {
forward_variables_from(invoker, [ "visibility" ])
archive = "${target_out_dir}/${package_name}.far"
package_name = package_name
repository = "fuchsia.com"
package_out_dir = _package_output_dir
deps = [ ":${_build_action_target}" ]
testonly = true
}
_extract_targets += [ ":${_extract_target_name}" ]
}
bazel_action(_build_action_target) {
command = "build"
bazel_targets = _bazel_targets
deps = _deps
testonly = true
package_outputs = _package_outputs
forward_variables_from(
invoker,
"*",
[
# These arguments are handled above.
"deps",
# These arguments are specific to this template, and not
# passed to bazel_action().
"tests",
])
}
group(_main_target) {
testonly = true
deps = _extract_targets
}
}