Проверка Visual Studio проектов из командной строки с помощью PVS-Studio


Помимо проверки непосредственно из Visual Studio, инструмент PVS-Studio позволяет выполнять проверку MSBuild проектов (то есть проектов Visual C++ и Visual C#) из командной строки. Это может быть полезно для настройки регулярных автоматических запусков анализатора. Например, во время "ночной сборки" на сборочном сервере.

Запуск анализа sln и csproj/vcxproj файлов

Для проверки С++/C# проектов либо решений (sln файлов), содержащих такие проекты, можно использовать анализатор PVS-Studio напрямую, без необходимости запускать процесс IDE (devenv.exe) и открывать в нём проекты, которые требуется проверить.

Command line модуль 'PVS-Studio_Cmd.exe' можно найти в установочной директории PVS-Studio (по умолчанию это 'c:\Program Files (x86)\PVS-Studio\'). Команда '--help' выведет все доступные аргументы анализатора:

PVS-Studio_Cmd.exe --help

Рассмотрим основные аргументы анализатора:

  • --target (-t): обязательный параметр. Позволяет указать объект для проверки (sln или csproj/vcxproj файл);
  • --sourceFiles (-f): путь до XML файла, в котором можно указать список файлов и\или фильтров, которые будут проверены. Подробное описание синтаксиса данного файла описано ниже, в соответствующем подразделе.
  • --output (-o): путь до plog файла, в который будут записаны результаты анализа. Если данный параметр пропущен, plog файл будет создан рядом с файлом, указанным в target;
  • --platform (-p) и --configuration (-c): платформа и конфигурация, для которых будет запущена проверка. Если данные параметры не указаны, будет выбрана первая из доступных пар "платформа|конфигурация" (при проверке sln файла) либо "Debug|AnyCPU" (при проверке отдельного csproj проекта) или "Debug|Win32" (при проверке отдельного vcxproj проекта);
  • --settings (-s): путь до файла настроек PVS-Studio. Если параметр опущен, будут использованы настройки IDE плагина PVS-Studio, находящиеся в папке; "c:\Users\%UserName%\AppData\Roaming\PVS-Studio\Settings.xml". Обратите внимание, что для корректной работы анализатора переданные через этот флаг настройки должны содержать вашу регистрационную информацию (при использовании настроек по умолчанию из AppData регистрационная информация может быть введена через интерфейс Visual Studio плагина PVS-Studio);
  • --progress (-r): включение режима подробного логгирования в stdout прогресса проверки (по умолчанию выключено);
  • --suppressAll (-a): добавить неподавленные сообщения в suppress файлы соответствующих проектов (по умолчанию выключено). При наличии данного флага все сообщения будут добавлены в базу подавленных сообщений после сохранения результата проверки. Флаг поддерживает 2 режима работы.
    • SuppressOnly добавляет сообщения из переданного plog'а в suppress файлы без запуска анализа;
    • AnalyzeAndSuppress запускает анализ, сохраняет plog, и только затем подавляет найденные в нём сообщения. Этот режим позволит вам при регулярных запусках получать отчёт анализатора, в котором содержатся только новые сообщения на изменённый \ написанный код, т.е. новые сообщения попадают в новый лог и сразу же подавляются - при последующей проверке их уже не будет выдано. Тем не менее, на случай, если вам всё же потребуется посмотреть старые сообщения (без перепроверки), рядом с plog файлом, содержащим новые сообщения, будет сохранён файл с полным логом проверки. Подробнее про режим подавления сообщений можно прочитать в этом разделе документации;
  • --sourceTreeRoot (-e): корневая часть пути, которую PVS-Studio будет использовать при генерации относительных путей в диагностических сообщениях. Задание этого параметра переопределяет значение 'SourceTreeRoot' в настройках PVS-Studio;
  • -- incremental (-i): режим инкрементального анализа. Для получения подробной информации об инкрементальном анализе в PVS-Studio обратитесь к разделу "Режим инкрементального анализа PVS-Studio". Доступны следующие режимы работы инкрементального анализа:
    • Scan – проанализировать все зависимости для определения того, на каких файлах должен быть выполнен инкрементальный анализ. Непосредственно анализ выполнен не будет. Будут учтены изменения, произведенные с момента последней сборки, предыдущая история изменений будет удалена.
    • AppendScan – проанализировать все зависимости для определения того, на каких файлах должен быть выполнен инкрементальный анализ. Непосредственно анализ выполнен не будет. Будут учтены изменения, произведенные с момента последней сборки, а также все предыдущие изменения.
    • Analyze – выполнить инкрементальный анализ. Этот шаг должен выполняться после выполнения шагов Scan или AppendScan, и может выполняться как до, так и после сборки решения или проекта. Статический анализ будет выполнен только для файлов из списка, полученного в результате выполнения команд Scan или AppendScan.
    • ScanAndAnalyze - проанализировать все зависимости для определения того, на каких файлах должен быть выполнен инкрементальный анализ, и сразу же выполнить инкрементальный анализ измененных файлов с исходным кодом. Будут учтены изменения, произведенные с момента последней сборки.
  • --msBuildProperties (-m): позволяет задать или переопределить свойства уровня проекта. Для задания или переопределения нескольких свойств уровня проекта, используйте символ "|", например: --msBuildProperties WarningLevel=2|OutDir=bin\OUT32\

Приведём пример запуска проверки для решения Visual Studio "My Solution":

PVS-Studio_Cmd.exe --target "mysolution.sln" --platform "Any CPU" 
--configuration "Release" --output "mylog.plog"
--settings "pvs.xml" --progress

Command line версия анализатора PVS-Studio поддерживает все настройки по фильтрации\отключению сообщений, доступные в IDE плагине для Visual Studio. Вы можете как задать их вручную в xml файле, переданном с помощью аргумента '--settings', так и использовать настройки, заданные через UI плагина, не передавая данного аргумента. Обратите внимание, что IDE плагин PVS-Studio использует отдельный набор настроек для каждого пользователя в системе.

Задание отдельных файлов для проверки

PVS-Studio_Cmd позволяет провести выборочную проверку отдельных файлов, заданных в списке, передаваемом с помощью флага --sourceFiles (-f). Список файлов для проверки имеет формат XML и может содержать список абсолютных путей до проверяемых файлов и\или масок, задающих такие файлы.

<SourceFilesFilters>
  <SourceFiles>
    <Path>C:\Projects\Project1\source1.cpp</Path>
    <Path>C:\Projects\Project1\source1.h</Path>
    <Path>\Project2\source2.cpp</Path>
    <Path>source_*.cpp</Path>
    <Path>stdAfx.h</Path>
  </SourceFiles>
  <TlogDirs>
    <Dir>D:\Build\Tlogs\</Dir>
  </TlogDirs>
  <SourcesRoot>C:\Projects\</SourcesRoot>
</SourceFilesFilters>

Рассмотрим подробнее все возможные поля и их допустимые значения.

  • Элемент SourceFiles позволяет задать список файлов и\или фильтров для проверки. Каждый файл\фильтр задаётся в подэлементе Path. Заданные в элементах Path фильтры будут применены ко всем файлам всех проектов проверяемого решения - на проверку будут оставлены только те файлы решения, которые либо указаны явно, либо путь до которых удовлетворяет указанному фильтру. Можно указывать как исходные компилируемые файлы (c/cpp для C++ и cs для C#), так и заголовочные файлы (h/hpp для C++). Важное примечание: проверка заголовочных файлов для C/C++ будет возможна только при условии наличия журналов трассировки компилятора. Способ их задания указан в описании элемента TLogDirs. Все указанные в Path значения будут нормализованы по сепараторам директорий, однако относительные пути и специальные символы (. и ..) раскрыты не будут. Маски поддерживают wildcard маркеры * и ?. Возможные значения подэлемента Path:
    • Абсолютный путь до файла будет проверен на точное соответствие файлам проекта
    • Относительный путь до файла (например, \Project1\source2.cpp) или любая маска, не начинающаяся с корневой директории (например, 'C:\' или '\\' для UNC путей) будет интерпретироваться, как маска, начинающаяся с '*'. Т.е. 'stdAfx.h' будет интерпретироваться, как '*stdAfx.h'.
  • Элемент TlogDirs позволяет задать список директорий, в которых будут искаться сборочные артефакты tlog - журналы трассировки компиляторов. Данные файлы требуются для проверки отдельных заголовочных файлов C/C++ - т.к. анализатор работает только с единицами компиляции (т.е. c/cpp исходными файлами), он не может проверить заголовочный файл отдельно от использующего его исходного файла. Для установления зависимости исходного файла от заголовочных анализатор использует tlog'и. Tlog файлы генерирует сборочная система MSBuild во время сборки проекта, рядом с выходной директорией, в которой собираются остальные артефакты сборки (например, скомпилированные бинарные файлы). Анализатору требуются файлы, имеющие следующее имя: CL.read.*.tlog, где * может быть любым числом. Обычно MSBuild генерирует по одному такому tlog файлу на проект. С помощью подэлементов Dir можно указать несколько директорий, содержащих tlog файлы разных проектов, либо один раз указать общую корневую директорию, в которой будут все tlog'и всех проектов - анализатор будет искать tlog'и во всех поддиректориях относительно указанных в каждом Dir подэлементе. Важное примечание: если tlog файлы сгенерированы не при сборке локально проверяемого проекта (например, сборка производилась на другой машине или в другой локальной директории), для корректной проверки заголовочных файлов также необходимо указать текущую корневую директорию проекта с помощью элемента SourcesRoot. Это связано с тем, что журналы трассировки tlog содержат пути до файлов в абсолютном представлении.
  • Элемент SourcesRoot предназначен для указания базовой корневой директории, в которой развёрнуто проверяемое дерево исходников. Если вы используете tlog файлы, сгенерированные не на проверяемом проекте, то укажите эту директорию для того, чтобы анализатор смог корректно идентифицировать файловые зависимости в вашем проекте с путями, которые присутствуют в tlog'ах. В качестве значения в SourcesRoot необходимо указать текущую корневую директорию проверяемого проекта. Например, если исходники проверяемых проектов лежат в C:\Projects\Project1\, C:\Projects\Project2\ и т.п., то в качестве корневой директории нужно указать C:\Projects\.

В режиме проверки через флаг --sourceFiles (-f) анализатор, в отличии от обычного запуска на полном проекте\решении, будет выдавать сообщения только на файлы, явно заданные фильтрами SourceFiles. Это означает, что при проверке исходного cpp файла анализатор выдаст сообщения только на этот файл - сообщения на включаемые им заголовочные файлы (h файлы) будут скрыты, если эти заголовочные файлы явно не прописаны в SourceFiles.

Коды возврата command line утилиты

Утилита PVS-Studio_Cmd имеет несколько ненулевых кодов возврата, которые не означают проблемы в работе самой утилиты, т.е. даже если утилита вернула не '0', это ещё не означает, что она "упала". Код возврата представляет собой битовую маску, маскирующую все возможные состояния, возникшие во время работы утилиты. Например, утилита вернёт ненулевой код возврата (в частности, 256) в случае, если анализатор нашёл в проверяемом коде потенциальные ошибки. Это позволяет обрабатывать такую ситуацию отдельно, например, на сборочном сервере, когда политика использования анализатора не подразумевает наличия срабатываний в коде, заложенном в систему контроля версий. Другой пример: если в процессе анализа были обнаружены потенциальные ошибки в коде, и один из файлов, указанных в файле проекта, отсутствует на диске, утилита возвратит код состояния 264 (8 - не найдены какие-то из проверяемых файлов либо проектных файлов, 256 - в проверяемом коде найдены потенциальные ошибки), или, в двоичном представлении: 100001000.

Рассмотрим далее все возможные коды состояния утилиты, из которых формируется битовая маска кода возврата.

  • '0' - анализ успешно завершён, ошибок в проверяемом коде не найдено;
  • '1' - ошибка (падение) анализатора при проверке одного из файлов;
  • '2' - общая (неспецифичная) ошибка при работе анализатора, перехваченное исключение при работе. Обычно это сигнализирует о наличии ошибки в коде самого анализатора и сопровождается выведением stack trace'а этой ошибки в stdErr. Если вам встретилась подобная ошибка, пожалуйста, помогите нам улучшить анализатор и пришлите этот stack trace нам;
  • '4' - какие-то из переданных аргументов командной строки некорректны;
  • '8' - не найден заданный проект, solution или файл настроек анализатора;
  • '16' - заданная конфигурация и (или) платформа не найдены в файле решения;
  • '32' - файл решения или проекта не поддерживается или содержит ошибки;
  • '64' - некорректное расширение проверяемого решения или проекта;
  • '128' - некорректная или просроченная лицензия на анализатор;
  • '256' - в проверяемом коде найдены потенциальные ошибки;
  • '512' - произошла ошибка при выполнении подавления сообщений
  • '1024' - показывает, что лицензия на анализатор истечёт в течение месяца;

Приведем пример скрипта Windows batch для расшифровки кода возврата утилиты PVS-Studio_Cmd:

@echo off

"C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe"
-t "YourSolution.sln" -o "YourSolution.plog"

set /A FilesFail = "(%errorlevel% & 1) / 1"
set /A GeneralExeption = "(%errorlevel% & 2) / 2"
set /A IncorrectArguments = "(%errorlevel% & 4) / 4"
set /A FileNotFound = "(%errorlevel% & 8) / 8"
set /A IncorrectCfg = "(%errorlevel% & 16) / 16"
set /A InvalidSolution = "(%errorlevel% & 32) / 32"
set /A IncorrectExtension = "(%errorlevel% & 64) / 64"
set /A IncorrectLicense = "(%errorlevel% & 128) / 128"
set /A AnalysisDiff = "(%errorlevel% & 256) / 256"
set /A SuppressFail = "(%errorlevel% & 512) / 512"
set /A LicenseRenewal = "(%errorlevel% & 1024) / 1024"

if %FilesFail% == 1 echo FilesFail
if %GeneralExeption% == 1 echo GeneralExeption
if %IncorrectArguments% == 1 echo IncorrectArguments
if %FileNotFound% == 1 echo FileNotFound
if %IncorrectCfg% == 1 echo IncorrectConfiguration
if %InvalidSolution% == 1 echo IncorrectCfg
if %IncorrectExtension% == 1 echo IncorrectExtension
if %IncorrectLicense% == 1 echo IncorrectLicense
if %AnalysisDiff% == 1 echo AnalysisDiff
if %SuppressFail% == 1 echo SuppressFail
if %LicenseRenewal% == 1 echo LicenseRenewal

Запуск анализа из командной строки для C/C++ проектов, не использующих сборочную систему Visual Studio

Если ваш C/C++ проект не использует стандартные сборочные системы Visual Studio (VCBuild\MSBuild) или даже использует собственную сборочную систему \ make-файлы через NMake проекты Visual Studio, то вы не сможете проверить такой проект с помощью PVS-Studio_Cmd.

В таком случае вы можете воспользоваться системой отслеживания компиляторов, которая позволяет анализировать проекты, независимо от их сборочной системы, "перехватывая" запуск процессов компиляции. Система отслеживания компиляции может использоваться как из командной строки, так и через пользовательский интерфейс приложения C and C++ Compiler Monitoring UI.

Также вы можете напрямую встроить запуск command line ядра анализатора непосредственно в вашу сборочную систему. Заметьте, что это потребует прописывать вызов ядра анализатора PVS-Studio.exe для каждого компилируемого файла, по аналогии с тем, как вызывается C++ компилятор.

Влияние настроек PVS-Studio на запуск из командной строки; фильтрация и преобразование результатов анализа (plog файла)

При запуске анализа кода из командной строки по умолчанию используются все те же настройки, что и при запуске из IDE (Visual Studio). При этом используется столько ядер процессора, сколько указано в настройках. Также можно указать, какой файл настроек использовать, с помощью аргумента --settings, как было описано выше.

Что касается, к примеру, системы фильтров (Keyword Message Filtering и Detectable Errors), то она НЕ применяется при анализе из командной строки. В том смысле, что в файле отчета независимо от заданных параметров будут все сообщения об ошибках. Но при загрузке файла с результатами в IDE фильтры уже будут применены. Это происходит из-за того, что фильтры применяются динамически к результатам (и при запуске из IDE также). Это очень удобно, поскольку, получив список сообщений, вы можете захотеть отключить некоторые из них (например, V201). Достаточно отключить их в настройках и соответствующие сообщения пропадут из списка БЕЗ перезапуска анализа.

Формат файла-отчёта (plog файл имеет XML формат) не предназначен для прямого отображения или чтения человеком. Однако, если необходимо каким-либо образом отфильтровать результаты анализа и преобразовать их в "читаемый" вид, можно воспользоваться утилитой PlogConverter, поставляемой в дистрибутиве PVS-Studio. Вы также можете скачать исходный код утилиты.

PlogConverter позволяет преобразовать один или несколько plog файлов в следующие форматы:

  • легковесный текстовый файл с результатами анализа. Может быть удобен для вывода результатов анализа (например, новых сообщений анализатора) в лог сборочной системы \ сервера непрерывной интеграции;
  • отчёт HTML с кратким описанием результатов анализа. Подходит для рассылки уведомлений электронной почтой;
  • отчёт HTML с сортировкой результатов анализа по разных параметрам и навигацией по исходному коду;
  • CSV таблица с результатами анализа;
  • Tasks файл для просмотра в QtCreator;
  • текстовый файл, содержащий сводную таблицу количества сообщений на разных уровнях\группах диагностик.

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

Приведём пример строки запуска утилиты PlogConverter (одной строкой):

PlogConverter.exe test1.plog test2.plog -o "C:\Results" -r "C:\Test" 
-a GA:1,2,3;64:1 -t Html,Txt,Totals -d V101,V105,V122

PlogConverter будет запущен для файлов текущей директории 'test1.plog' и 'test2.plog', результаты работы для заданных файлов будут объединены и сохранены в папку Results на диске C, будут выданы только сообщения из групп диагностик General Analysis (GA), 1, 2 и 3 уровней, и группы 64 битных ошибок (64) 1 уровня. Диагностики с кодами V101, V105 и V122 будут отфильтрованы из результатов анализа. Результаты будут сохранены в виде текстового и HTML файлов, а также в виде сводного текстового файла по всем диагностикам (с учётом ранее названных критериев фильтрации). Оригинальный plog файл в результате работы утилиты изменён не будет.

Детальное описание уровней достоверности предупреждений и наборов диагностических правил приведено в разделе документации "Знакомство со статическим анализатором кода PVS-Studio".

Подробная справка по всем параметрам утилиты PlogConverter доступна с помощью команды

PlogConverter.exe --help

Если же вам необходимо преобразовать результаты анализа (plog файл) в какой-либо особенный формат, вы можете сделать это, самостоятельно прочитав plog файл, как XML документ. Заметьте, что вы можете переиспользовать алгоритм разбора структуры plog файла из нашей утилиты для создания собственного формата вывода результатов анализа.

Регулярное использование PVS-Studio и интеграция в процесс "ежедневных сборок"

Работа с анализатором кода PVS-Studio состоит из двух этапов: внедрение и постоянное использование. На этапе внедрения PVS-Studio в существующий крупный проект программисты просматривают сообщения анализатора и либо исправляют код, либо размечают код с помощью функций "Mark as False Alarm" и "Message Suppression". Разобравшись со всеми сообщениями от PVS-Studio, разработчики запускают окончательную проверку всего кода и получают 0 сообщений от анализатора (если не включено отображение ошибок, размеченных как ложные срабатывания или подавленных через suppress файлы). Это означает, что стадия внедрения завершена и начинается стадия регулярного использования.

Теперь весь новый код, который добавляется в проект, будет проверяться с помощью PVS-Studio. На самом деле проверяться будет ВЕСЬ код, но ошибки будут обнаруживаться только новые. Ошибки будут найдены во вновь написанном/исправленном коде или в старом коде, который так и не был размечен.

Возможность запуска анализа кода из командной строки нужна для того, чтобы выполнять регулярную (к примеру, ежедневную) проверку кода. Процедура выглядит так:

  • Запустить проверку кода из командной строки.
  • Отправить получившийся файл отчета всем заинтересованным разработчикам.

Таким образом, ежедневный запуск PVS-Studio позволит избежать появления новых ошибок в вашем коде.

Авто-обновление и установка дистрибутива PVS-Studio

Для установки дистрибутива PVS-Studio из командной строки в "тихом" режиме (т.е. без интерфейса и диалоговых окон), нужно передать ему следующие параметры (одной строкой):

PVS-Studio_setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
/COMPONENTS=Core,Standalone,MSVS,MSVS\2010,
MSVS\2012,MSVS\2013,MSVS\2015,MSVS\2017,MSVS\2019

Аргумент /COMPONENTS позволяет задать устанавливаемые компоненты: Standalone (C and C++ Compiler Monitoring), плагины для разных IDE. Данный аргумент является необязательным.

PVS-Studio может потребоваться перезагрузка компьютера в случае, например, если обновляемые файлы были заблокированы. Для установки без перезагрузки необходимо использовать флаг 'NORESTART'. Обратите внимание, что при запуске установщика PVS-Studio в silent режиме перезагрузка может произойти без предварительных уведомлений или диалогов.

Обратите внимание, что одновременно с установкой PVS-Studio не допускается запускать Visual Studio (процесс devenv.exe).

Утилита PVS-Studio-Updater.exe позволяет проверить наличие обновлений анализатора, а в случае их наличия, скачать и установить их на локальной машине. Для запуска утилиты обновления в 'тихом' режиме можно использовать те же параметры, что и для дистрибутива:

PVS-Studio-Updater.exe /VERYSILENT /SUPPRESSMSGBOXES

В случае отсутствия обновлений на сервере, утилита завершит работу с кодом 0. Т.к. PVS-Studio-Updater.exe производит локальную установку PVS-Studio, во время его работы в системе также не должен быть запущен процесс devenv.exe.

Заключение

Ежедневный запуск PVS-Studio из командной строки способен существенно повысить качество кода. В таком случае при корректном коде ежедневно вы будете видеть 0 новых сообщений от анализатора. Если произойдет некорректная модификация старого (ранее просмотренного) кода, то очередной запуск PVS-Studio сразу выявит внесенные дефекты. Новый код естественно также будет проверяться регулярно в автоматическом (независимом от программиста) режиме.


Найденные ошибки

Проверено проектов
361
Собрано ошибок
13 417

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;