Como criar arquivos gcov para um projeto em um diretório diferente?

2

Eu quero analisar os dados de cobertura de código. Eu quero criar arquivos gcov do OpenSSL (e de outros projetos), mas só posso criá-los no mesmo diretório do projeto e apenas para os arquivos na pasta atual.

Eu quero criá-los em um diretório diferente, preservar a estrutura do diretório original de origem e tornar todo o processo o mais automático possível.

fonte: ~/mygcovproject/projects/openssl-1.0.0

saída: ~/mygcovproject/gcovdata/openssl-1.0.0

Atualmente, posso criar os arquivos apenas desta maneira:

$ 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)

Mas há 2 grandes problemas com esse método:

1) Existem muitas pastas e subpastas.

2) Eu tenho que mover os arquivos manualmente.

Como devo fazer isso? Você pode me ajudar por favor?

Upd :

Obrigado Gilles, isso me ajudou muito, mas eu ainda luto com a última parte. Recebo mensagens de erro do 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
...

Eu tentei isso também, mas não funcionou, recebi erros :

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

...

Eu tentei um único comando :

$ 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

Parece que só posso executar o gcov nos arquivos na mesma pasta. Como devo resolver isso? Devo cd nos diretórios no loop, então mova os arquivos? Ou estou fazendo algo errado?

Eu tentei nas pastas com as opções -o, mas não funcionou:

$ 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 : A partir da solução Gilles, criei um código de trabalho. Obrigado. No final, coloquei todos eles no mesmo diretório, mas criei um prefixo a partir do caminho deles.

### 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
    
por BlackCat 25.07.2015 / 20:46

1 resposta

2

Você tem os comandos, então coloque-os em um script!

Para executar vários comandos em dados diferentes, coloque os dados alterados em uma variável .

Para executar gcov e mv em todos os arquivos, há vários métodos possíveis, incluindo:

  • Execute gcov em todos os arquivos e mova-os.
  • Execute gcov em um arquivo e mova sua saída.
  • Execute gconv nos arquivos em um diretório e mova-os.

A primeira abordagem não funciona porque gcov precisa ser executado no diretório que contém os arquivos de origem. A terceira abordagem baseada em diretório é, na verdade, a mais complicada das três: o método mais simples seria executar gcov em um arquivo de cada vez.

No bash, você pode enumerar todos os arquivos C em um diretório e seus subdiretórios recursivamente com o padrão de curinga **/*.c . O curinga ** precisa ser ativado com a globstar opção . Para iterar os arquivos, use um for loop .

Para mudar para um diretório apenas para executar um comando, execute cd e esse comando em um subshell : (cd … && gcov …) .

Você precisa de mais um tipo de construção de shell: um pouco de manipulação de nomes de arquivos para extrair a parte do diretório. A expansão do parâmetro construct ${x%/*} se expande para o valor da variável x com o menor sufixo correspondente ao padrão /* removido. Em outras palavras, essa é a parte do diretório do nome do arquivo armazenado em x . Isso não funcionaria se x consistisse apenas em um nome de arquivo sem parte de diretório (por exemplo, foo em oposição a bar/foo ); Acontece que não há nenhum arquivo .c na raiz da árvore de código-fonte do OpenSSL, mas uma maneira simples de garantir que o nome do arquivo comece com ./ , que designa o diretório atual.

Invoque esse script na raiz da árvore de código-fonte do OpenSSL, depois de executar ./config com as opções desejadas.

#!/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

Para evitar a necessidade de mover os arquivos .gcov , uma abordagem alternativa seria criar uma floresta de links simbólicos para o diretório de compilação e executar gcov no diretório gcovdata . Com o GNU coreutils (ou seja, no Linux ou Cygwin não integrado), você pode fazer isso com cp -al .

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