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

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

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

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

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

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

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

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

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

Цель - последовательность процессов, которые запускает утилита 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--Отсортировать конфиги по алфавиту.

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

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

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

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

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 означает, что утилита будет удалять повторения, конструкция $(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 в том, что он общий на все 350 сборок в нашем репозитории. И нам не нужно ничего больше прописывать в настройках каждого проекта, как если бы мы программировали микроконтроллер в пресловутом IAR или Keil.

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

Сортировка нужна не только в сортировке конфигов. Автоматический форматировщик отступов в Си коде clang-format.exe, например, еще сортирует #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 для чего-либо?
33.33% да 1
66.67% нет 2
Проголосовали 3 пользователя. Воздержался 1 пользователь.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Вы собирали программы из GNU Make?
100% да 3
0% нет 0
Проголосовали 3 пользователя. Воздержался 1 пользователь.
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Как Вы передаете конфигурации для сборки С/C++ программ/прошивок?
20% через прохардкоженные константы прямо в коде 1
60% через *.h файлики 3
20% через скрипты сборки GNU make 1
20% через механизм Device Tree 1
20% через механизм Kconfig 1
60% через скрипты Сmake 3
40% через конфигурационный структуры в Си коде 2
0% через скрипты ninja 0
0% через xml(ку) для GUI-IDE 0
Проголосовали 5 пользователей. Воздержались 2 пользователя.
Источник: https://habr.com/ru/articles/745244/


Интересные статьи

Интересные статьи

Недавно в рабочем проекте потребовалось реализовать универсальную сортировку, которая подходила бы для большинства моделей. Если с обычной сортировкой по полю всё просто - её, подробно описанную, вы н...
В сети огромное количество мануалов по созданию отказоустойчивых групп доступности AlwaysON Microsoft SQL Server посредством Windows Server Failover Cluster. Но что делать, если экземпляры Microsoft S...
В период с 199x по 201x развелось очень много программистов-микроконтроллеров, которые никогда не представляли свою работу без IDE (IAR, KEIL, Code Composer Studio, AtilocTrueStudio). В этом тексте я ...
Threading Building Blocks (TBB) — популярная библиотека для параллельного программирования на C++ с открытым исходным кодом, опубликована на GitHub. Пару лет назад команда разработки решилась на глоба...
Наверное никому из нас не нравится долго ждать завершения сборки проекта, когда каждая секунда похожа на вечность. И хорошо, если это рабочие часы, и скоротать время можно за кружечкой кофе, обсу...