【问题标题】:How can I do code coverage from multiple source files using gcov? Getting "has arcs to entry block"如何使用 gcov 从多个源文件中进行代码覆盖?获得“有弧进入块”
【发布时间】:2020-06-22 21:56:58
【问题描述】:

我有一个包含大量源文件的项目。然后将它们编译为.o 对象,最后与main.o 链接以生成main.exe。我正在使用 gcc 使用 --coverage -O0 编译所有文件(source1.csource2.cmain.c),为每个文件生成 .o.gcno。然后,我将所有内容链接在一起并调用main.exe,再次为每个目标文件生成.gcda 文件。

当我运行gcov source1.o source2.o main.o 时收到警告?错误?每个函数两次:

./tests/source1.gcno:'build' has arcs to entry block
./tests/source1.gcno:'build' has arcs from exit block

问题在于,这会使终端充满这些消息并且需要很长时间才能完成。我在 SO 中只能找到 this,所以我检查了 gcc 和 gcov 的版本:

$ gcc --version
gcc.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ gcov --version
gcov (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.

然而,这个问题对我帮助不大。我正在使用安装了巧克力的 MinGW-w64。我在互联网上也找不到任何使用 gcov 和多个源文件的示例,因此标题。

我不知道到底出了什么问题,因为我已经被这个问题困扰了一个星期了。我的项目确实运行并产生了代码覆盖率,但是这些成千上万的警告使我的 CI 消息过长。

另外,如果有人能更好地解释警告消息的含义,我将不胜感激。

编辑:

我用来编译main.c的标志示例:

gcc -Wall -Werror --coverage -O0 -lgcov -I ./tests/include -I ./src -c ./tests/main.c -o ./tests/build/main.o

【问题讨论】:

    标签: c gcov


    【解决方案1】:
    gcov source1.o source2.o main.o
    

    没有。那是行不通的。它的工作原理是这样的:

    • 你用--coverage编译你的程序
      • --coverage 插入整个程序语句,例如 fprintf(<some log file>, "I was here")
      • 此类fprintf 语句会在每个进入/退出函数、每个if 进入/退出、每个流进入/退出等上生成。
    • 然后你执行你的程序
      • 在程序执行期间,fprintf 语句会被执行。
      • 会创建一个日志文件,其中包含来自所有可执行文件的“我曾在这里”信息。
    • 然后您的程序终止。
    • 然后你在结果日志文件上执行gcov

    我在互联网上也找不到任何使用 gcov 和多个源文件的示例

    @edit 从单个源文件到三个源文件。

    示例:让我们获取一些源文件1.c 2.c 3.c 和一个makefile:

    cat >1.c <<EOF
    main() {
        func(0);
    }
    EOF
    
    cat >2.c <<EOF
    int func(int a) {
        if (a) {
            printf("Never here\n");
        }
        printf("Always here\n");
    }
    EOF
    
    cat >3.c <<EOF
    int func2(int b) {
        if (b == 1) {
            printf("func2\n");
        }
        printf("func2 no \n");
        return b + 1;
    }
    EOF
    
    cat >Makefile <<EOF
    CFLAGS=--coverage
    a.out: 1.o 2.o 3.o
        $(CC) $(CFLAGS) $^
    
    EOF
    

    我们编译这些并执行

    $ make
    cc --coverage   -c -o 1.o 1.c
    cc --coverage   -c -o 2.o 2.c
    cc --coverage   -c -o 3.o 3.c
    cc --coverage 1.o 2.o 3.o
    

    然后我们运行可执行文件

    $ ./a.out
    Always here
    

    新文件已创建:

    $ ls
    1.c  1.c.gcov  1.gcda  1.o  2.c  2.c.gcov  2.gcda  2.o  3.c  3.c.gcov  3.gcda  3.o  Makefile  a.out*
    

    然后你可以在那些文件上执行gcov

    $ gcov *.gcno
    File '1.c'
    Lines executed:100.00% of 2
    Creating '1.c.gcov'
    
    File '2.c'
    Lines executed:80.00% of 5
    Creating '2.c.gcov'
    
    File '3.c'
    Lines executed:0.00% of 5
    Creating '3.c.gcov'
    

    您可以检查生成的1.c.gcov 文件。

    在目标文件上执行gcov 没有意义。 gcov 解析来自执行的信息。不需要-lgcov - 只需要--coverage--coverage 本身就可以使用-lgcov)。

    【讨论】:

    • 即使我在目标文件上执行gcov,我仍然得到覆盖结果。现在我更改为.gcda 文件,我仍然得到相同的结果。我还删除了-lgcov。我也找不到您的示例非常有用,因为 >“我也无法在互联网上找到任何使用 gcov 和多个源文件的示例,因此标题。”
    • ?您只需从多个源文件编译可执行文件,然后在生成的文件上运行 gcov.. I also couldn't find any examples on the internet using gcov with multiple source files .... 好的。 gcov 自动“找到”它的文件,所以如果你给它提供目标文件,它会尝试在与目标文件相同的目录中搜索 gcda 文件。因此,如果您执行gcov file.o,gcov 将搜索file.gcnofile.o.gcno 以及类似...文件的数量无关紧要,gcov 必须找到结果文件。
    猜你喜欢
    • 2011-05-11
    • 2017-07-05
    • 2010-12-29
    • 2016-01-29
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    相关资源
    最近更新 更多