【问题标题】:gcov on larger projects (static libraries, ...)gcov 用于大型项目(静态库,...)
【发布时间】:2011-07-31 22:40:03
【问题描述】:

我正在处理具有以下目录布局的大型项目:

Source
 MyA
  aa.cpp
  ab.cpp
  ac.cpp
 MyB
  ba.cpp
  bb.cpp
  bc.cpp
 MyTest
  testaa.cpp
  testab.cpp
  testac.cpp
  testba.cpp
  testbb.cpp
  testbc.cpp
  main.cpp
Build
 MyA
  aa.o
  ab.o
  ac.o
  libMyA.a (static library)
 MyB
  ba.o
  bb.o
  bc.o
  libMyB.a (static library)
 MyTest
  testaa.o
  testab.o
  testac.o
  testba.o
  testbb.o
  testbc.o
  MyTest (executable)

使用-fprofile-arcs -ftest-coverage 编译后,我在 Build/MyTest 目录中执行 MyTest 应用程序。正如预期的那样,在 Build 目录中有 *.gcno 和 *.gcda 文件。在 MyTest 目录中运行 gcov 后,会生成不同的 *.gcov 文件,但不幸的是不是针对 MyA 和 MyB 中的所有文件,尽管在这两个库中调用了每个函数。尝试了不同的选项,但不知何故我无法使用此布局创建有用的(意味着正确的)*.gcov 文件。

如果我将每个 cpp 复制到一个目录中并重复这些步骤,一切都会按预期工作,并且覆盖率分析是完美的。

【问题讨论】:

    标签: unit-testing gcc build-process code-coverage gcov


    【解决方案1】:

    如果您对产品或应用程序进行了彻底的手动测试,并为此付出了很多努力。如果您的目标是使用 lcov 和 gcov 获取代码覆盖率报告,但错误地删除了 gcno 文件。您可以通过重新编译代码来重新生成 gcno 文件,但它将使用新的时间戳生成,并且 gcov 报告错误说“stamp mismatch with graph file”并且不会生成代码覆盖率报告。这将导致您的所有测试工作都白费。

    仍然有一个快捷方式可以生成代码覆盖率报告。这只是一种解决方法,不应一直依赖。建议在测试完成之前保留 *.gcno 文件。

    记下您的 gcc 版本(gcc -v)并从镜像站点之一下载其源代码 例如 - ftp://gd.tuwien.ac.at/gnu/sourceware/gcc/releases/gcc-4.4.6/gcc-4.4.6.tar.bz2

    解压下载的文件后,gcc文件夹结构如下 gcc-4.4.6 gcc-4.4.6/gcc

    如果你直接进入 gcc-4.4.6/gcc 并尝试从那里进行 ./configure 和 compile(make) 那么你会遇到以下问题 构建/genmodes -h > tmp-modes.h /bin/sh: build/genmodes: 没有这样的文件或目录

    解决方案是从 gcc-4.4.6 执行 ./configure 和 make,不会显示与 genmodes 相关的错误。这将编译包括 gcc 在内的所有模块。如果 ./configure 显示任何错误,您可能必须安装 gcc 所需的 mpfr 和 gmp 模块

    转到 gcc-4.4.6/gcc/gcov.c 并在下面的行注释,然后使用上面的命令重新编译

    /*  if (tag != bbg_stamp)
        {
          fnotice (stderr, "%s:stamp mismatch with graph file\n", da_file_name);
          goto cleanup;
        }*/
    

    编译后新gcov二进制文件的示例路径为gcc-4.4.6/host-x86_64-unknown-linux-gnu/gcc/gcov

    将此二进制文件放入 /usr/bin 并使用命令重新生成代码覆盖率报告,如下例所示 lcov --capture --directory ./ --output-file coverage.info ; genhtml coverage.info --output-directory /var/www/html/coverage

    现在您应该不会收到“stamp mismatch with graph file”错误,您将正确获得代码覆盖率报告

    【讨论】:

    • 很多有用的信息,但没有回答原来的问题。
    【解决方案2】:
    1. 您必须将源文件指定为 g++/gcc 的绝对路径。不要使用“..”或“foo/bar.cpp”之类的相对路径,否则会出现“geninfo: WARNING: no data found for XXXX”等错误。

    2. 不要在 g++/gcc 的命令行中包含任何头文件。否则你会得到“stamp mismatch with graph file”错误。

    所以,当有多个目录时,以下应该可以工作:

    g++ --coverage -DDEBUG -g3 heyo.cpp /app/helper/blah.cpp /app/libfoo/foo.cpp -o program
    
    ./program
    
    lcov --directory . --capture --output-file app.info
    
    genhtml --output-directory cov_htmp app.info
    

    或者,如果你在一个已经使用相对路径的 Makefile 中,使用起来很方便:

    g++ --coverage -DDEBUG -g3 $(abspath heyo.cpp helper/blah.cpp ../foo/bar/baz.cpp) -o program
    

    【讨论】:

    • 这非常适合我的情况。非常感谢。我想我之前低估了lcov
    【解决方案3】:

    为了能够保持您的目录结构,您需要在每个源文件文件夹中运行一次 gcov,但使用 -o 选项告诉 gcov 数据文件在哪里。

    我觉得应该是这样的:

    gcov -o ../../Build/MyA *.cpp
    

    我有一个具有类似源文件结构的项目,但我让编译器将目标文件等转储到源文件夹中。然后我从根文件夹多次运行 gcov,每个源文件一次,但我指定源文件的相对路径并使用 -o 选项指定相对文件夹,如下所示:

    gcov -o Source/MyA Source/MyA/aa.cpp
    

    【讨论】:

    • 我假设你也在从你的根目录调用 gcc/g++ 吗?如果我只使用任何目录中的 -o 选项,我的所有 *.gov 文件都包含很多 /*EOF*/ ,尽管所有路径都已正确设置。可能我的主要问题是构建系统(qmake)从不同的位置调用编译器。
    • @azraiyl:我正在使用 scons 构建项目,所以我不完全确定,但是,是的,我认为 scons 使用源文件的相对路径。
    猜你喜欢
    • 1970-01-01
    • 2011-02-15
    • 2020-01-16
    • 2015-09-29
    • 1970-01-01
    • 2014-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多