Вопрос или проблема
Я пытаюсь создать простой проект, чтобы изучить autotools и automake. У меня есть подкаталог под названием Atmega-lib, который собирает статическую библиотеку под названием libatmega328p.a. Проблема, с которой я сталкиваюсь, заключается в том, что когда я запускаю make flash
, я получаю следующее сообщение:
make: *** No rule to make target 'Atmega-lib/libatmega328p.a', needed by 'atmega'. Stop.
Но запуск make
сначала, а затем make flash
работает. Как я могу сделать так, чтобы запуск только make flash
собирал все, а затем пытался выполнить правило?
Вот мой Makefile:
SUBDIRS = Atmega-lib
#SUBDIRS = Atmega-lib
AM_CFLAGS = -I$(SUBDIRS)/include -Wall -Wextra -std=c89 -g -Wpadded -Wconversion -fno-common -mmcu=atmega328p -Wl,--gc-sections -Wshadow -Wdouble-promotion -Wundef
# -nostdlib
OUTPUT_HEX = atmega328p.hex
bin_PROGRAMS = atmega
atmega_LDADD = Atmega-lib/libatmega328p.a
atmega_SOURCES = main.c
# Добавьте пользовательскую цель для прошивки
flash: atmega Atmega-lib/libatmega328p.a
@echo "Прошивка ATmega328P..."
avrdude -F -V -p m328p -c arduino -P /dev/ttyACM0 -b 115200 -U flash:w:$(OUTPUT_HEX):i
# Правило для создания hex файла с использованием avr-objcopy
$(OUTPUT_HEX): atmega
avr-objcopy -O ihex -R .eeprom $< $(OUTPUT_HEX)
Вещь, которую мне нужно сказать automake, – это сначала запустить SUBDIRS перед сборкой программы atmega, точно так же, как это происходит при запуске make
отдельно, но я не знаю, как это сделать.
РЕДАКТИРОВАТЬ:
Я добавил эту строку сразу после правила flash, и это сработало. Было ли это правильным способом решения моей проблемы?
# Добавьте пользовательскую цель для прошивки
flash:
$(MAKE)
@echo "Прошивка ATmega328P..."
avrdude -F -V -p m328p -c arduino -P /dev/ttyACM0 -b 115200 -U flash:w:$(OUTPUT_HEX):i
Спасибо заранее!
Ответ или решение
Чтобы решить проблему с зависимостями в вашем проекте, использующем Automake и Autotools, вам нужно убедиться, что при вызове make flash
сначала собираются все необходимые сайты, включая создание статической библиотеки libatmega328p.a
в каталоге Atmega-lib
. Это можно сделать, добавив несколько дополнительных правил в ваш файл Makefile.am
.
1. Основная проблема
Как вы заметили, при вызове команды make flash
возникает ошибка, потому что Make не знает, что необходимо сначала построить подкаталог Atmega-lib
. Ваша правка, которая добавляет вызов $(MAKE)
в целевой flash
, решает проблему, однако это не самое элегантное и правильное решение с точки зрения архитектуры Makefile. Использование $(MAKE)
для рекурсивного вызова может привести к потенциальным проблемам и не всегда является оптимальным.
2. Рекомендуемое решение
Чтобы правильно настроить ваш Makefile так, чтобы сначала выполнялась сборка подкаталогов, вы можете использовать следующий подход:
SUBDIRS = Atmega-lib
AM_CFLAGS = -I$(SUBDIRS)/include -Wall -Wextra -std=c89 -g -Wpadded -Wconversion -fno-common -mmcu=atmega328p -Wl,--gc-sections -Wshadow -Wdouble-promotion -Wundef
OUTPUT_HEX = atmega328p.hex
bin_PROGRAMS = atmega
atmega_LDADD = Atmega-lib/libatmega328p.a
atmega_SOURCES = main.c
# Описание ваших выходных файлов
$(OUTPUT_HEX): atmega
avr-objcopy -O ihex -R .eeprom $< $(OUTPUT_HEX)
# Расширенное правило для флешинга
flash: $(OUTPUT_HEX)
@echo "Flashing the ATmega328P..."
avrdude -F -V -p m328p -c arduino -P /dev/ttyACM0 -b 115200 -U flash:w:$(OUTPUT_HEX):i
# Убедитесь, что правила для подкаталогов выполняются перед построением программы
.PHONY: all flash
all: $(subdir-objects)
3. Объяснение изменений:
-
flash как зависимость от OUTPUT_HEX: Теперь цель
flash
зависит от$(OUTPUT_HEX)
, которое, в свою очередь, зависит отatmega
. Это значит, что при выполненииmake flash
, Make будет знать, что ему нужно сначала собрать все зависимости. -
Использование
.PHONY
: добавленный.PHONY
позволяет сделать целиall
иflash
явными для Make, что улучшает читаемость и поддержку Makefile. -
Встраивание всех правил в логическую структуру: Это способствует лучшему пониманию и поддержанию вашего Makefile. Теперь стоит ожидать, что, когда вы выполняете
make flash
, он правильно пройдет цепочку зависимости и соберет все необходимые файлы.
Заключение
Ваше первоначальное решение для вызова $(MAKE)
в целевой flash
— это ненадежный способ улучшающего процесса, и конструкция выше обеспечит более правильный и управляемый подход. Этот метод более декларативный и позволяет избежать неопределенных состояний в будущем, когда вы будете вносить изменения в проект или добавлять новые зависимости.