Как стать автором
Обновить

Сортировка Конфигов для Make Сборок

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров2.2K

Как известно любая большая программа на Си содержит много программных компонентов и, как следствие, много настроек: констант, макросов, конфигурационных структур и прочего. Всё это можно назвать одним словом: конфиги.

Все передают конфиги по-разному. Это один из религиозных аспектов в программировании микроконтроллеров.

1--Junior разработчики прописываю (про)hard(коженные) константы в каждом файле проекта или пихают всё в config.h, который потом вручную подключают #include(ом) во все *.с файлы,

2--Middle программисты передают конфиги через переменные окружения, которые определяют в скриптах сборки (Make, Cmake и т.п.).

3--Senior(ы) вообще передают конфиги через Device Tree и механизм Kconfig.

Тут мы не будет рассуждать как лучше и правильнее передавать конфиги в сборки. Поговорим лишь о том как поступать во втором случае, когда конфиги прописаны как переменные окружения в отдельном make файле по имени config.mk.

Терминология

Конфиг - набор определенных переменных окружения, которые используются при сборке программы (например на Си).

Цель - последовательность процессов, которые запускает утилита make, чтобы получить какой-то файл или просто выполнить действие.

Сборка - это папка с настройками конкретного проекта программы и артефакты. Обычно сборка это комплект следующих файлов: Makefile, config.mk, version.h. Если Вы работаете в Eclipse, то к файлам сборки также относятся настройки текстового редактора Eclipse для этой конкретной сборки. Это файлы *.project *.cproject. Всё перечисленное следует подвергать версионному контролю (например в GIT). Сборка порождает артефакты. Это файлы *.hex, *.bin, *.map, *.elf. Хорошей практикой считается, когда в папке со сборкой даже нет ни одного *.с файлика! Всё, что нужно сборка берёт из общей пере используемой кодовой базы, которая лежит в другой папке.

Пролог

У нас в репозитории есть много сборок (порядка 350) на все случаи жизни, где конфиги передаются прямо через переменные окружения прописанные в make скриптах.

У каждой сборки есть файл config.mk в котором перечислены программные компоненты из которых должна собираться эта конкретная сборка. Содержимое этого файла обычно выглядит так.

#Do not include .mk files here. That is general global configuration
ADC=Y
ADC_ISR=Y
ADT=Y
ALLOCATOR=Y
ARRAY=Y
ASICS=Y

....

TASK=Y
TBFP=Y
TERMINAL=Y
TIME=Y
UART0=Y
UART2=Y
UNIT_TEST=Y
UTILS=Y
UWB=Y

Это просто атомарные строчки. Тут происходит определение переменных окружения. Декларативно перечисляется из чего собирать прошивку. У другой сборки есть свой такой же декларативный config.mk файл и свой собственный набор переменных окружения.

В чем проблема?

1--Проблема в том, что, когда сборок становится слишком много, то их приходится создавать по образу и подобию других сборок. Потом часто возникает потребность сравнить конфиги двух разных сборок и выясняется, что конфиги сильно отличаются.

Причем они отличаются не потому, что состоят из разных программных компонентов, а потому, что строчки в конфиг файлах перечислены в случайном порядке, перемешаны (не отсортированы). Как известно, правда в том, что минимальный diff будет у двух отсортированных файлов.

2--При командной разработке разные разработчики не глядя на существующий конфиг повторно добавляют новые строчки переменных окружения, которые дублируют старые переменные окружения. Иногда они добавляют вперед и их переменная окружения не применяется. Переменная окружения перетирается предшественником. Если же добавляют переменную окружения в конец файла кофига, то она обнуляет предыдущую переменную окружения. В общем это порождает анархию и взаимную ненависть.

Когда конфиг отсортирован, то его проще просматривать и искать в нем что-то. Также легче найти место для вставки новой переменной окружения методом визуального бинарного поиска.

В связи с этим возникают две задачи:

1--Удалить повторяющиеся переменные окружения.

2--Отсортировать переменные окружения по алфавиту внутри файла config.mk.

Как отсортировать конфиги?

1--Понятное дело, что вручную никто не хочет сортировать 150 строчек в файле. Дело в том что очень мало программистов вообще знают сколько букв содержится в английском алфавите и еще меньше людей могут сходу взять карандаш и правильно написать порядок букв английского алфавита от A до Z. И это нормально! Надо просто автоматизировать процесс сортировки файла.

2--Можно написать отдельный *.bat файл для сортировки когфигов культовой консольной утилитой sort.exe. Утилиту sort можно установить из пакета CygWin. Однако вам придется при добавлении каждой новой сборки также прописывать новую строчку в этом *.bat файле сортировки. По факту оказалось, что людям просто лень этим заниматься. И это тоже нормально!

3--Самое правильное решение - это встроить сортировку конфигов в сам процесс сборки артефактов. К счастью, мы традиционно используем систему сборки GNU Make и тут это сделать очень просто. Для этого надо всего лишь определить ещё одну крохотную цель sort_config.

