Как использовать gcovr с исходными файлами вне текущего каталога/build/run?

mkdir -p /tmp/build &&
cd /tmp/build &&
mkdir -p /tmp/src &&
echo "int main(){return 0;}" > /tmp/src/prog.c &&
gcc --coverage -o prog /tmp/src/prog.c &&
./prog &&
gcovr -v -r .

выведет пустой отчет.

Scanning directory . for gcda/gcno files...
Found 2 files (and will process 1)
Processing file: /tmp/build/prog.gcda
Running gcov: 'gcov /tmp/build/prog.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory /tmp/build' in '/tmp/build'
Finding source file corresponding to a gcov data file
  currdir      /tmp/build
  gcov_fname   #tmp#src#prog.c.gcov
               ['        -', '    0', 'Source', '/tmp/src/prog.c\n']
  source_fname /tmp/build/prog.gcda
  root         /tmp/build
  fname        /tmp/src/prog.c
Parsing coverage data for file /tmp/src/prog.c
  Filtering coverage data for file /tmp/src/prog.c
Gathered coveraged data for 0 files
------------------------------------------------------------------------------
                           GCC Code Coverage Report
Directory: .
------------------------------------------------------------------------------
File                                       Lines    Exec  Cover   Missing
------------------------------------------------------------------------------
------------------------------------------------------------------------------
TOTAL                                          0       0    --%
------------------------------------------------------------------------------

Однако, если я вручную запускаю

gcov /tmp/build/prog.gcda --branch-counts --branch-probabilities --preserve-paths --object-directory /tmp/build

Я получаю правильные результаты

File '/tmp/src/prog.c'
Lines executed:100.00% of 1
No branches
No calls
Creating '#tmp#src#prog.c.gcov'

Кажется, что gcovr не извлекла покрытие из правильных в остальном выходных данных gcov. Это происходит только в том случае, если исходный файл находится за пределами текущего каталога (такой же, как каталог сборки, такой же, как выходной каталог, такой же, как каталог запуска), и gcc ics вызывается с абсолютным путем к исходному файлу.

Как я могу это исправить?

Редактировать

Исправлено в исходном gcovr для относительных путей, но похоже на ошибку для абсолютных путей.

См. https://github.com/gcovr/gcovr/issues/169.


person not-a-user    schedule 12.05.2017    source источник
comment
Вместо того, чтобы давать все эти mkdir, вы должны объяснить структуру каталогов непосредственно в своем вопросе. Объяснение того, где размещаются файлы obj и исходники   -  person Vikas Tawniya    schedule 17.05.2017
comment
@Vikas Мне больше нравится, если есть исполняемый код, который воспроизводит проблему. (По крайней мере, если вопрос заключается в этом виде ошибки или ошибки пользователя?)   -  person not-a-user    schedule 18.05.2017


Ответы (2)


Из вашего кода я понял, что вы все сделали и запустили программу, но вы все еще находитесь в каталоге сборки, где находится объектный файл.

Итак, что вам нужно понять:

gcovr -v -r <path>

этот флаг -r принимает корневой каталог, что означает родительский каталог, внутри которого находится исходный каталог и каталог объектов. Чтобы он мог отслеживать их обоих и генерировать данные о покрытии и все, что вы хотите.
Попробуйте сделать это, и это сработает.

Для вашего понимания:

Файлы .gcno, которые генерируются после компиляции, представляют собой просто блок-схемы данных для этого конкретного исходного файла.
Позже, когда вы запускаете программу, для каждого исходного файла создается файл .gcda. Этот файл содержит реальные данные о покрытии, но для gcovr необходимы все эти три файла (.gcno, .gcda, sourceFile)

Надеюсь, это помогло. :)

update:
Вернемся к обходным решениям
Вы можете указать местоположение данных о покрытии в виде чистого аргумента (без вариантов) и указать корень на свои источники.

gcovr .../path/To/GCDA -r .../path/to/src/ [rest desired flags]

