«Если смотреть на закипающий чайник, то он никогда не закипит»

Пролог

Компиляцию большой программы можно сравнить с кипячением воды. Вы никогда не можете сказать сколько еще осталось ждать до окончания процесса. Многим пользователям GUI-IDE приходится страдать от того, что запустив сборку проекта приходится ждать окончания непредсказуемое время.

Однако эту проблему можно решить если собирать код скриптами сборки. Достоинством сборки проекта из самостоятельно написанных скриптов является то, что в процесс сборки можно добавлять всяческие полезные механизмы. Вы программируете не только свою прошивку, но и процесс сборки самой прошивки.

В этом тексте я написал про то, как добавить индикатор прогресса в процесс сборки прошивки.

Теория

переменная окружения - ( environment variable) — это просто текстовая строка. Её видят все процессы в операционной системе. Благодаря переменным окружения программы могут получать себе конфиги.

инкрементировать - увеличивать на единицу

Реализация

Основная идея очень проста. Надо сначала посчитать сколько нам надо собрать объектных файлов TOTAL_FILES, затем собирать си файлы один за другим и каждый раз увеличивать на единицу отдельную переменную окружения CURRENT_CNT. После каждой сборки файла печатать в консоль рациональное число CURRENT_CNT/TOTAL_FILES для оценки проделанной работы на текущем этапе. Но обо всем по порядку.

Проще всего сделать progress bar как раз в случае когда, в качестве системы сборки выбран GNU Make.

Утилита make хороша тем, что может работать практически с неограниченным количеством переменных окружения.

Первым делом надо определить сколько всего файлов участвует в сборке программы. Это можно определить просто просчитав количество слов в переменной окружения OBJECTS

OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(SOURCES_TOTAL_C:.c=.o)))

TOTAL_FILES := $(words $(OBJECTS))
$(info TOTAL_FILES:$(TOTAL_FILES) )

Да. В языке make есть функции которые могут получать аргументы и возвращать результат.

Имя функции GNU Make

Назначение

info

функция печатает то, что передается ей в аргументы в stdout

eval

это функция, которая позволяет вычислять простые математические формулы. Позволяет определять не постоянные переменные. То есть в переменную помещает результат оценки других переменных или функций. Аргумент функции eval расширяется. eval функция ничего не возвращает

notdir

извлечь имя файла отбросив информацию об расположении папки

shell

это функция, которая может общаться с окружением вне make-файла

addprefix

Добавляет приставку к каждому слову в переменной окружения

words

Возвращает количество слов в тексте

Львиную долю процесса сборки занимает компиляция си-файлов. Поэтому имеет смысл инкрементировать переменную окружения CURRENT_CNT каждый раз, когда происходит одно преобразование из *.с файла в *.o файл.

Перед вами правило получения объектных файлов.

Цель (что надо получить) : зависимости (исходное сырье)
действия для достижения цели (рецепты)

В этом вся суть GNU Make.

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 
	$(eval CURRENT_CNT=$(shell echo $$(($(CURRENT_CNT)+1))))
	@echo Compiling $(CURRENT_CNT)/$(TOTAL_FILES) $@
	@ $(CC) -c -MD $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

Тут оператор @ перед вызовом компилятора нужен для того, чтобы не печатать строку в консоль а только запустить ее на исполнение. Когда строка начинается с @, то эхо набора команды подавляется. Это нужно, чтобы не захламлять многословием лог сборки проекта, ибо переменная окружения CFLAGS содержит длинные пути к заголовочным файлам и плотные пучки опций для компилятора gcc.

Тут можно еще заметить специальную переменную $@. Она просто заменяется на имя цели обрабатываемого правила. Это раскроется в объектные файлы build/test_libc.o build/test_sw_list.o build/test_drv8870.o и т д

Специальная переменная $< - это имя первой зависимости обрабатываемого правила. В данном случае это си файлы.

Всё готово. Теперь можно и запустить сборку программы набрав make all.

В натуре выглядит это так.

Как по, мне очень наглядно.

Итог
Удалось добавить в процесс сборки индикацию прогресса буквально добавив всего 3 строчки кода в скрипт сборки проекта. Вот так просто и не затейливо. Вам уже нравится GNU Make?

Теперь больше нет мучительных ожиданий окончания компиляции. Всё стало прозрачнее и понятнее. Можно распределять свое внимание между другими задачами.

Ссылки

Название

URL

Сколько Надо Строк Кода Для Того Чтобы Подписать Артефакты? (3 строки в Makefile)

https://habr.com/ru/articles/731484/

Генерация зависимостей внутри программы в Makefile

https://habr.com/ru/articles/765424/

Сборка firmware для CC2652 из Makefile

https://habr.com/ru/articles/726352/

ToolChain: Настройка сборки прошивок для микроконтроллеров Artery из Makefile

https://habr.com/ru/articles/792590/

Интеграция clang-format в Процесс Сборки c Makefile

https://habr.com/ru/articles/833500/

Как составить функцию инициализации микроконтроллера в Makefile

https://habr.com/ru/articles/818917/

Как собрать Си программу в OS Windows через Makefile

https://habr.com/ru/articles/754972/

Автоматическое Обновление Версии Прошивки в Makefile

https://habr.com/ru/articles/791768/

Настройка ToolChain(а) для Win10+GCC+С+Makefile+ARM Cortex-Mx+GDB

https://habr.com/ru/articles/673522/

Обновление Прошивки из Make Скрипта

https://habr.com/ru/articles/857416/

Почему важно собирать код из скриптов

https://habr.com/ru/articles/723054/

Вёрстка Учебника (LaTeX + CPP + GNU Make + Jenkins = Учебник)

https://habr.com/ru/articles/859120/

Почему Сборка с Помощью Есlipse ARM GCC Плагинов это Тупиковый Путь

https://habr.com/ru/articles/794206/

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

https://habr.com/ru/articles/745244/

Техникум: Автоматическое Aрхивирование Aртефактов в Makefile

https://habr.com/ru/articles/826730/

Сборка и отладка прошивки IoT-модуля: Python, make, апельсины и чёрная магия
@faruk_yussuf

https://habr.com/ru/companies/whoosh/articles/825330/

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


  1. kipar
    13.11.2025 19:22

    В CMake по умолчанию такой индикатор.


    1. randomsimplenumber
      13.11.2025 19:22

      Но его можно отключить ;)


  1. zubrbonasus
    13.11.2025 19:22

    Можно доверить сборку бинарника ci скрипту и делать это все на сервере, занимаясь при этом разработкой следующих задач.


    1. aabzel Автор
      13.11.2025 19:22

      Уже сделано
      Пуск Сервера Сборки Jenkins
      https://habr.com/ru/articles/695978/


  1. viordash
    13.11.2025 19:22

    а Вы не рассчитываете запускать сборку проектов в несколько потоков? например make all -j8


    1. aabzel Автор
      13.11.2025 19:22

      Она сейчас так и собирается

      echo off
      cls
      make clean 2>&1 | tee clean_log.txt
      make all -j8 | tee build_log.txt


      1. viordash
        13.11.2025 19:22

        хм, мне казалось что при параллельной сборки могут быть гонки у CURRENT_CNT. А у вас нумерация идет подряд, странно.