blob: 901e692039d534fc1ef50c64083b81f155feaf88 [file] [log] [blame]
# Copyright 2022 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/components/fuchsia_package.gni")
import("//build/components/fuchsia_test.gni")
import("//build/fuzzing/fuchsia_fuzzer_component.gni")
# Defines a package of fuzzers
#
# This template is used to bundle several fuzzers or fuzzer tests and their associated data into a
# single Fuchsia package. See //examples/fuzzers/BUILD.gn for examples.
#
# Parameters: Same as `fuchsia_test_package`, but with `test_components` replaced one or more of the
# following:
# cpp_fuzzer_components (optional)
# rust_fuzzer_components (optional)
# [list] A list of `fuchsia_*_component` targets for fuzzers in the indicated language. Each
# list is asscoiated with the corresponding list of sanitizers, e.g. each label in
# `cpp_fuzzers` is built as a fuzzer when the toolchain variant selected for that label
# matches an element of `_cpp_sanitizers`.
#
template("fuchsia_fuzzer_package") {
if (current_toolchain == default_toolchain) {
no_forward = [
"package_name",
"cpp_fuzzer_components",
"rust_fuzzer_components",
"test_components",
"visibility",
]
package_name = target_name
if (defined(invoker.package_name)) {
package_name = invoker.package_name
}
cpp_fuzzer_components = []
if (defined(invoker.cpp_fuzzer_components)) {
cpp_fuzzer_components = invoker.cpp_fuzzer_components
}
rust_fuzzer_components = []
if (defined(invoker.rust_fuzzer_components)) {
rust_fuzzer_components = invoker.rust_fuzzer_components
}
# Step 1: Determine which components to fuzz vs test based on which variants are active. This is
# eager, and may include components that don't end up being selected by a fuzzer variant. This
# is unlikely to happen with normal development workflows, but if it does, it will only
# advertise one or more fuzzer tests as fuzzers, which will produce a descriptive error message
# if run.
#
# TODO(https://fxbug.dev/42056967): Make this less eager, e.g. by extending test_spec to include metadata
# from the binary itself, or by making the fuzzer vs test a runtime determination.
can_fuzz_cpp = false
can_fuzz_rust = false
foreach(selector, select_variant_canonical) {
selector_host = defined(selector.host) && selector.host
# TODO(https://fxbug.dev/42124940): Add LSan.
if (!selector_host && selector.variant == "asan-fuzzer") {
can_fuzz_cpp = true
can_fuzz_rust = true
}
if (!selector_host && selector.variant == "ubsan-fuzzer") {
can_fuzz_rust = true
}
}
component_sets = [
{
components = cpp_fuzzer_components
is_fuzzed = can_fuzz_cpp
},
{
components = rust_fuzzer_components
is_fuzzed = can_fuzz_rust
},
]
# Step 2: Assemble a package and add both fuzzers and fuzzer tests to it.
package_target = "${package_name}_package"
fuchsia_package(package_target) {
testonly = true
visibility = [ ":*" ]
package_name = package_name
deps = []
forward_variables_from(invoker, "*", no_forward)
forward_variables_from(invoker, [ "visibility" ])
deps += cpp_fuzzer_components
deps += rust_fuzzer_components
}
# Step 3: Register fuzzers and fuzzer tests. The former are distinguished from the latter by a
# fuzzer-specific `build_rule`.
group_deps = [ ":$package_target" ]
foreach(component_set, component_sets) {
foreach(component, component_set.components) {
component_name = get_label_info(component, "name")
test_target = "${component_name}_test"
fuchsia_test(test_target) {
package = ":$package_target"
package_name = package_name
component = component
if (component_set.is_fuzzed) {
build_rule = "fuchsia_fuzzer_package"
}
# Fuzzer tests may produce errors so long as they do not crash.
log_settings = {
max_severity = "ERROR"
}
}
group_deps += [ ":$test_target" ]
}
}
# Step 4: Add the package and test registrations to a group with the `target_name`.
group(target_name) {
testonly = true
forward_variables_from(invoker, [ "visibility" ])
deps = group_deps
}
} else {
group(target_name) {
testonly = true
forward_variables_from(invoker, [ "visibility" ])
deps = [ ":$target_name($default_toolchain)" ]
}
not_needed(invoker, "*")
}
}