Это точно решит вашу проблему.
Работал на меня, освещая мои проекты.

person Vikas Tawniya    schedule 17.05.2017
comment
Файлы .gcno уже содержат пути, по которым можно найти исходники. (Выполните strings в файле .gcno.) - person not-a-user; 18.05.2017
comment
Хорошей практикой является хранение исходников и каталога сборки отдельно, поэтому gcovr должен это поддерживать. - person not-a-user; 18.05.2017
comment
да, я говорю о корневом каталоге здесь. который содержит сборку и исходный каталог. Кроме того, всегда добавляйте дополнительную косую черту после последнего имени каталога в пути. - person Vikas Tawniya; 18.05.2017
comment
Я понимаю, но я хочу использовать gcovr в Makefile и не хочу делать никаких предположений о том, где я строю. (Как вычислить тот общий корневой каталог? Что, если он содержит еще много несвязанных исходников и файлов gcov? Вот он /tmp/, неужели я хочу скормить все /tmp/ int gcovr?!?Нет!) - Пока я этим занимаюсь , lcov кажется лучшим решением моей проблемы. (Работает в каталоге сборки, находит исходники, (эффективно) проверяя файлы .gcno.) - person not-a-user; 18.05.2017
comment
Я сделал это для нескольких крупных проектов, использующих cmake. Я делал сборку, передавая флаг --coverage в команду, чтобы она работала с обычным файлом сборки cmake. Там были тысячи исходных файлов, поэтому мне пришлось указать ближайший из возможных родительский каталог, в котором есть каталоги obj и src. gcovr отслеживает все gcda файлы, а затем только те исходные файлы, которые относятся ко всем gcda - person Vikas Tawniya; 19.05.2017
comment
Но есть еще один обходной путь. Я свяжусь с вами после понедельника, так как мне нужно будет проверить свою предыдущую работу. - person Vikas Tawniya; 19.05.2017
comment
он не требует наличия как источника, так и объекта непосредственно под каталогом, который мы передали. Это может быть где угодно по линии. обычно файлы obj создаются с использованием той же структуры, что и исходные файлы, когда мы используем автоматическое построение. Итак, он работает нормально. - person Vikas Tawniya; 19.05.2017
comment
@ not-a-user обновил ответ для обхода проблемы, проверьте его. :) - person Vikas Tawniya; 25.05.2017
comment
У меня есть исходные файлы в нескольких каталогах, как указать несколько значений для -r (--root)? запятая/точка с запятой? - person kaps; 01.08.2018

Gcovr генерирует отчеты только для исходных файлов вашего проекта. Это предназначено для исключения покрытия из заголовков библиотек и т. д.

Вопрос в том, какие файлы находятся в вашем проекте? Это определяется корневым путем -r.

Если вы находитесь в /tmp/build, а корень — ., он же /tmp/build, а исходный файл — /tmp/src/prog.c, то этот исходный файл явно находится за пределами вашего проекта. В подробном выводе gcovr сообщит Filtering coverage data for file /tmp/src/prog.c.

Если вы находитесь в /tmp/build, а корень — .. или /tmp, а исходный файл — /tmp/src/prog.c, то этот исходный файл находится в проекте.

Если вы находитесь в /tmp/build, а корень — ., он же /tmp/build, а исходный файл — ../src/prog.c, то gcovr делает что-то сомнительное: он объединяет имя файла с текущим каталогом и проверяет это. Итак, мы на самом деле видим /tmp/build/../src/prog.c. Что касается gcovr, это в рамках вашего проекта. Похоже, такое поведение необходимо для включения в проект кода, на который ссылается символическая ссылка.

Вы можете отключить это «исходник в проекте?» фильтр, предоставив свой собственный, лучший фильтр. Например, вы можете попросить gcovr сообщать о покрытии только для источников с /tmp/src:

gcovr -r . -f /tmp/src
person amon    schedule 09.01.2018