blob: f470ac2588faeb1038150444372fcf1d9fd6d40f [file] [log] [blame]
# Copyright 2020 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
import("//build_overrides/pigweed.gni")
import("$dir_pw_build/error.gni")
import("$dir_pw_build/target_types.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_third_party/fuzztest/fuzztest.gni")
import("$dir_pw_unit_test/test.gni")
config("public_include_path") {
include_dirs = [ "public" ]
visibility = [ ":*" ]
}
config("private_include_path") {
include_dirs = [ "private" ]
visibility = [ ":*" ]
}
config("overrides_include_path") {
include_dirs = [
"public_overrides",
"private_overrides",
]
visibility = [ ":*" ]
}
# See https://llvm.org/docs/LibFuzzer.html#fuzzer-friendly-build-mode
config("fuzzing_build_mode_unsafe_for_production") {
defines = [ "FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" ]
}
pw_doc_group("docs") {
sources = [
"concepts.rst",
"docs.rst",
"guides/fuzztest.rst",
"guides/index.rst",
"guides/libfuzzer.rst",
"guides/reproducing_oss_fuzz_bugs.rst",
]
inputs = [
"doc_resources/pw_fuzzer_coverage_guided.png",
"examples/fuzztest/BUILD.gn",
"examples/fuzztest/BUILD.bazel",
"examples/fuzztest/CMakeLists.txt",
"examples/fuzztest/metrics.h",
"examples/fuzztest/metrics_unittest.cc",
"examples/fuzztest/metrics_fuzztest.cc",
]
}
pw_test_group("tests") {
group_deps = [
":fuzztest_tests",
"examples/fuzztest:tests",
"examples/libfuzzer:tests",
]
}
################################################################################
# FuzzTest support
#
# Create FuzzTest-style fuzzers by adding a dep on dir_pw_fuzzer:fuzztest
group("fuzztest") {
if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) {
public_deps = [ ":fuzztest.enabled" ]
} else {
public_deps = [ ":fuzztest.disabled" ]
}
}
# Used by fuzzable unit tests when fuzzing is enabled. Includes headers and deps
# that provide a Pigweed-compatible subset of FuzzTest, as well as extensions to
# support common Pigweed types.
if (dir_pw_third_party_fuzztest != "" && pw_toolchain_FUZZING_ENABLED) {
pw_source_set("fuzztest.enabled") {
public = [
"private/pw_fuzzer/internal/fuzztest.h",
"public/pw_fuzzer/fuzztest.h",
]
public_configs = [
":public_include_path",
":private_include_path",
]
public_deps = [
"$dir_pw_third_party/fuzztest/fuzztest:fuzztest_core",
dir_pw_containers,
dir_pw_result,
dir_pw_status,
dir_pw_string,
]
}
}
# Used by fuzzable unit tests when fuzzing is disabled. Includes stubs of the
# Pigweed-compatible subset of FuzzTest's interface, as well as extensions to
# support common Pigweed types.
pw_source_set("fuzztest.disabled") {
public = [
"private_overrides/pw_fuzzer/internal/fuzztest.h",
"public/pw_fuzzer/fuzztest.h",
"public_overrides/fuzztest/fuzztest.h",
]
public_configs = [
":public_include_path",
":overrides_include_path",
]
public_deps = [
dir_pw_containers,
dir_pw_result,
dir_pw_status,
dir_pw_string,
]
}
pw_test("fuzztest_tests") {
sources = [ "domain_test.cc" ]
deps = [ ":fuzztest" ]
}
# This target should only be used when defining a fuzzing toolchain, e.g. to set
# `pw_unit_test_BACKEND = "$dir_pw_fuzzer:gtest"
# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz.
if (dir_pw_third_party_googletest == "") {
pw_error("gtest") {
message_lines = [
"pw_unit_test_BACKEND is set to dir_pw_fuzzer:gtest, ",
"but dir_pw_third_party_googletest is not set.",
]
}
} else if (!pw_toolchain_FUZZING_ENABLED) {
pw_error("gtest") {
message_lines = [
"pw_unit_test_BACKEND is set to dir_pw_fuzzer:gtest, ",
"but $current_toolchain does not support fuzzing.",
]
}
} else {
group("gtest") {
if (pw_toolchain_OSS_FUZZ_ENABLED) {
public_deps = [ "$dir_pw_unit_test:light" ]
} else {
public_deps = [ "$dir_pw_unit_test:googletest" ]
}
}
}
# This target should only be used when defining a fuzzing toolchain, e.g. to set
# `pw_unit_test_MAIN = "$dir_pw_fuzzer:fuzztest_main"
# TODO: b/295961502 - Support running FuzzTest-based fuzzers on OSS-Fuzz.
if (dir_pw_third_party_fuzztest == "") {
pw_error("fuzztest_main") {
message_lines = [
"pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ",
"but dir_pw_third_party_fuzztest is not set.",
]
}
} else if (!pw_toolchain_FUZZING_ENABLED) {
pw_error("fuzztest_main") {
message_lines = [
"pw_unit_test_MAIN is set to dir_pw_fuzzer:fuzztest_main, ",
"but $current_toolchain does not support fuzzing.",
]
}
} else {
group("fuzztest_main") {
if (pw_toolchain_OSS_FUZZ_ENABLED) {
deps = [ "$dir_pw_unit_test:simple_printing_main" ]
} else {
deps = [ "$dir_pw_third_party/fuzztest/fuzztest:fuzztest_gtest_main" ]
}
}
}
################################################################################
# libFuzzer support
#
# Create libFuzzer-style fuzzers by using the `pw_fuzzer` template from
# fuzzer.gni.
# Add flags for linking against compiler-rt's libFuzzer. This is added
# automatically by `pw_fuzzer`.
config("libfuzzer_config") {
ldflags = [ "-fsanitize=fuzzer" ]
}
# Includes wrapper's for LLVM's libFuzzer compiler runtime library.
pw_source_set("libfuzzer") {
public = [
"public/pw_fuzzer/asan_interface.h",
"public/pw_fuzzer/fuzzed_data_provider.h",
]
public_configs = [ ":public_include_path" ]
public_deps = [ dir_pw_log ]
}
# This can be linked against fuzz target functions to create unit tests for
# them.
pw_source_set("libfuzzer_test") {
testonly = pw_unit_test_TESTONLY
sources = [ "pw_fuzzer_disabled.cc" ]
public_deps = [ ":libfuzzer" ]
deps = [ dir_pw_unit_test ]
}
# libFuzzer-based fuzzers have a distinct dep graph.
group("fuzzers") {
deps = [ "examples/libfuzzer:fuzzers" ]
}
################################################################################
# Local fuzzing support
# Add flags for adding LLVM sanitizer coverage for fuzzing. This is added by
# the host_clang_fuzz toolchains.
config("instrumentation") {
cflags = [ "-fsanitize=fuzzer-no-link" ]
}
################################################################################
# OSS-Fuzz support
#
# OSS-Fuzz manipulates compiler and linker flags directly. See
# google.github.io/oss-fuzz/getting-started/new-project-guide/#Requirements.
#
# WARNING: This is not hermetic by design. It never can be, and never will be.
config("oss_fuzz_instrumentation") {
cflags_c = string_split(getenv("CFLAGS"))
cflags_cc = string_split(getenv("CXXFLAGS"))
# OSS-Fuzz sets "-stdlib=libc++", which conflicts with the "-nostdinc++" set
# by `pw_minimal_cpp_stdlib`.
if (cflags_cc + [ "-stdlib=libc++" ] - [ "-stdlib=libc++" ] != cflags_cc) {
cflags_cc += [ "-Wno-unused-command-line-argument" ]
}
# Disable UBSan vptr when the target is built with -fno-rtti.
if (cflags_cc + [ "-fno-rtti" ] - [ "-fno-rtti" ] != cflags_cc) {
cflags_cc += [ " -fno-sanitize=vptr" ]
}
cflags_cc += [ "-fcoverage-compilation-dir=" + getenv("PW_ROOT") ]
ldflags = cflags_cc + [ "-fuse-ld=lld" ]
}
config("libfuzzer_oss_fuzz_config") {
engine = getenv("LIB_FUZZING_ENGINE")
if (engine == "") {
engine = "-fsanitize=fuzzer"
}
ldflags = [ engine ]
}