blob: b59326846ebdbde095189dfe4402fe09fe843456 [file] [log] [blame]
# Copyright 2021 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/config/profile/config.gni")
import("//build/zircon/migrated_targets.gni")
if (toolchain_variant.tags + [ "llvm-profdata" ] - [ "llvm-profdata" ] !=
toolchain_variant.tags) {
have_llvm_profdata = 1
} else {
have_llvm_profdata = 0
}
zx_library("llvm-profdata") {
sdk = "source"
sdk_headers = [ "lib/llvm-profdata/llvm-profdata.h" ]
sources = [ "llvm-profdata.cc" ]
deps = []
public_deps = [ "//sdk/lib/stdcompat" ]
public_configs = [ ":have_llvm_profdata" ]
if (is_kernel) {
deps += [
"//zircon/kernel/lib/ktl",
"//zircon/kernel/lib/libc",
]
}
if (is_efi_toolchain) {
# Under PE-COFF, it doesn't work for the runtime itself to be instrumented.
# There's no way to reconcile direct use of the __llvm_profile_raw_version
# symbol in the source with the compiler-generated COMDAT definition in the
# same translation unit.
_profile_configs = [
"//build/config/profile:coverage",
"//build/config/profile",
]
configs += _profile_configs
configs -= _profile_configs
}
}
config("have_llvm_profdata") {
visibility = [ ":*" ]
defines = [ "HAVE_LLVM_PROFDATA=$have_llvm_profdata" ]
}
if (!is_kernel) {
import("//build/components.gni")
import("//build/test.gni")
group("tests") {
testonly = true
deps = [
":llvm-profdata-tests",
":llvm-profdata-unittests($host_toolchain)",
]
}
example_public = [ "coverage-example.h" ]
example_sources = [ "coverage-example.cc" ]
# This one file is always compiled with relocatable coverage support,
# regardless of the prevailing variant.
source_set("coverage-example") {
testonly = true
public = example_public
sources = example_sources
deps = [ ":coverage-example.deps" ]
# Make sure the LinkTimeDeadFunction is really dead at link time.
configs -= [ "//build/config:default_linker_gc" ]
configs += [ "//build/config:linker_gc" ]
# This test requires coverage instrumentation, so we disable the profile
# instrumentation if enabled by removing the profile config since
# -fprofile-instr-generate and -fprofile-generate are mutually
# incompatible. These flags both use the backend instrumentation pass, but
# the LLVM IR intrinsics are emitted at different stages and their
# combination is not supported.
configs += [ "//build/config/profile" ]
configs -= [ "//build/config/profile" ]
configs += [ "//build/config/profile:profile-use" ]
configs -= [ "//build/config/profile:profile-use" ]
}
# When an instrumented variant might be using selective instrumentation, this
# could prevent the example code from being instrumented. So in that case,
# extra compilation switches ensure that it will be.
group("coverage-example.deps") {
visibility = [ ":*" ]
testonly = true
public_configs = [ ":coverage-example.config" ]
if (selective_profiling) {
public_deps = [ ":coverage-example.list" ]
}
}
if (selective_profiling) {
# The compiler switch requires an input file, so generate one.
generated_file("coverage-example.list") {
visibility = [ ":*" ]
testonly = true
outputs = [ "$target_gen_dir/$target_name" ]
output_conversion = "list lines"
contents = []
foreach(file,
rebase_path(example_sources + example_public, root_build_dir)) {
contents += [ "src:$file" ]
}
}
}
config("coverage-example.config") {
visibility = [ ":*" ]
cflags = [
"-fprofile-instr-generate",
"-fcoverage-mapping",
]
if (current_os != "mac") {
cflags += [
"-mllvm",
"-runtime-counter-relocation=true",
]
}
# Explicitly select these source files to be instrumented. When no
# -fprofile-list switches are passed, everything is instrumented. But if
# the ambient configs used -fprofile-list, then only things selected in
# -fprofile-list files will be instrumented. Additional -fprofile-list
# files always add together, so adding another file with an explicit source
# file list adds those to the inclusion list. But note that including this
# file if no other -fprofile-list files prevents functions in other source
# files (i.e. headers used by the example sources) form being instrumented.
if (selective_profiling) {
inputs = get_target_outputs(":coverage-example.list")
cflags += [ "-fprofile-list=" + rebase_path(inputs[0], root_build_dir) ]
}
}
# When built in a variant without the instrumentation, the library code is
# stubbed out. For tests, use a separate compilation of its code that still
# lacks instrumentation itself but has the full runtime support enabled.
# The coverage-example code's data will be the only instrumentation data it
# finds.
if (have_llvm_profdata == 0) {
source_set("llvm-profdata-for-test") {
sources = [ "llvm-profdata.cc" ]
defines = [ "HAVE_LLVM_PROFDATA_OVERRIDE=1" ]
public_deps = [ ":llvm-profdata" ]
}
} else {
group("llvm-profdata-for-test") {
public_deps = [ ":llvm-profdata" ]
}
}
test("llvm-profdata-unittests") {
sources = [ "llvm-profdata-tests.cc" ]
deps = [
":coverage-example",
":llvm-profdata-for-test",
"//src/lib/elfldltl",
"//src/lib/fxl/test:gtest_main",
]
# Make sure the LinkTimeDeadFunction is really dead at link time.
configs -= [ "//build/config:default_linker_gc" ]
configs += [ "//build/config:linker_gc" ]
}
fuchsia_unittest_package("llvm-profdata-tests") {
deps = [ ":llvm-profdata-unittests" ]
}
}