I am building a number of sources and then running gcovr with JSON output:
foreach(COMPONENT IN LISTS BLAHDIBLAH)
...
add_custom_command(TARGET ${COMPONENT}_coverage
COMMAND gcovr --exclude-unreachable-branches -k -r ${CMAKE_CURRENT_SOURCE_DIR} --json -o ${COMPONENT}_coverage_lines.json ${CMAKE_BINARY_DIR}/CMakeFiles/${COMPONENT}_test.dir/${UNIT_PATH_${COMPONENT}}
COMMAND gcovr --exclude-unreachable-branches -k -r ${CMAKE_CURRENT_SOURCE_DIR} --json -b -o ${COMPONENT}_coverage_branches.json ${CMAKE_BINARY_DIR}/CMakeFiles/${COMPONENT}_test.dir/${UNIT_PATH_${COMPONENT}}
)
list(APPEND COV_DEPS ${COMPONENT}_coverage)
...
endforeach()
Later on, I add a coverage target to combine the gcovr output:
add_custom_target(coverage
COMMAND gcovr --exclude-unreachable-branches -k -r .. --add-tracefile coverage/*.json --html-details coverage/coverage.html
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
If I run make coverage, only the first source file is picked up by gcovr, but if I run the command manually:
gcovr --exclude-unreachable-branches -k -r .. --add-tracefile coverage/*.json --html-details coverage/coverage.html
... then all the sources are picked up.
Why does that command work in the terminal, but not in CMake?
The answer is in the custom target. The argument to
--add-tracefileneeds to be enclosed in speech-marks, which themselves need to be escaped: