web-dev-qa-db-ja.com

プロジェクトの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)

しかし、この方法には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
3
BlackCat

コマンドがあるので、スクリプトに入れてください!

さまざまなデータに対して一連のコマンドを実行するには、変更するデータを 変数 に入れます。

すべてのファイルに対してgcovおよびmvを実行するには、次のようないくつかの可能な方法があります。

  • すべてのファイルに対してgcovを実行してから、それらを移動します。
  • 1つのファイルで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ファイルを移動する必要がないようにするには、別の方法として、コンパイルディレクトリへのシンボリックリンクのフォレストを作成し、gcovgcovdataディレクトリで実行します。 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