code-coverage / turbocov fixes
Common: * The turbocov build target (somehow) never got hooked up to the root CMakeLists.txt file. This is now fixed. macOS: * Emit coverage for 'AppleClang' compiler. * Have run-cts find the tucked-away `llvm-profdata` executable. Windows: * Various fixes for building with clang * Fix turbocov stdout CRLF corruption * Fix bad JSON with backslashes Change-Id: I481cceafe2e72b544e13168172fc1456e5df2005 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/117880 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Kokoro: Ben Clayton <bclayton@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
b4049dcf40
commit
78e4530f59
|
@ -347,7 +347,7 @@ function(common_compile_options TARGET)
|
|||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
target_compile_options(${TARGET} PRIVATE "--coverage")
|
||||
target_link_options(${TARGET} PRIVATE "gcov")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
elseif(COMPILER_IS_CLANG OR COMPILER_IS_CLANG_CL)
|
||||
target_compile_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
|
||||
target_link_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
|
||||
else()
|
||||
|
@ -451,10 +451,13 @@ if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND (CMAKE_CXX_SIMULATE_ID STREQUAL
|
|||
set(COMPILER_IS_CLANG_CL TRUE)
|
||||
endif()
|
||||
|
||||
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
|
||||
if((CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
|
||||
((CMAKE_CXX_COMPILER_ID STREQUAL "Clang") AND
|
||||
(NOT COMPILER_IS_CLANG_CL)))
|
||||
set(COMPILER_IS_CLANG TRUE)
|
||||
endif()
|
||||
|
||||
if((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR COMPILER_IS_CLANG)
|
||||
set(COMPILER_IS_LIKE_GNU TRUE)
|
||||
endif()
|
||||
|
||||
|
@ -555,8 +558,7 @@ function(tint_default_compile_options TARGET)
|
|||
${COMMON_GNU_OPTIONS}
|
||||
)
|
||||
|
||||
if (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") OR
|
||||
("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang"))
|
||||
if (COMPILER_IS_CLANG)
|
||||
target_compile_options(${TARGET} PRIVATE
|
||||
${COMMON_CLANG_OPTIONS}
|
||||
)
|
||||
|
@ -655,9 +657,11 @@ add_custom_target(tint-format
|
|||
COMMENT "Running formatter"
|
||||
VERBATIM)
|
||||
|
||||
if (DAWN_EMIT_COVERAGE)
|
||||
add_subdirectory(tools/src/cmd/turbo-cov)
|
||||
|
||||
if (DAWN_EMIT_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# Generates a lcov.info file at the project root.
|
||||
# The tint-generate-coverage target generates a lcov.info file at the project
|
||||
# root, holding the code coverage for all the tint_unitests.
|
||||
# This can be used by tools such as VSCode's Coverage Gutters extension to
|
||||
# visualize code coverage in the editor.
|
||||
get_filename_component(CLANG_BIN_DIR ${CMAKE_C_COMPILER} DIRECTORY)
|
||||
|
|
|
@ -102,8 +102,14 @@ if (WIN32)
|
|||
# Generate the NapiSymbols.lib from the NapiSymbols.def file
|
||||
set(NAPI_SYMBOLS_LIB "${DAWN_NODE_GEN_DIR}/NapiSymbols.lib")
|
||||
# Resolve path to lib.exe
|
||||
get_filename_component(VS_BIN_DIR "${CMAKE_LINKER}" DIRECTORY)
|
||||
set(LIB_EXE "${VS_BIN_DIR}/lib.exe")
|
||||
get_filename_component(LINKER_BIN_DIR "${CMAKE_LINKER}" DIRECTORY)
|
||||
if (EXISTS "${LINKER_BIN_DIR}/lib.exe")
|
||||
set(LIB_EXE "${LINKER_BIN_DIR}/lib.exe")
|
||||
elseif (EXISTS "${LINKER_BIN_DIR}/lld-link.exe")
|
||||
set(LIB_EXE "${LINKER_BIN_DIR}/lld-link.exe")
|
||||
else()
|
||||
message(FATAL_ERROR "unable to find lib.exe or lld-link.exe")
|
||||
endif()
|
||||
add_custom_command(
|
||||
COMMAND "${LIB_EXE}"
|
||||
"/DEF:${NAPI_SYMBOLS_DEF}"
|
||||
|
|
|
@ -62,7 +62,7 @@ Napi::Value CreateGPU(const Napi::CallbackInfo& info) {
|
|||
#ifdef DAWN_EMIT_COVERAGE
|
||||
struct Coverage {
|
||||
Coverage() : output_path_{GetOutputPath()} {
|
||||
__llvm_profile_set_filename(output_path_.c_str());
|
||||
__llvm_profile_set_filename(output_path_.string().c_str());
|
||||
}
|
||||
~Coverage() { std::filesystem::remove(output_path_); }
|
||||
|
||||
|
@ -75,7 +75,7 @@ struct Coverage {
|
|||
static Napi::Value End(const Napi::CallbackInfo& info) {
|
||||
__llvm_profile_write_file();
|
||||
auto* coverage = static_cast<Coverage*>(info.Data());
|
||||
return Napi::String::New(info.Env(), coverage->output_path_.c_str());
|
||||
return Napi::String::New(info.Env(), coverage->output_path_.string().c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -259,17 +259,36 @@ func run() error {
|
|||
}
|
||||
|
||||
if genCoverage {
|
||||
llvmCov, err := exec.LookPath("llvm-cov")
|
||||
dawnOutDir := filepath.Dir(dawnNode)
|
||||
|
||||
profdata, err := exec.LookPath("llvm-profdata")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find LLVM, required for --coverage")
|
||||
profdata = ""
|
||||
if runtime.GOOS == "darwin" {
|
||||
profdata = "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/llvm-profdata"
|
||||
if !fileutils.IsExe(profdata) {
|
||||
profdata = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
turboCov := filepath.Join(filepath.Dir(dawnNode), "turbo-cov"+fileutils.ExeExt)
|
||||
if profdata == "" {
|
||||
return fmt.Errorf("failed to find llvm-profdata, required for --coverage")
|
||||
}
|
||||
|
||||
llvmCov := ""
|
||||
turboCov := filepath.Join(dawnOutDir, "turbo-cov"+fileutils.ExeExt)
|
||||
if !fileutils.IsExe(turboCov) {
|
||||
turboCov = ""
|
||||
if path, err := exec.LookPath("llvm-cov"); err == nil {
|
||||
llvmCov = path
|
||||
} else {
|
||||
return fmt.Errorf("failed to find turbo-cov or llvm-cov")
|
||||
}
|
||||
}
|
||||
r.covEnv = &cov.Env{
|
||||
LLVMBin: filepath.Dir(llvmCov),
|
||||
Profdata: profdata,
|
||||
Binary: dawnNode,
|
||||
Cov: llvmCov,
|
||||
TurboCov: turboCov,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
|
||||
#include "llvm/ProfileData/InstrProfReader.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <fcntl.h> // _O_BINARY
|
||||
#include <io.h> // _setmode
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
|
@ -40,6 +45,13 @@ void emit(const llvm::StringRef& str) {
|
|||
} // namespace
|
||||
|
||||
int main(int argc, const char** argv) {
|
||||
#if defined(_MSC_VER)
|
||||
// Change stdin & stdout from text mode to binary mode.
|
||||
// This ensures sequences of \r\n are not changed to \n.
|
||||
_setmode(_fileno(stdin), _O_BINARY);
|
||||
_setmode(_fileno(stdout), _O_BINARY);
|
||||
#endif
|
||||
|
||||
if (argc < 3) {
|
||||
fprintf(stderr, "turbo-cov <exe> <profdata>\n");
|
||||
return 1;
|
||||
|
|
|
@ -42,9 +42,10 @@ type Coverage struct {
|
|||
|
||||
// Env holds the environment settings for performing coverage processing.
|
||||
type Env struct {
|
||||
LLVMBin string // path to the LLVM bin directory
|
||||
Profdata string // path to the llvm-profdata tool
|
||||
Binary string // path to the executable binary
|
||||
TurboCov string // path to turbo-cov (optional)
|
||||
Cov string // path to the llvm-cov tool (one of Cov or TurboCov must be supplied)
|
||||
TurboCov string // path to the turbo-cov tool (one of Cov or TurboCov must be supplied)
|
||||
}
|
||||
|
||||
// RuntimeEnv returns the environment variable key=value pair for setting
|
||||
|
@ -92,33 +93,37 @@ func (e Env) AllSourceFiles() *Coverage {
|
|||
// Import uses the llvm-profdata and llvm-cov tools to import the coverage
|
||||
// information from a .profraw file.
|
||||
func (e Env) Import(profrawPath string) (*Coverage, error) {
|
||||
llvmProfdataExe := filepath.Join(e.LLVMBin, "llvm-profdata"+fileutils.ExeExt)
|
||||
llvmCovExe := filepath.Join(e.LLVMBin, "llvm-cov"+fileutils.ExeExt)
|
||||
|
||||
profdata := profrawPath + ".profdata"
|
||||
defer os.Remove(profdata)
|
||||
|
||||
if err := exec.Command(
|
||||
llvmProfdataExe,
|
||||
if e.Profdata == "" {
|
||||
return nil, fmt.Errorf("cov.Env.Profdata must be specified")
|
||||
}
|
||||
if e.TurboCov == "" && e.Cov == "" {
|
||||
return nil, fmt.Errorf("One of cov.Env.TurboCov or cov.Env.Cov must be specified")
|
||||
}
|
||||
|
||||
if out, err := exec.Command(
|
||||
e.Profdata,
|
||||
"merge",
|
||||
"-sparse",
|
||||
profrawPath,
|
||||
"-output",
|
||||
profdata).Run(); err != nil {
|
||||
return nil, fmt.Errorf("llvm-profdata errored: %w", err)
|
||||
profdata).CombinedOutput(); err != nil {
|
||||
return nil, fmt.Errorf("llvm-profdata errored: %w\n%v", err, string(out))
|
||||
}
|
||||
defer os.Remove(profdata)
|
||||
|
||||
if e.TurboCov == "" {
|
||||
data, err := exec.Command(
|
||||
llvmCovExe,
|
||||
e.Cov,
|
||||
"export",
|
||||
e.Binary,
|
||||
"-instr-profile="+profdata,
|
||||
"-format=text",
|
||||
"-skip-expansions",
|
||||
"-skip-functions").Output()
|
||||
"-skip-functions").CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("llvm-cov errored: %v\n%v", string(err.(*exec.ExitError).Stderr), err)
|
||||
return nil, fmt.Errorf("llvm-cov errored: %v\n%v", string(data), err)
|
||||
}
|
||||
cov, err := e.parseCov(data)
|
||||
if err != nil {
|
||||
|
@ -127,9 +132,9 @@ func (e Env) Import(profrawPath string) (*Coverage, error) {
|
|||
return cov, nil
|
||||
}
|
||||
|
||||
data, err := exec.Command(e.TurboCov, e.Binary, profdata).Output()
|
||||
data, err := exec.Command(e.TurboCov, e.Binary, profdata).CombinedOutput()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("turbo-cov errored: %v\n%v", string(err.(*exec.ExitError).Stderr), err)
|
||||
return nil, fmt.Errorf("turbo-cov errored: %v\n%v", string(data), err)
|
||||
}
|
||||
cov, err := e.parseTurboCov(data)
|
||||
if err != nil {
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"compress/zlib"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
@ -156,7 +157,7 @@ func (t *Tree) writeFilesJSON(spansByID map[SpanID]Span, sb *strings.Builder) {
|
|||
sb.WriteString(`,`)
|
||||
}
|
||||
sb.WriteString(`"`)
|
||||
sb.WriteString(path)
|
||||
sb.WriteString(filepath.ToSlash(path))
|
||||
sb.WriteString(`":`)
|
||||
sb.WriteString(`{`)
|
||||
if totalLines := file.allSpans.NumLines(); totalLines > 0 {
|
||||
|
|
Loading…
Reference in New Issue