コードカバレッジデータを分析したい。 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)
しかし、この方法には2つの大きな問題があります。
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
...
1つのコマンドを試しました:
$ 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'
pd2: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
コマンドがあるので、スクリプトに入れてください!
さまざまなデータに対して一連のコマンドを実行するには、変更するデータを 変数 に入れます。
すべてのファイルに対してgcov
およびmv
を実行するには、次のようないくつかの可能な方法があります。
gcov
を実行してから、それらを移動します。gcov
を実行し、その出力を移動します。gconv
を実行してから、それらを移動します。gcov
はソースファイルを含むディレクトリで実行する必要があるため、最初の方法は機能しません。 3番目のディレクトリベースのアプローチは、実際には3つの中で最も複雑です。最も単純な方法は、一度に1つのファイルに対してgcov
を実行することです。
Bashでは、 ワイルドカードパターン**/*.c
を使用して、ディレクトリとそのサブディレクトリ内のすべてのCファイルを再帰的に列挙できます。 **
ワイルドカードは globstar
オプション で有効にする必要があります。ファイルを反復処理するには、 for loop
を使用します。
1つのコマンドを実行するだけのディレクトリに変更するには、cd
とそのコマンドを サブシェル :(cd … && gcov …)
で実行します。
もう1種類のシェル構成が必要です。ディレクトリ部分を抽出するためにファイル名を少し操作する必要があります。 パラメータ展開 構文${x%/*}
は、パターン/*
に一致する最短のサフィックスが削除された変数x
の値に展開されます。つまり、これはx
に保存されているファイル名のディレクトリ部分です。これは、x
がディレクトリ部分のないファイル名のみで構成されている場合は機能しません(つまり、bar/foo
ではなくfoo
)。 OpenSSLソースツリーのルートに.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