Shell-Script

如何為不同目錄中的項目創建 gcov 文件?

  • May 6, 2020

我想分析程式碼覆蓋率數據。我想從 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)我必須手動移動文件。

我該怎麼做?你能幫我嗎?

更新

謝謝 Gilles,它幫了我很多,但我仍然在最後一部分掙扎。我從 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'

Upd2:從 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

你有命令,所以把它們放在一個腳本中!

要對不同的數據執行一堆命令,請將變化的數據放入一個變數中。

要在所有文件上執行gcovmv處理,有幾種可能的方法,包括:

  • 在所有文件上執行gcov,然後移動它們。
  • 在一個文件上執行gcov,然後移動其輸出。
  • gconv對目錄中的文件執行,然後移動它們。

第一種方法不起作用,因為gcov需要在包含源文件的目錄中執行。第三種基於目錄的方法實際上是三種方法中最複雜的:最簡單的方法是一次執行gcov一個文件。

在 bash 中,您可以使用萬用字元模式 遞歸地列舉目錄及其子目錄中的所有 C 文件**/*.c**需要使用選項globstar啟用萬用字元。要遍歷文件,請使用for loop.

要更改為僅執行一個命令的目錄,請在子shellcd中執行該命令:。(cd … && gcov …)

您需要另一種類型的 shell 構造:對文件名進行一些操作以提取目錄部分。參數擴展構造擴展為具有與已刪除模式匹配的最短後綴${x%/*}的變數的值。換句話說,這是儲存在. 如果僅包含沒有目錄部分的文件名(即與 相對),這將不起作用;碰巧在 OpenSSL 原始碼樹的根目錄下沒有文件,而是一種確保文件名以 開頭的簡單方法,它表示目前目錄。x``/*``x``x``foo``bar/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

引用自:https://unix.stackexchange.com/questions/218335