Add option and target for generating code cov info

The new `tint-generate-coverage` CMake target can be used with the clang toolchain to generate a `lcov.info` file at the root of the project, along with a `coverage.summary` human readable plain text file.

The `lcov.info` file can then be used by various tools to display code coverage information in your IDE / code editor.

Useful for ensuring decent test coverage.

Change-Id: I3d846f6da3af25d3d600d8e028f27b89e35b545f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/31121
Commit-Queue: Ben Clayton <bclayton@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 528671b..1d23434 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,8 @@
 option(TINT_ENABLE_ASAN "Enable address sanitizer" OFF)
 option(TINT_ENABLE_UBSAN "Enable undefined behaviour sanitizer" OFF)
 
+option(TINT_EMIT_COVERAGE "Emit code coverage information" OFF)
+
 option(TINT_CHECK_CHROMIUM_STYLE "Check for [chromium-style] issues during build" OFF)
 
 if(WIN32)
@@ -173,6 +175,18 @@
     endif()
   endif()
 
+  if (${TINT_EMIT_COVERAGE})
+    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")
+        target_compile_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
+        target_link_options(${TARGET} PRIVATE "-fprofile-instr-generate" "-fcoverage-mapping")
+    else()
+        message(FATAL_ERROR "Coverage generation not supported for the ${CMAKE_CXX_COMPILER_ID} toolchain")
+    endif()
+  endif()
+
   if (MSVC)
     # Specify /EHs for exception handling.
     target_compile_options(${TARGET} PRIVATE
@@ -228,3 +242,18 @@
   WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
   COMMENT "Running formatter"
   VERBATIM)
+
+
+if (${TINT_EMIT_COVERAGE} AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+  # Generates a lcov.info file at the project root.
+  # 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)
+  set(PATH_WITH_CLANG "${CLANG_BIN_DIR}:$ENV{PATH}")
+  add_custom_target(tint-generate-coverage
+    COMMAND ${CMAKE_COMMAND} -E env PATH=${PATH_WITH_CLANG} ./tools/tint-generate-coverage $<TARGET_FILE:tint_unittests>
+    DEPENDS tint_unittests
+    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+    COMMENT "Generating tint coverage data"
+    VERBATIM)
+endif()