Libtool 为对象添加前缀,但 gcov 要求它们不带前缀

Posted

技术标签:

【中文标题】Libtool 为对象添加前缀,但 gcov 要求它们不带前缀【英文标题】:Libtool prefixes objects but gcov requires them without prefix 【发布时间】:2015-03-16 06:02:26 【问题描述】:

我需要使用gcov 在我正在处理的共享库上执行一些测试覆盖率。

问题是libtool 将目标文件从my-name.c 重命名为libmylib_la-my-name.lo,而gcov 无法处理该转换。每次运行都会产生错误cannot open notes file

如果我在构建 gcov 后手动将 my-name.c 重命名为 libmylib_la-my-name.c 工作正常,那么除了文件名修改之外没有其他问题。

附录

试图提供一个最小的工作示例,我发现文件名修改仅在设置 lib..._la_CFLAGS 时发生(以及设置为空值时)。

cat <<EOT > configure.ac
AC_INIT(sample,0.0.1)
AC_CONFIG_SRCDIR(configure.ac)
AM_INIT_AUTOMAKE(foreign)
LT_INIT
AC_PROG_CC
AC_CONFIG_FILES(Makefile)
AC_OUTPUT
EOT

cat <<EOT > Makefile.am
lib_LTLIBRARIES=libsample.la
libsample_la_SOURCES=sample.c
# The following line triggers the filename mangling (libsample_la-sample.lo instead of sample.lo)
libsample_la_CFLAGS=
EOT

touch sample.c && autoreconf -if && ./configure && make

有没有办法避免 libtool 操作的文件名重整或让gcov 了解文件名重整方案?

【问题讨论】:

如果没有您的 Makefile.am,很难诊断 - 您需要提供更多信息。 @Brett 好的,提供示例项目。 在使用每个目标编译标志时,automake 都会执行文件名修改。该信息(像往常一样)被埋在automake manual中。 【参考方案1】:

Libtool 不应更改 .c 文件名。但是,它确实更改了 .o 文件名;这是因为它需要在某些平台上编译库两次(一次为 .so(共享)库创建与位置无关的代码(PIC),一次为 .a(静态)库创建不是 PIC 的代码)。

您可能会看到gcov 存在共享库问题。详情见“can gcov deal with shared object?”。

如果这不能解决问题,我将不得不同意 Brett 的意见,即您需要提供更多信息。

【讨论】:

这似乎是一个不同的问题:如果在构建之后我重命名我的测试源文件(例如,mv test.c libsample_la-test.c)一切正常。【参考方案2】:

Gcov gcdagcno 文件以目标文件命名。您可以直接在目标文件上从源目录运行gcov,也可以使用gcov-o 选项指定目标文件和对应的gcov 文件。

例如,我有一个构建共享库的小项目。我通过gcov 标志来制作命令:

make CFLAGS="-O0 --coverage" LDFLAGS=--coverage

src/.libs文件夹中创建对象文件和对应的gcno文件:

$ ls -la src/.libs
libtest_la-test.o
libtest_la-test.gcno

源文件在src文件夹中

$ ls src/
test.c

接下来我运行我的测试套件并创建gcda 文件:

$ ls -la src/.libs
libtest_la-test.o
libtest_la-test.gcno
libtest_la-test.gcda

现在我可以进入src目录并运行gcov,指定目标文件名:

$ gcov -o .libs/libtest_la-test.o test.c
File ‘test.c’
Lines executed:27.08% of 96
Creating ‘test.c.gcov'

也可以只在目标文件上运行gcov

$ gcov .libs/libtest_la-test.o
File ’test.c’
Lines executed:27.08% of 96
Creating ’test.c.gcov'

或者甚至只是指定目标文件的基本名称和gcov 文件:

$ gcov .libs/libtest_la-test
File ’test.c’
Lines executed:27.08% of 96
Creating ’test.c.gcov'

但我会建议另一种对我非常有效的自动化方法,使用lcov。我从***目录调用它,指定源文件和目标文件的路径:

$ lcov --base-directory src --directory src/.libs/ --capture --output-file gcov.info
Capturing coverage data from src/.libs/
Found gcov version: 4.8.2
Scanning src/.libs/ for .gcda files ...
Found 10 data files in src/.libs/
Processing .libs/test_la-test.gcda
[…]
Finished .info-file creation

$ genhtml -o html/coverage gcov.info
Reading data file gcov.info
Found 10 entries.
Found common filename prefix "/usr/src/libtest”
Writing .css and .png files.
Generating output.
Processing file src/test.c
[…]
Writing directory view page.
Overall coverage rate:
  lines......: 56.1% (2098 of 3737 lines)
  functions..: 68.8% (139 of 202 functions)

现在html/coverage 目录包含可以在网络浏览器中轻松分析的 html 文件。

【讨论】:

以上是关于Libtool 为对象添加前缀,但 gcov 要求它们不带前缀的主要内容,如果未能解决你的问题,请参考以下文章

gcov 检测共享对象引用 __gcov_init 隐藏符号

为 gcov 编译 googletest

CMake添加gcov代码覆盖测试支持

如何告诉 gcov 忽略不可命中的 C++ 代码行?

用“+”运算符为对象添加前缀有啥作用? [复制]

使用了 Libtool 库,但未定义“LIBTOOL”?