Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
Как мы исправили один баг в CMake

Как мы исправили один баг в CMake

23 Мар 2020

В августе 2019 года в CMake появилась долгожданная поддержка предкомпилированных заголовков. До этого приходилось использовать разные плагины, например, Cotire. Сразу после выпуска CMake с новым функционалом было ещё несколько доработок. Но уже осенью мы посчитали, что можно начать использовать эту фичу, и переписали наши скрипты. Позже мы нашли баг, который формировал неправильные параметры компилятора Clang и мешал запуску анализатора PVS-Studio. Баг пришлось исправить самим.

0719_CMakePchFix_ru/image1.png

Что не так?

Проблема была в том, что исходный файл, в котором использовался предкомпилированный заголовок, был некорректно препроцессирован, если использовался компилятор Clang. На месте header-файла было пустое место. Но в GCC и MSVC все работало нормально.

Что делает CMake?

Стоит рассказать о том, как CMake формирует предкомпилированный заголовок. Для каждого target'а (а начиная с CMake 3.17 и для каждого типа сборки – Debug, Release, ...) создается 2 файла: cmake_pch.hxx и cmake_pch.cxx. hxx-файл – это header-файл, из которого уже будет сформирован предкомпилированный заголовок, а cxx – пустой файл с содержимым:

/* Generated by CMake */

Нужен он для генерации предкомпилированного заголовка – он используется как исходник при запуске компилятора.

Во время сборки проекта заголовочный файл включается через передачу флагов компилятора. Для Clang это:

-Xclang -include-pch -Xclang <PCH_FILE>

Т.е. в команду компиляции передается уже созданный предкомпилированный заголовок. В итоге команды запуска сохраняются в файле compile_commands.json, который анализатор использует для проверки проекта.

Проблема

Однако на этом моменте имя оригинального header-файла потеряно. При запуске препроцессора Clang пытается достать имя заголовочного файла из созданного предкомпилированного заголовка и в итоге использует пустой файл cmake_pch.cxx. Почему? Если взглянуть в документацию Clang, то можно увидеть их способ создания предкомпилированных заголовков:

To generate PCH files using clang -cc1, use the option -emit-pch:
$ clang -cc1 test.h -emit-pch -o test.h.pch

Заголовочный файл test.h используется в качестве исходного. А вот как делает CMake:

-Xclang -emit-pch -Xclang -include -Xclang <PCH_HEADER>

Он включает его через специальный флаг, а затем передает cmake_pch.cxx как исходник. Информация о включенных файлах, переданных через командную строку, к сожалению, теряется, а информация об исходном файле остается. Это можно узнать, посмотрев документацию Clang:

Original file name
    The full path of the header that was used to generate the AST file.

Но как в этом случае работал Cotire?

Cotire по своей структуре похож на CMake, однако cxx-файл выглядел примерно так:

#ifdef __cplusplus
#include "/path/to/header.hxx"
#endif

В исходнике у него была директива include, поэтому препроцессор работал нормально. Это первое, что мы хотели предложить в качестве исправления.

Однако при таком подходе появились проблемы - нарушалась кодировка файлов (компилятор может преобразовывать исходный файл в свою кодировку), могла сломаться работа других компиляторов, а в CMake 3.17 файл cmake_pch.cxx создавался только один для каждого типа сборки, когда hxx-файлы могли отличаться.

Решение

В итоге было решено передавать в строку компиляции еще и оригинальный исходный файл:

-Xclang -include-pch -Xclang <PCH_FILE> -Xclang -include -Xclang <PCH_HEADER>

Благодаря опции -Xclang следующий флаг передается напрямую в препроцессор, минуя драйвер, который выполняет поиск соответствующего заголовку .pch/.gch файла. Ссылка на патч: PCH: Clang: Update PCH usage flags to include original header.

Заключение

Наш небольшой патч вошел в CMake 3.17, исправив проблему. Надеюсь, было интересно, и вы узнали чуть больше о работе CMake.

Мы можем рекомендовать использовать эту фичу в реальных проектах.

Популярные статьи по теме
PVS-Studio ROI

Дата: 30 Янв 2019

Автор: Андрей Карпов

Время от времени нам задают вопрос, какую пользу в денежном эквиваленте получит компания от использования анализатора PVS-Studio. Мы решили оформить ответ в виде статьи и привести таблицы, которые по…
Эффект последней строки

Дата: 31 Май 2014

Автор: Андрей Карпов

Я изучил множество ошибок, возникающих в результате копирования кода. И утверждаю, что чаще всего ошибки допускают в последнем фрагменте однотипного кода. Ранее я не встречал в книгах описания этого …
Как PVS-Studio оказался внимательнее, чем три с половиной программиста

Дата: 22 Окт 2018

Автор: Андрей Карпов

PVS-Studio, как и другие статические анализаторы кода, часто выдаёт ложные срабатывания. Но не стоит спешить считать странные срабатывания ложными. Это короткая история о том, как PVS-Studio вновь ок…
Характеристики анализатора PVS-Studio на примере EFL Core Libraries, 10-15% ложных срабатываний

Дата: 31 Июл 2017

Автор: Андрей Карпов

После большой статьи про проверку операционной системы Tizen мне было задано много вопросов о проценте ложных срабатываний и о плотности ошибок (сколько ошибок PVS-Studio выявляет на 1000 строк кода)…
Бесплатный PVS-Studio для тех, кто развивает открытые проекты

Дата: 22 Дек 2018

Автор: Андрей Карпов

В канун празднования нового 2019 года команда PVS-Studio решила сделать приятный подарок всем контрибьюторам open-source проектов, хостящихся на GitHub, GitLab или Bitbucket. Им предоставляется возмо…
PVS-Studio для Java

Дата: 17 Янв 2019

Автор: Андрей Карпов

В седьмой версии статического анализатора PVS-Studio мы добавили поддержку языка Java. Пришло время немного рассказать, как мы начинали делать поддержку языка Java, что у нас получилось и какие дальн…
Главный вопрос программирования, рефакторинга и всего такого

Дата: 14 Апр 2016

Автор: Андрей Карпов

Вы угадали, ответ - "42". Здесь приводится 42 рекомендации по программированию, которые помогут избежать множества ошибок, сэкономить время и нервы. Автором рекомендаций выступает Андрей Карпов - тех…
Зло живёт в функциях сравнения

Дата: 19 Май 2017

Автор: Андрей Карпов

Возможно, читатели помнят мою статью под названием "Эффект последней строки". В ней идёт речь о замеченной мной закономерности: ошибка чаще всего допускается в последней строке однотипных блоков текс…
Технологии, используемые в анализаторе кода PVS-Studio для поиска ошибок и потенциальных уязвимостей

Дата: 21 Ноя 2018

Автор: Андрей Карпов

Краткое описание технологий, используемых в инструменте PVS-Studio, которые позволяют эффективно обнаруживать большое количество паттернов ошибок и потенциальных уязвимостей. Статья описывает реализа…
Любите статический анализ кода!

Дата: 16 Окт 2017

Автор: Андрей Карпов

Я в шоке от возможностей статического анализа кода, хотя сам участвую в разработке инструмента PVS-Studio. На днях я был искренне удивлён тому, что анализатор оказался умнее и внимательнее меня.

Комментарии (0)

Следующие комментарии

На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять