![](https://habrastorage.org/getpro/habr/upload_files/fd6/0c8/7f2/fd60c87f29117cd4ee8ab8c31039f0ae.png)
Есть такая утилита для автоматического выравнивания отступов в исходных кодах. Называется clang-format.exe. Надо признать, что сейчас де факто основной утилитой автоматического выравнивания отступов является именно утилита clang-format.exe из LLVM. Её достоинство в том что ей всё равно в каком текстовом редакторе вы пишите код. Что в Eclipse, что Notepad++, что MS Visual Code. Сlang-format он выровняет всё, что ему подадут на вход в соответствии с указанным конфигом в опциях командной строки.
Есть еще тоже консольный GNU indent, однако indent очень устарел и слаб. Плюс падает от обнаружения препроцессора.
Цель данного текста- показать, как интегрировать clang-format в процесс сборки прошивки.
Почему обычно делают форматирование отступов в исходниках?
На то я вижу минимум три причины:
1--Для однообразности и красоты. В каждой российской компании свой собственный, внутренний, ни на кого больше не похожий стандарт оформления исходных текстов программ на Си. Причем отличается обычно на 80%..90% от других организаций.
2--Чтобы был минимальный diff при сравнении разных по времени версий одного и того же куска Си кода
3--Чтобы можно было составлять простые и предсказуемые регулярные выражения для поиска шаблонов кусков кода утилитой grep и find в репозитории с кодом.
В чем проблема?
Проблем тут две:
1--Первая проблема в том, что вручную выставлять отступы это очень утомительно и рутинно. Однако эта проблема решается, как раз, утилитами автоматического выставления отступов.
2--Вторая проблема в том, что для автоматического форматирования кода утилитами приходится составлять *.bat файл и явно прописывать внутри какой файл надо форматировать. Это тоже очень рутинно с учетом, что файлов в сборке порядка нескольких сотен. Вот у меня типичная сборка собирает 237 с-файликов. И что, мне прописывать 237 строчки в bat файле что ли?
Очевидно же, что надо как-то автоматизировать процесс прогона с-файлов через утилиту форматировщик clang-format.
Решение
Попробуем запустить clang-format автоматически из скриптов сборки. Проще говоря, надо вмонтировать утилиту автоматического выравнивания прямо в систему сборки прошивки.
Что надо из софта?
# |
Название утилиты |
Назначение |
1 |
grep |
рекурсивный поиск по файловой системе |
2 |
sed |
утилита авто замены ключевых слов в файлах |
3 |
make |
утилита управления системой сборки |
4 |
clang-format |
утилита автоматического выравнивания исходных кодов |
Можно написать отдельный make файл для вызова этой утилиты. Вот по такой схеме.
![](https://habrastorage.org/getpro/habr/upload_files/1da/c2e/53a/1dac2e53ac9a91fea086916d321482da.png)
Вот такой Make скрипт сам производит выравнивание тех же самых файлов, что участвовали в сборке прошивки.
$(info ClangFormatScript)
CLANG_FORMAT_TOOL =C:/cygwin64/bin/clang-format.exe
SOURCES_CF := $(subst .c,.cf, $(SOURCES_C))
#$(error SOURCES_CF=$(SOURCES_CF))
MCAL_STYLE="{
MCAL_STYLE+= BreakBeforeBraces: Attach,
MCAL_STYLE+= ColumnLimit: 120,
MCAL_STYLE+= IndentWidth: 4,
MCAL_STYLE+= PointerAlignment: Left,
MCAL_STYLE+= SortUsingDeclarations: true,
MCAL_STYLE+= SpaceBeforeParens: Never,
MCAL_STYLE+= SortIncludes: true,
MCAL_STYLE+= TabWidth: 4,
MCAL_STYLE+= UseTab: Never,
MCAL_STYLE+=}"
#$(error MCAL_STYLE=$(MCAL_STYLE))
%.cf: %.c
$(info RunClangFormat)
$(CLANG_FORMAT_TOOL) -verbose -i -style=$(MCAL_STYLE) $<
.PHONY: clang_format
clang_format: $(SOURCES_CF)
$(info ClangFormatDone)
Однако есть один момент. Не все файлы исходников следует подвергать автоматическому выравниванию. Дело в том, что если ты меняешь форматирование в файле, то ты, как бы, автоматически становишься владельцем этого кода. Оно тебе надо? Ты же не хочешь нести ответственность за этот странный чужой код просто потому, что ты там поменял TAB на 4 пробела? Поэтому существует такое негласное правило буравчика:
Ни в коем случае нельзя менять форматирование в чужом коде!
Очевидно, что в скриптах сборки надо как-то пометить те файлы сорцов, которые мы не будем форматировать. А в системе сборки make сделать это очень просто. Надо всего-навсего проиндексировать чужие сорцы в переменную окружения SOURCES_THIRD_PARTY_C.
ifneq ($(FAT_FS_MK_INC),Y)
FAT_FS_MK_INC=Y
FAT_FS_DIR += $(THIRD_PARTY_DIR)/fat_fs
#@echo $(error FAT_FS_DIR= $(FAT_FS_DIR))
INCDIR += -I$(FAT_FS_DIR)
INCDIR += -I$(FAT_FS_DIR)/src
INCDIR += -I$(FAT_FS_DIR)/src/options
SOURCES_THIRD_PARTY_C += $(FAT_FS_DIR)/src/diskio.c
#SOURCES_THIRD_PARTY_C += $(FAT_FS_DIR)/src/option/unicode.c
SOURCES_THIRD_PARTY_C += $(FAT_FS_DIR)/src/option/ccsbcs.c
SOURCES_THIRD_PARTY_C += $(FAT_FS_DIR)/src/ff.c
endif
Если лень это производить вручную, то можно применить этот bash скрипт
grep -rl SOURCES_C . | xargs sed -i 's/SOURCES_C/SOURCES_THIRD_PARTY_C/g'
Далее в rules.mk просуммировать те сорцы, которые мы форматируем SOURCES_C и те, которые мы не форматируем SOURCES_THIRD_PARTY_C в одну переменную окружения SOURCES_TOTAL_C
SOURCES_TOTAL_C += $(SOURCES_C)
SOURCES_TOTAL_C += $(SOURCES_THIRD_PARTY_C)
SOURCES_TOTAL_C := $(subst /cygdrive/c/,C:/, $(SOURCES_TOTAL_C))
Вот так получается, что THIRD PARTY код останется без изменений. Всё что надо - это открыть папку с проектом из консоли и набрать
make clang_format
Все нужные с-файлы станут с выровненными отступами. Автоматически...
Итоги
Как видите, сборка из скриптов (в частности make) дает такие преимущества как автоматическое выравнивание отступов исходного кода.
Понятное дело, что если вы собираете программы из IDE мышкой, то вам такое не доступно в принципе. Поэтому имеет смысл задуматься о переносе на сборки скриптами.
А с Make удалось с полпинка вмонтировать утилиту clang-format в основной конвейер сборки прошивки. Успех!
Словарь
акроним |
расшифровка |
LLVM |
Low Level Virtual Machine |
bash |
Bourne again shell |
GNU |
GNU’s Not UNIX |
sed |
Stream EDitor |
grep |
search Globally for lines matching the Regular Expression, and Print them |
Ссылки
Комментарии (18)
SnakeSolid
03.08.2024 05:06Я придерживаюсь следующей стратегии:
Озвучить всем стиль написания кода, включая отступы, расположение скобок и форматирование аргументов. В идеале, предоставить правила форматирования для популярных IDE.
Добавить прекоммит-хук, который будет запрещать заливать или мержить неправильно отформатированный код. В качестве альтернативы можно автоматически добавлять комментарии о неправильном форматировании в ревью.
После этого каждый разработчик может использовать тот инструмент, который ему удобен для форматирования. При необходимости, если стиль репозитория отличается от предложенного, можно либо сначала отформатировать весь код в едином стиле, либо фильтровать ошибки форматирования только в тех участках, где были внесены изменения.
Hamletghost
03.08.2024 05:06+2Добавлю, что правила можно положить сразу в репу, современные ide отлично его применяют перед комитом сами, в прекомите можно оставить только проверку. Ну и в ci должна быть lint стадия, где форматирование тоже должно провериться (если залили без хуков)
NN1
03.08.2024 05:06+2Дополню ответ утилитой pre-commit или ручной pre commit hook чтобы не забыть отформатировать перед комитом в случае правки в другом редакторе.
aabzel Автор
03.08.2024 05:06Проблема в том, что не все используют git c его hook(ами).
У других Perforсe, Arcadia, SVN, Mercurial, или вовсе под в ZIP архиве (привет военное НИИ).
Вот и получается что встроить форматирование в скрпипт сборки это самый демократичный вариант.NN1
03.08.2024 05:06+2У некоторых перечисленных уже есть precommit hook.
А ещё можно использовать git обёртку во многих случаях.
Zip архив ведь как-то создавался с системой контроля версий. Вот там и добавить.
При сборке конечно можно форматировать, только это не на каждую сборку стоит делать, а только на финальную иначе сборка будет занимать приличное время когда файлов будет много.
Caefah
03.08.2024 05:06+1clang-format очень тонко кастомизируемый инструмент под множество стандартов или личных предпочтений пользователя. В статье полно абсолютно ненужной «воды», но при этом отсутствует главное — то самое заявленное в заголовке и поэтому ожидаемое описание как работать с clang-format, используя всю его мощь и множество настроек.
aabzel Автор
03.08.2024 05:06Не согласен. Сlang-format не настолько гибкий как надо.
Сlang-format, например, не может принудительно выравнивать аргументы функций в столбик.Caefah
03.08.2024 05:06Я нигде и не заявлял что clang-format «гибкий как надо», идеален или абсолютно универсален. Поэтому не совсем понятно с чем именно Вы не согласны.
Это просто инструмент. Кому-то он подходит, кому-то — нет. Лично мне — нет. Я хочу вот так, а он этого не умеет:void add_string_to_array( char ***array, const char *another_array ){ int size = 0; if(array != NULL) { while(array[size] != NULL) { size++; } } }
aabzel Автор
03.08.2024 05:06А зачем выдумывать свое форматирование, если в Clang format нет для него опций?
Это же лишняя морока потом вручную всё расставлять.
aabzel Автор
03.08.2024 05:06Лично мне — нет. Я хочу вот так, а он этого не умеет:
И чем Вы тогда пользуетесь?
Caefah
03.08.2024 05:06+1Пока ничем. В IDE, только, использую удаление лишних табуляторов, пробелов и пустых строк. Ищу консольный инструмент, который бы мне подходил и его можно было бы использовать в Makefile. Но пока все ранее перепробованные не удовлетворяют требованиям. Где-то код отформатируют как надо, а в других, самых неожиданных местах, только всё испортят.
aabzel Автор
03.08.2024 05:06Вам не жалко вертикального пространства монитора, из за переноса фигурных скобок на новую строку?
Caefah
03.08.2024 05:06Для меня важно то, что строка с
while(array[si...
визуально не прилипает к вышестоящей строке с if
if(arr...
Поэтому она чётко видна и такой код более читабельный. Акцентирую на том, что это моё личное предпочтение и настаивать на каких-то форматах по-умолчанию вообще не в моих правилах. Не зря только в clang-format уже заложены десятки детерминированных форматов — важна универсальность в рамках одной группы, совместно трудящейся над общим кодом.
Вам не жалко вертикального пространства монитора
Мне не жалко. У меня для кода отдельный, вертикально ориентированный монитор. Очень удобно!
И очевидно, что пользователям моего ПО будет вообще безразлично оформление. Никого из них не заботит изящность. Зато волнуют ошибки, которые могут появиться по вине разработчика из-за плохой читабельности кода. Поэтому если есть выбор, то код я оформлю так, чтобы для меня было удобно кодить, благодаря чему мне и только мне будет комфортно ориентироваться в написанном.
aabzel Автор
03.08.2024 05:06Цель данного текста не научить пользоваться опциями clang-format , а показать, как интегрировать clang-format в процесс сборки прошивки.
randomsimplenumber
Смысл действия непонятен. Компилятору, который собирает бинарник, все равно как отформатирован исходник. Человек, которому не всё равно, читает исходники до сборки, а не после.
Я слышал, форматирование в IDE завезли.
aabzel Автор
Дело в том, что определённое форматирование требуют в компании. Якобы чтобы всё было однообразно и предсказуемо.
Я работал в нескольких компаниях и в 3 из 5 был свой стандарт отступов в коде.
Flammmable
Вы за 12 лет работы сменили не менее 5 компаний?
aabzel Автор
Задач по программировать микроконтроллеры в России очень мало.
Даже если Вы найдёте работу, то Вы сделаете всё за год, даже если будете писать всего лишь по 150 строчек кода в день. У вас буквально Flash память закончится за год. Прошивки пишутся быстро, особенно когда есть заготовки программных компонентов: MCAL, драйверы ASIC чипов, connectivity, sensitivity, computing, storage и control.
Как только Вы напишите прошивку, начальство станет предлагать Вам заняться всяческими смежными обязанностями: технический писатель, сисадмин, тестировщик, чертёжник, схемотехник, тополог, рабочий в производстве на участок ручной пайки поверхностного монтажа, курьер лишь бы хоть как-то оставить Вас в этой организации.
Если Вы будете отказываться, говоря, что хотите программировать микроконтроллеры дальше, то Вас станут изживать как проблемного сотрудника, перестанут давать новые задачи, назначат какую-н скучную рутину (например искать на рынке самые дешевые выводные резисторы), или придумают какую-нибудь провокацию (часто с участием женщин), спровоцируют на конфликт.
В этой профессии все пути тупиковые:
1—Если Вы будете бестолковым программистом, то Вас будут изживать из организации как безнадежного растяпу.
2—Если Вы будете очень толковым сотрудником, то Вас тоже будут изживать из организации ещё более интенсивнее, только уже как явного конкурента.
Программисты микроконтроллеров в России коммерческому рынку нужны, но только как сезонные работники на одну прошивку (полгода-год), подобно тому как в Финляндии сезонно нанимают сборщиков клубники. А потом тебе снова метаться по собеседованиям, искать фриланс, out source.
Многие будут склонять тебя организовать ИП или работать удалённо как самозанятого. Это называется "предприниматель в спальне".
Поэтому да, в среднем программисты-микроконтроллеров в России за 10 лет меняют работу от 7 до 15 раз...