SORTER_TOOL=C:/cygwin64/bin/sort.exe
$(info Sort Program config)

$(info MK_PATH=$(MK_PATH))
MK_PATH_WIN := $(subst /cygdrive/c/,C:/, $(MK_PATH))
$(info MK_PATH_WIN=$(MK_PATH_WIN))
$(info WORKSPACE_LOC=$(WORKSPACE_LOC))

PROJECT_DIR=$(MK_PATH_WIN)

CONFIG_FILE=$(PROJECT_DIR)/config.mk
$(info CONFIG_FILE=$(CONFIG_FILE))

#CONFIG_FILE:=$(subst /cygdrive/c/,C:/, $(CONFIG_FILE))
#$(info CONFIG_FILE=$(CONFIG_FILE))

sort_config: $(CONFIG_FILE)
	$(info SortConfig...)
	$(SORTER_TOOL) -u $(CONFIG_FILE) -o $(CONFIG_FILE)

Тут опция -u означает, что утилита sort будет удалять повторения, а конструкция $(CONFIG_FILE) -o $(CONFIG_FILE) означает, что имя файла на выходе будет совпадать с именем файла на входе. Получается сортировка in place.

Затем надо открыть основной rule.mk и встроить туда новую цель sort_config. Перед сборкой сорцов отсортировать конфиг


EXTRA_TARGETS += sort_config
EXTRA_TARGETS += $(DEPENDENCY_GRAPH)
EXTRA_TARGETS += $(STATIC_ANALYSIS_TARGET)
EXTRA_TARGETS += $(CLI_COMMAMD_LIST_GENERATE)
EXTRA_TARGETS += $(PREPROCESS_CODE_BASE)
EXTRA_TARGETS += generate_definitions

# default action: build all 
all: $(EXTRA_TARGETS) $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin 

generate_definitions:
	cpp $(CPP_FLAGS) $(WORKSPACE_LOC)empty_sourse.c -dM -E> c_defines_generated.h

Достоинство rule.mk в том, что он общий на все 150-350 сборок в нашем репозитории. И нам не нужно ничего больше прописывать в настройках каждого проекта, как если бы мы программировали микроконтроллер в пресловутом IAR или Keil.

Теперь если Вы откроете папку сборки в консоли и напишите make all, Вы через минуту получите не только артефакты, но и аккуратный причёсанный конфиг!

Сортировка нужна не только в сортировке конфигов. Автоматический форматировщик отступов в Си коде clang-format.exe, например, еще сортирует #include по алфавиту.

Общая канва в том, что в программировании надо сортировать всё, что перечисляется и где порядок не имеет существенного значения. Это перечисление прототипов фунцнкий, перечисление констант emumeratios, перечисление include(ов), перечисление конфигов и т.п.

Итоги

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

При этом сортировка это признак наличия какого-то разума и культуры. Например посвящённые страны сортируют даже бытовой мусор.

Как видите, использование сборки из-под скриптов позволяет Вам помимо самой сборки артефактов еще и выполнять всяческую инфраструктурную DevOps(овую) работу. Это особенно просто и легко делается в GNU Make.

GNU Make вообще всё равно с каким языком программирования работать. Более того, GNU Make всё равно даже какие консольные утилиты запускать.

Links

https://ru.wikipedia.org/wiki/Sort

Генерация зависимостей внутри программы
https://habr.com/ru/articles/765424/

Сборка firmware для CC2652 из Makefile
https://habr.com/ru/articles/726352/

Почему Важно Собирать Код из Скриптов
https://habr.com/ru/articles/723054/

Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB
https://habr.com/ru/articles/673522/

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы использовали утилиту sort для чего-либо?
55.56% да10
44.44% нет8
Проголосовали 18 пользователей. Воздержался 1 пользователь.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали программы из GNU Make?
90.48% да19
9.52% нет2
Проголосовал 21 пользователь. Воздержался 1 пользователь.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Как Вы передаете конфигурации для сборки С/C++ программ/прошивок?
30% через прохардкоженные константы прямо в коде6
65% через *.h файлики13
15% через скрипты сборки GNU make3
10% через механизм Device Tree2
10% через механизм Kconfig2
45% через скрипты Сmake9
30% через конфигурационный структуры в Си коде6
0% через скрипты ninja0
10% через xml(ку) для GUI-IDE2
Проголосовали 20 пользователей. Воздержались 3 пользователя.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы пользуетесь утилитой WinMerge?
35.29% да6
64.71% нет11
Проголосовали 17 пользователей. Воздержавшихся нет.
Теги:
Хабы:
Всего голосов 9: ↑4 и ↓5+1
Комментарии10

Публикации

Истории

Работа

Программист С
32 вакансии
DevOps инженер
41 вакансия

Ближайшие события

7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
22 – 24 ноября
Хакатон «AgroCode Hack Genetics'24»
Онлайн
28 ноября
Конференция «TechRec: ITHR CAMPUS»
МоскваОнлайн
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань