| # Copyright 2019 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("$zx/public/gn/config/standard.gni") |
| import("$zx/public/gn/toolchain/environment.gni") |
| import("$zx/public/gn/toolchain/environment_redirect.gni") |
| |
| # Lists the names of the default set of sanitized variants used to build fuzzer |
| # binaries. Named lists of useful variant subsets are defined in standard.gni, |
| # e.g. $standard_sanitizer_variants. If at some point the fuuzers should be |
| # built with a different set of default variants, the set of named lists should |
| # be changed there to minimize duplication of individual items here. |
| _fuzzer_default_variants = [] |
| foreach(sanitizer, standard_sanitizer_variants) { |
| # Clear from last iteration. |
| _sanitizer_variant = { |
| } |
| _sanitizer_variant = sanitizer.variant |
| _fuzzer_default_variants += [ _sanitizer_variant.name ] |
| } |
| |
| # Produces a component manifest similar to that produces by the $cmx() |
| # invocation in //build/fuzzing/fuzzer.gni. These manifests don't have |
| # much meaning in a standalone Zircon, but are most easily generated alongside |
| # the fuzzers. |
| template("_fuzzer_cmx") { |
| assert(defined(invoker.name), "$target_name must define 'name'.") |
| fuzzer_name = "${invoker.name}.${toolchain.variant}" |
| generated_file(target_name) { |
| contents = { |
| program = { |
| binary = "bin/$fuzzer_name" |
| } |
| sandbox = { |
| services = [ "fuchsia.process.Launcher" ] |
| features = [ |
| "isolated-persistent-storage", |
| "isolated-temp", |
| ] |
| } |
| } |
| outputs = [ |
| "$target_gen_dir/$fuzzer_name.cmx", |
| ] |
| output_conversion = "json" |
| source = rebase_path(outputs[0], root_build_dir) |
| metadata = { |
| manifest_lines = [ "meta/$fuzzer_name.cmx=$source" ] |
| } |
| } |
| } |
| |
| # Builds fuzzer binaries using the libFuzzer fuzzing engine. |
| # |
| # See [libFuzzer](https://llvm.org/docs/LibFuzzer.html) for background on |
| # libFuzzer. To create a fuzzer, developers should specify the code being |
| # fuzzed in $deps, and provide an "LLVMFuzzerTestOneInput" fuzz target |
| # function for libFuzzer in $sources. |
| # |
| # The fuzzer() template below will build the fuzzer binary, link the engine, and |
| # instrument the $deps in an environment corresponding to an appropriate base |
| # environment. This means dependents on this target will get fuzzers for their |
| # base environment (e.g. host dependents will get host fuzzers, etc.). |
| # |
| # In order to be properly picked up by the //garnet/tests/zircon:zircon_fuzzers |
| # package, it is required that Zircon fuzzer names end in "-fuzzer", e.g. a |
| # fuzzer in $zx/system/ulib/foo might be named "foo-fuzzer". |
| # |
| # Parameters |
| # |
| # sanitizers |
| # Optional: A list of variant names as they appear in $variants. This |
| # controls which toolchain variants are used to build each fuzzer binary. |
| # This is only needed if a fuzzer should not be built with one or more of |
| # $fuzzer_default_variants. |
| # Type: list(string) |
| # Default: fuzzer_default_variants |
| # |
| # See executable() for additional parameters and details. |
| template("fuzzer") { |
| # Match any "*.fuzzer" environment ("*" is ${toolchain.base_environment}). |
| if (get_path_info(toolchain.environment, "extension") == "fuzzer") { |
| fuzzer_name = target_name |
| |
| # The test() template is used for programs that verify proper operation of |
| # associated code if the tests passes. This isn't an appropriate choice for |
| # fuzzers as they run indefinitely and never "pass". |
| zx_executable(fuzzer_name) { |
| testonly = true |
| |
| # Explicitly forward visibility for nested scope, and ensure the redirect |
| # is always visible. |
| forward_variables_from(invoker, |
| "*", |
| [ |
| "testonly", |
| "visibility", |
| ]) |
| forward_variables_from(invoker, [ "visibility" ]) |
| if (defined(visibility)) { |
| visibility += [ ":$fuzzer_name" ] |
| } |
| data_deps = [ |
| ":$fuzzer_name.cmx", |
| ] |
| metadata = { |
| fuzzer = [ "$fuzzer_name.${toolchain.variant}" ] |
| } |
| } |
| _fuzzer_cmx("$fuzzer_name.cmx") { |
| name = fuzzer_name |
| } |
| if (defined(invoker.sanitizers)) { |
| not_needed(invoker.sanitizers) |
| } |
| } else { |
| # Otherwise build sanitized variants in the fuzzer environment. |
| if (defined(invoker.sanitizers)) { |
| sanitizer_names = invoker.sanitizers |
| } else { |
| sanitizer_names = _fuzzer_default_variants |
| } |
| environment_redirect(target_name) { |
| testonly = true |
| forward_variables_from(invoker, [ "visibility" ]) |
| environment_label = |
| "$zx/public/gn/fuzzer:${toolchain.base_environment}.fuzzer" |
| direct = true |
| deps = [] |
| foreach(sanitizer, sanitizer_names) { |
| deps += [ ":$target_name.$sanitizer" ] |
| } |
| } |
| not_needed(invoker, "*") |
| } |
| } |