如何正确处理 GCC 测试覆盖率分析的输出目录?

How do I correctly handle output directories for GCC test coverage profiling?

我正在尝试为我的单元测试生成覆盖率数据,最终目标是将所述数据显示为我们自动构建输出的一部分。

我们使用 makefile 和 cs-make 构建,cxxtest 作为单元测试框架。自动生成的测试运行器文件是 C++,我们所有的应用程序文件都是 C.

单元测试可执行文件的单元测试目标和配方是:

.SECONDEXPANSION:
UnitTest/%.exe: UnitTest/Tests/$$*/$$*Tests_cxx.cpp
    cs-rm *.gcda
    ..\cxxtest\bin\cxxtestgen --error-printer -o $@ $(addsuffix .h, $(basename $@))
    gcc -ftest-coverage -fprofile-arcs $(INCLUDES) $($*_SOURCES) -o $@
    ./$@
    gcovr -v

根据情况使用$(INCLUDES)$(SOURCES)

配方由运行执行(例如)

cs-make cs-make -C TestPlatform -f UnitTest\makefile UnitTest\Test1.exe

这会构建 Test1.exe 并生成 .gcno 文件。 Test1.exe 运行并生成 .gcda 个文件。 gcovr 正确解释这些文件并输出覆盖率数据。

到目前为止,还不错。但我们实际上是通过执行 运行 并行构建和 运行 多个单元测试:

cs-make -C TestPlatform -j -f UnitTest\makefile UnitTest\all

其中 all 依赖于所有定义的单元测试可执行文件。

为了支持并行构建,我在 GCC 调用中添加了这个选项:

-fprofile-dir=UnitTest/Tests/$*/Coverage

它将每个可执行文件的 .gcda 文件放在单独的目录中。

但是现在,gcovr 无法正确处理文件:

gcovr -v
Filters for --root: (1)
- <_sre.SRE_Pattern object at 0x0000000004FED600>
Filters for --filter: (1)
- DirectoryPrefixFilter(C\:\/Workspace\/CoverageTest\/TestPlatform\/)
Filters for --exclude: (0)
Filters for --gcov-filter: (1)
- AlwaysMatchFilter()
Filters for --gcov-exclude: (0)
Filters for --exclude-directories: (0)
Scanning directory . for gcda/gcno files...
Found 6 files (and will process 4)
Pool started with 1 threads
Processing file: C:\Workspace\CoverageTest\TestPlatform\UnitTest\Tests\Test1\Coverage\coverage.gcda
Running gcov: 'gcov C:\Workspace\CoverageTest\TestPlatform\UnitTest\Tests\Test1\Coverage\coverage.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory C:\Workspace\CoverageTest\TestPlatform\UnitTest\Tests\Test1\Coverage' in 'c:\users\jfowkes\appdata\local\temp\tmpdfjja7'
Processing file: C:\Workspace\CoverageTest\TestPlatform\Test1Tests_cxx.gcda
Running gcov: 'gcov C:\Workspace\CoverageTest\TestPlatform\Test1Tests_cxx.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory C:\Workspace\CoverageTest\TestPlatform' in 'c:\users\jfowkes\appdata\local\temp\tmpdfjja7'
Processing file: C:\Workspace\CoverageTest\TestPlatform\coverage.gcda
Running gcov: 'gcov C:\Workspace\CoverageTest\TestPlatform\coverage.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory C:\Workspace\CoverageTest\TestPlatform' in 'c:\users\jfowkes\appdata\local\temp\tmpdfjja7'
Processing file: C:\Workspace\CoverageTest\TestPlatform\UnitTest\Tests\Test1\Coverage\Test1Tests_cxx.gcda
Running gcov: 'gcov C:\Workspace\CoverageTest\TestPlatform\UnitTest\Tests\Test1\Coverage\Test1Tests_cxx.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory C:\Workspace\CoverageTest\TestPlatform\UnitTest\Tests\Test1\Coverage' in 'c:\users\jfowkes\appdata\local\temp\tmpdfjja7'
Gathered coveraged data for 0 files
------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
------------------------------------------------------------------------------
TOTAL                                          0       0    --%
------------------------------------------------------------------------------
cs-make: Leaving directory `C:/Workspace/CoverageTest/TestPlatform'

gcovr 似乎正在寻找文件并将它们交给 gcov,但没有覆盖率数据出来。

我尝试了各种不同的 gcovr 选项,但 none 似乎让这一切变得更好。

我是 运行 这个基于 Windows 10 的 Eclipse CDT - 这是我们的要求。根据其他答案,我怀疑可能存在路径 and/or 目录分隔符问题,但实际上我现在不确定任何事情。

我的问题是:我需要通过 makefile 进行哪些更改,以便我可以将此覆盖率数据添加到我们的构建中,从而继续支持并行构建?

我当然可以重组我们的单元测试以拥有一个 makefile-per-unit-test-suite,但这是大量的工作,我想尽可能避免它。

问题是 gcovr/gcov 需要将覆盖率数据与源文件相关联才能生成覆盖率报告,而 -fprofile-dir 的使用使这变得困难。 AFAIK gcovr 目前无法正确处理这种情况。 Gcovr 的 --object-directory 选项在这种情况下无法提供帮助。

考虑 cd 进入执行构建的临时目录。所以粗略地说,从

gcc --coverage test/source.c -o testfoo
./testfoo
gcovr

[[ -d build-foo ]] || mkdir build-foo
cd build-foo && gcc --coverage ../test/source.c -o testfoo
cd build-foo && ./testfoo
cd build-foo && gcovr -r ../test

不幸的是,这将是您的“每个测试套件生成文件”方法的变体。

另一种选择可能是 运行 在其他目录中并行测试,然后一次将一个测试套件的覆盖率数据复制回您的构建目录。这需要您为 GCOV_PREFIX 环境变量提供适当的路径。这与在交叉编译环境中使用 gcovr 的过程相同,正如 gocarlos 在 gcovr 问题跟踪器上所解释的那样:https://github.com/gcovr/gcovr/issues/259#issuecomment-406788661