如何为不同目录中的项目创建 gcov 文件?

如何为不同目录中的项目创建 gcov 文件?

我想分析代码覆盖率数据。我想从 OpenSSL(以及其他项目)创建 gcov 文件,但我只能在项目的同一目录中创建它们,并且只能针对当前文件夹中的文件。

我想在不同的目录中创建它们,保留源原始目录结构,并使整个过程尽可能自动化。

来源: ~/mygcovproject/projects/openssl-1.0.0

输出: ~/mygcovproject/gcovdata/openssl-1.0.0

目前我只能通过这种方式创建文件:

$ cd ~/mygcovproject/projects/openssl-1.0.0
$ make clean
$ export CC="gcc -fprofile-arcs -ftest-coverage"; ./config
$ make
$ make tests

$ cd test
$ gcov *.c
$ mv *.gcov ~/mygcovproject/gcovdata/openssl-1.0.0/test/
$ cd ..

$ cd apps
$ gcov *.c
$ mv *.gcov ~/mygcovproject/gcovdata/openssl-1.0.0/apps/
$ cd ..

$cd crypto
... (for all the folders)

但这种方法有两个大问题:

1)有很多文件夹和子文件夹。

2)我必须手动移动文件。

我该怎么做?你能帮我吗?

更新:

谢谢吉尔斯,它对我帮助很大,但我仍然很难理解最后一部分。我从 gcov 收到错误消息:

$ cat dothemagic.sh 
#!/bin/bash
shopt -s globstar
gcov_data_dir="../../gcovdata/${PWD##*/}"
mkdir -p "$gcov_data_dir"
#make
#make tests
for x in ./**/*.c; do
  gcov "$gcov_data_dir/${x%/*}/$x"
done
exit

$ ./dothemagic.sh 
../../gcovdata/openssl-1.0.0/./apps/./apps/app_rand.gcno:cannot open notes file
../../gcovdata/openssl-1.0.0/./apps/./apps/apps.gcno:cannot open notes file
../../gcovdata/openssl-1.0.0/./apps/./apps/asn1pars.gcno:cannot open notes file
../../gcovdata/openssl-1.0.0/./apps/./apps/ca.gcno:cannot open notes file
../../gcovdata/openssl-1.0.0/./apps/./apps/ciphers.gcno:cannot open notes file
../../gcovdata/openssl-1.0.0/./apps/./apps/cms.gcno:cannot open notes file
../../gcovdata/openssl-1.0.0/./apps/./apps/crl2p7.gcno:cannot open notes file
...

我也尝试过这个,但它不起作用,我收到错误:

for x in ./**/*.c; do
  echo $x
  gcov $x
done


$ ./run_tests.sh openssl-1.0.0

./apps/app_rand.c
File 'app_rand.c'
Lines executed:37.50% of 40
Creating 'app_rand.c.gcov'
Cannot open source file app_rand.c

./apps/apps.c
File 'apps.c'
Lines executed:33.76% of 939
Creating 'apps.c.gcov'
Cannot open source file apps.c

...

我尝试了一个命令:

$ gcov ./apps/app_rand.c
File 'app_rand.c'
Lines executed:37.50% of 40
Creating 'app_rand.c.gcov'
Cannot open source file app_rand.c

看起来我只能对同一文件夹中的文件运行 gcov 。我应该如何解决这个问题?我应该在循环中的目录中进行 cd,然后移动文件吗?或者我做错了什么?

我在文件夹中尝试使用 -o 选项,但它不起作用:

$ pwd
/home/blackcat/gcov_project/projects/openssl-1.0.0/test
$ ls bftest.*
bftest.c  bftest.c.gcov  bftest.gcda  bftest.gcno  bftest.o
$ gcov -o ~/gcov_project/gcov/ bftest.c
/home/blackcat/gcov_project/gcov/bftest.gcno:cannot open notes file
$ gcov bftest.c
File 'bftest.c'
Lines executed:47.52% of 101
Creating 'bftest.c.gcov'

File '/usr/include/x86_64-linux-gnu/bits/stdio2.h'
Lines executed:100.00% of 1
Creating 'stdio2.h.gcov'

File '/usr/include/x86_64-linux-gnu/bits/string3.h'
Lines executed:100.00% of 2
Creating 'string3.h.gcov'

更新2:从 Gilles 解决方案开始,我创建了一个工作代码。谢谢。最后,我将它们全部放在同一个目录中,但我从它们的路径创建了一个前缀。

### Generate and copy gcov files ###

cd "$TARGET_DIR"
mkdir -p "$OUTPUT_DIR"

CDIR=""
for x in **/*.c; do
  if [ "$CDIR" != "$TARGET_DIR/${x%/*}" ]; then
    CDIR="$TARGET_DIR/${x%/*}"
    cd $CDIR
    gcov -p *.c

    SUBDIR="${x%/*}"
    PREFIX="#${SUBDIR/\//\#}"

    for f in *.gcov; do
        if [[ $f == \#* ]] ;
        then
           cp $f "$OUTPUT_DIR/$f"
        else
           cp $f "$OUTPUT_DIR/$PREFIX#$f"
        fi
    done
  fi
done

答案1

您拥有命令,因此请将它们放入脚本中!

要对不同的数据运行一堆命令,请将变化的数据放入多变的

要运行gcov所有mv文件,有几种可能的方法,包括:

  • 运行gcov所有文件,然后移动它们。
  • 在一个文件上运行gcov,然后移动其输出。
  • gconv对目录中的文件运行,然后移动它们。

第一种方法不起作用,因为gcov需要在包含源文件的目录中执行。第三种基于目录的方法实际上是三种方法中最复杂的一种:最简单的方法是gcov一次运行一个文件。

在 bash 中,您可以使用以下命令递归枚举目录及其子目录中的所有 C 文件通配符模式 **/*.c**需要使用以下命令启用通配符globstar选项。要迭代文件,请使用for loop

要更改到某个目录只是为了运行一个命令,请cd在 a 中运行该命令子外壳: (cd … && gcov …)

您还需要另一种类型的 shell 构造:对文件名进行一些操作以提取目录部分。这参数扩展构造扩展为具有与删除的模式匹配的最短后缀${x%/*}的变量的值。换句话说,这是存储在.如果仅包含没有目录部分的文件名(即与 相对),则这将不起作用;碰巧OpenSSL 源代码树的根部没有文件,但有一个简单的方法可以确保文件名以 开头,它指定当前目录。x/*xxfoobar/foo.c./

./config使用所需选项运行后,在 OpenSSL 源代码树的根部调用此脚本。

#!/bin/bash
shopt -s globstar
gcov_data_dir="../../gcovdata/${PWD##*/}"
make
make tests
for x in ./**/*.c; do
  mkdir -p "$gcov_data_dir/${x%/*}"
  (cd "${x%/*}" && gcov "${x##*/}") &&
  mv "$x.gcov" "$gcov_data_dir/${x%/*}"
done

为了避免移动文件.gcov,另一种方法是创建一个指向编译目录的符号链接林,并gcov在该gcovdata目录中运行。借助 GNU coreutils(即在非嵌入式 Linux 或 Cygwin 上),您可以使用cp -al.

cp -al openssl-1.0.0 gcovdata
cd gcovdata
for x in ./**/*.c; do
  (cd "${x%/*}" && gcov "${x##*/}")
done

答案2

运行 gcov 后,只需执行以下操作:

mv *.gcov sub-folder-name
mv *.gcda sub-folder-name
mv *.gcno sub-folder-name

相关内容