如何通过Automake与Autotools实现一键make flash全量构建
我正在学习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.am代码:
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 # Add a custom target for flashing flash: atmega Atmega-lib/libatmega328p.a @echo "Flashing the ATmega328P..." avrdude -F -V -p m328p -c arduino -P /dev/ttyACM0 -b 115200 -U flash:w:$(OUTPUT_HEX):i # Rule to create the hex file using avr-objcopy $(OUTPUT_HEX): atmega avr-objcopy -O ihex -R .eeprom $< $(OUTPUT_HEX)
我尝试修改flash规则为以下代码后可正常运行,想问这个解法是否正确:
# Add a custom target for flashing flash: $(MAKE) @echo "Flashing the ATmega328P..." avrdude -F -V -p m328p -c arduino -P /dev/ttyACM0 -b 115200 -U flash:w:$(OUTPUT_HEX):i
这个解法是有效的,但不是最符合Automake规范的写法,详细说明如下:
原规则报错原因
原flash规则依赖atmega和Atmega-lib/libatmega328p.a,但Automake处理子目录依赖时,不会自动为单个静态库文件生成递归构建规则。直接运行make flash时,Make找不到构建Atmega-lib/libatmega328p.a的明确规则,因此报错。而先执行make时,Automake生成的默认规则会递归构建所有子目录的目标,静态库提前生成,后续make flash自然能正常执行。
修改后的规则为什么能工作
修改后的flash规则通过执行$(MAKE)(等价于make)触发了Automake的默认全量构建流程,会自动递归构建Atmega-lib子目录的静态库,同时生成atmega可执行文件和对应的hex文件,所有依赖满足后再执行烧录命令,因此可以正常运行。
更规范的写法
虽然你的方法可行,但更符合Automake规范的做法是让flash依赖标准的all目标,并标记为PHONY目标(避免和同名文件冲突):
.PHONY: flash flash: all @echo "Flashing the ATmega328P..." avrdude -F -V -p m328p -c arduino -P /dev/ttyACM0 -b 115200 -U flash:w:$(OUTPUT_HEX):i
这样做的好处:
all是Automake的标准目标,会自动处理所有子目录的递归构建,逻辑更清晰- 标记
flash为PHONY,确保每次执行make flash都会触发构建和烧录,不会因存在同名文件导致Make跳过执行
另外补充:原规则中flash依赖Atmega-lib/libatmega328p.a是多余的,因为atmega已经通过atmega_LDADD依赖了该静态库,构建atmega时会自动确保静态库已生成。
内容的提问来源于stack exchange,提问作者Liwinux

