Автоматическая проверка стиля кодирования

Когда над одним проектом работает несколько человек, то использование каждым программистом своего стиля кодирования затрудняет чтение, поддержку и слияние кода. Хороший вариант — принудительное использование единого стиля кодирования, например: JSF Air Vehicle — C++ Coding Standards, Google C++ Style Guide, Стандарты программирования на C++" от Александреску.
Однако каждый программист ленив и старые привычки написания кода искоренить совсем непросто. На помощь приходят так называемые code beautifier'ы. Мой выбор для языка C++ это: стандарт кодирования от Гугл + CppLint.
CppLint — это скрипт на Питоне и для его работы необходимо иметь этот самый Питон (версии 2.х и 3.х не совместимы, требуется именно 2.х). Установив Питон и проассоциировав файлы .py, можно запустить из скрипт cpplint на исполнение из командной строки и прочитать хэлп:
cpplint.py --help


Интересно и вполне себе всё понятно. Теперь можно проверить тестовый файл:
cpplint.py cpplint_test_header.h


Работает замечательно. Однако регулярно проверять каждый исходник своего проекта руками из под консоли — занятие и неприятное, и неблагодарное. Очень уж хочется это дело автоматизировать и добавить в процесс сборки проекта. Как это сделать? Нужно залезть в makefile. Сейчас я работаю с pic'ами из под MPLAB X с компилятором xc32 (а это g++), и для каждого проекта существует доступный для редактирования makefile (изменения проекта в среде влекут изменения автогенерируемых makefile'ов, включаемых в основной).
Добавив в переменные среды системы путь к установленному нами Питону, закинем скрипт в ту же директорию в подпапку cpplint и расскажем об этом в makefile'e:

# cpplint settings
python27      = $(PYTHON)/python
cpplintDir    = $(PYTHON)/cpplint

Вызов питоновского скрипта:

cpplintScript = $(shell $(python27) $1 $2)

Осталось определить файлы, для которых будет вызываться cpplint (их будем передавать аргументом скрипту). В моём проекте весь код структурирован так:
  • main.cpp в директории app/
  • Заголовочные файлы модулей в директории app/inc/<MODULE_NAME>/
  • Исходники модулей в директории app/src/<MODULE_NAME>/
Создадим новую цель и укажем зависимости требуемые для анализа файлы:

.PHONY: cpplint
cpplint: app/*.cpp \
	app/inc/*/*.h \
	app/src/*/*.cpp 
	$(call cpplintScript, $(cpplintDir)/cpplint.py, $^ )

Имя цели — cpplint, зависимости — все файлы .cpp в папке app/, все файлы .h во всех подпапках первого уровня по адресу app/inc/, все файлы .cpp во всех подпапках первого уровня по адресу app/src. Цель выполняет вызов скрипта параметрами передаёт $^, т.е. список всех зависимостей. Как вариант, можно воспользоваться одним из определений в makefile с перечислением всех исходных файлов, однако лично мне это не нужно. В случае сильно многоуровневой иерархии проекта желательно воспользоваться рекурсией makefile'ов.
Замечательно, осталось только вsgjkyznm эту цель до сборки проекта:
.build-pre: cpplint

После сборки результат виден в окошке Output MPLAB'а:

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

cpplintFlags  = --verbose=0
cpplintFiles  = $(wildcard app/*.cpp) \
	        $(wildcard app/*.c) \
	        $(wildcard app/inc/*/*.h) \
	        $(wildcard app/src/*/*.cpp)

cpplint:
	$(call cpplintScript, $(cpplintDir), $(cpplintFlags) $(cpplintFiles) )

Для получения ещё большего удовольствия от сборки проекта добавим автоматическую генерацию документации по doxygen:

.build-post: .build-impl doxy

...

.PHONY: doxy
doxy:
	doxygen Doxyfile

Дополнительно:


Если у кого-то появится желание использовать данный стандарт кодирования для программ на языке Си, то необходимо вручную добавить расширение *.c в cpplint.py:
_valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh', 'c'])
  • +4
  • 01 июля 2014, 13:46
  • becopt

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

RSS свернуть / развернуть
А не проще ли использовать утилиты автоматического форматирования, типа AStyle? Зачем делать руками то, что можно автоматизировать?
Взять за правило, перед commit-ом очередной порции кода в систему контроля версии проводить приведение кода к стандартному стилю. Через какое то время, все привыкают к одному стилю, и начинают писать используя его.
0
Наверное я просто не готов нажимать магическую кнопку, а потом удивляться в стиле «Что это? Я же такого не писал / писал совсем не так...» :)
Вероятно нажать кнопку и проще, но исправляя ошибки точно учишься быстрее. В своё время работая на Java меня очень впечатлил checkstyle.
0
В человеческих IDE эта функция уже встроена.
0
Хороший вариант — принудительное использование единого стиля кодирования

Я хотел бы подчеркнуть, что это не просто «хороший вариант» — это жизненная необходимость.
0
кодирования… слово то какое…
0
  • avatar
  • xar
  • 02 июля 2014, 00:05
Про это уже обсуждали здесь как-то: сподручнее для языка происходит новое словообразование с использованием именно «кодирование», чем уже от устаревающего «программирование».

P.S. Хотя, лучше бы что-то подобное почитать про Coding Standards of Embedded C Programming for MCU
0
Программирование и кодирование — несколько разные понятия, так что стиль относится именно ко второму. Ни о каком «устаревании» и речи не идет.
0
написание же
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.