cmake-scripts icon indicating copy to clipboard operation
cmake-scripts copied to clipboard

Excluding dependencies in code coverage reports

Open mscofield0 opened this issue 4 years ago • 11 comments

I am using CPM for managing dependencies in my project and since it is source-based (downloads the source and then builds it), llvm-cov finds and includes it in the code coverage report.

I am using the caching feature of CPM so everything is in a .cache/CPM directory.

What do you suggest I do?

mscofield0 avatar Apr 29 '21 10:04 mscofield0

Both the add_code_coverage_all_targets and target_code_coverage functions should have the ability to exclude files from being profiled with glob patterns:

add_code_coverage_all_targets(EXCLUDE .*/test/.*)
*or*
target_code_coverage(test_lib EXCLUDE .*/test/.*)

If you're using the add_code_coverage, it adds profiling to everything after the point where it's included, so something along the lines of:

*cpm_builds*

add_code_coverage()

*add_profiled_targets*

could work.

StableCoder avatar Apr 29 '21 12:04 StableCoder

The following doesn't work... I want to exclude the test directory and the dependencies stored at the CPM_SOURCE_CACHE. The current working directory of the CMakeLists.txt is test.

if(DEFINED ENV{CPM_SOURCE_CACHE})
  add_code_coverage_all_targets(EXCLUDE $ENV{CPM_SOURCE_CACHE}/.*)
else()
  add_code_coverage_all_targets(EXCLUDE build/.*)
endif()

target_code_coverage(Greeter)
target_code_coverage(GreeterTests AUTO .*)

mscofield0 avatar Apr 29 '21 15:04 mscofield0

Ah, I see.

To maintain flexibility between individual targets and the `all-type targets, they all maintain their own exclusion lists.

So in this case, I'm pretty sure that, with the code above, running ccov-all or similar, the results would have the CPM items excluded, and the individual ccov-Greeter and ccov-GreeterTests would still have them included.

So to resolve here, I believe you just have to add the same excludes to the individual target_code_coverage calls, ala:

if(DEFINED ENV{CPM_SOURCE_CACHE})
  add_code_coverage_all_targets(EXCLUDE $ENV{CPM_SOURCE_CACHE}/.* build/.*)
else()
  add_code_coverage_all_targets(EXCLUDE build/.*)
endif()

target_code_coverage(Greeter EXCLUDE $ENV{CPM_SOURCE_CACHE}/.* build/.*)
target_code_coverage(GreeterTests AUTO EXCLUDE .* $ENV{CPM_SOURCE_CACHE}/.*)

StableCoder avatar Apr 29 '21 20:04 StableCoder

I actually had an error in the above command, I didn't type EXCLUDE, but it doesn't seem to make a difference:

if(DEFINED ENV{CPM_SOURCE_CACHE})
  add_code_coverage_all_targets(EXCLUDE $ENV{CPM_SOURCE_CACHE}/.* build/.*)
else()
  add_code_coverage_all_targets(EXCLUDE build/.*)
endif()


target_code_coverage(Greeter EXCLUDE $ENV{CPM_SOURCE_CACHE}/.* build/.*)
target_code_coverage(GreeterTests AUTO EXCLUDE .* $ENV{CPM_SOURCE_CACHE}/.*)
/code-coverage.cmake:447 (add_dependencies):
  The dependency target "ccov-report-GreeterTests" of target "ccov-report"
  does not exist.

mscofield0 avatar Apr 29 '21 20:04 mscofield0

Alright, new theory.

After far too long, I think that the problem is that clang/LLVM excludes via a regex pattern, and GCC/lcov uses a globbing pattern. So try out having a pattern for both and see how that plays out:

if(DEFINED ENV{CPM_SOURCE_CACHE})
  add_code_coverage_all_targets(EXCLUDE 
# For LLVM/clang
$ENV{CPM_SOURCE_CACHE}/.* build/.*
# For GCC/lcov
$ENV{CPM_SOURCE_CACHE}/* */build/*
)
else()
  add_code_coverage_all_targets(EXCLUDE build/.* */build/*)
endif()


target_code_coverage(Greeter EXCLUDE $ENV{CPM_SOURCE_CACHE}/.* build/.* $ENV{CPM_SOURCE_CACHE}/* */build/*)
target_code_coverage(GreeterTests AUTO EXCLUDE .* * $ENV{CPM_SOURCE_CACHE}/.* $ENV{CPM_SOURCE_CACHE}/*)

See if that starts removing things?

StableCoder avatar Apr 30 '21 00:04 StableCoder

llvm-cov runs normally, but still doesn't exclude the directories we set.

And with gcc it just doesn't work (same error as before):

code-coverage.cmake:424 (add_dependencies):
  The dependency target "ccov-report-GreeterTests" of target "ccov-report"
  does not exist.

mscofield0 avatar Apr 30 '21 07:04 mscofield0

I'm having trouble reproducing this. Is there a repo/commit somewhere you can point me to with the issue?

StableCoder avatar May 04 '21 14:05 StableCoder

I've made it public https://github.com/mscofield0/ModernCppStarter

mscofield0 avatar May 04 '21 14:05 mscofield0

Alright, I've got something that's works for me, with your repo, try it out.

# ---- code coverage ----

if(DEFINED ENV{CPM_SOURCE_CACHE})
  set(CCOV_EXCLUDES $ENV{CPM_SOURCE_CACHE}/.* $ENV{CPM_SOURCE_CACHE}/*)
endif()
set(CCOV_EXCLUDES ${CMAKE_BINARY_DIR}/.* ${CMAKE_BINARY_DIR}/*)

add_code_coverage_all_targets(EXCLUDE ${CCOV_EXCLUDES})

target_code_coverage(Greeter EXCLUDE ${CCOV_EXCLUDES})
target_code_coverage(GreeterTests AUTO EXCLUDE ${CCOV_EXCLUDES})

The biggest thing that was wrecking me was the $ENV{CPM_SOURCE_CACHE}/, which if I didn't have it defined, meant that it was equivalent to '/', ie everything on a unix filesystem.

Secondly was the build/* items, which for GCC appears in the .info files with the full path, and thus starting with just 'build' would match almost nothing. CHanging these to the CMAKE_BINARY_DIR, which is the root of the generated build files, including what CPM brings in by default, means all that would be automatically excluded.

Also, if when running the GCC ccov you have an issue with the ccov-report target, update the CPMAddPackage for this repo from aa8c42bf67beee5568472f6db4676c0e9399c4ff to e07087b0682da7ae0d2d9f9292fa4a7a6c821067 or newer.

StableCoder avatar May 04 '21 23:05 StableCoder

It works on gcc lcov for me, but not for llvm-cov, the llvm-cov output remains the same as before.

This is the CMake code:

if(DEFINED ENV{CPM_SOURCE_CACHE})
  # file(GLOB_RECURSE CCOV_EXCLUDES CONFIGURE_DEPENDS $ENV{CPM_SOURCE_CACHE}/*)
  set(CCOV_EXCLUDES $ENV{CPM_SOURCE_CACHE}/.* $ENV{CPM_SOURCE_CACHE}/*)
endif()
# file(GLOB_RECURSE CCOV_EXCLUDES CONFIGURE_DEPENDS ${CMAKE_BINARY_DIR}/*)
set(CCOV_EXCLUDES ${CMAKE_BINARY_DIR}/.* ${CMAKE_BINARY_DIR}/*)

add_code_coverage_all_targets(EXCLUDE ${CCOV_EXCLUDES})

target_code_coverage(Greeter EXCLUDE ${CCOV_EXCLUDES})
target_code_coverage(GreeterTests AUTO EXCLUDE ${CCOV_EXCLUDES})

mscofield0 avatar May 05 '21 17:05 mscofield0

Bumping the issue

mscofield0 avatar May 27 '21 07:05 mscofield0