| # 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, "*") |
| } |
| } |