我仍在学习 makefile,但我在理解如何正确使用它方面遇到了问题。
我有一个简单的项目,结构如下:
我想使用我的
Makefile
编译子目录 Mcal
和 Ecual
中的所有源文件,而不需要为使用的每个 .c
文件重复代码。
我当前的 Makefile 代码是:
#Directories
#Files
FILENAME = blink
#Flags
MCU = atmega16a
WFLAGS = -Wall -Wextra -Werror -Wshadow
#Toolchain
COMPILE = avr-gcc -mmcu=$(MCU) -Os $(WFLAGS)
LINK = avr-gcc -mmcu=$(MCU)
# Linking
$(FILENAME): main.o Led.o Dio.o
$(LINK) $^ -o $(FILENAME)
#Compiling
main.o: main.c
$(COMPILE) -c $^ -o $@
Led.o: Ecual/Led/Led.c
$(COMPILE) -c $^ -o $@
Dio.o: Mcal/Dio/Dio.c
$(COMPILE) -c $^ -o $@
我使用了这个,但只有当所有源文件都位于根文件中时它才有效:
#Compiling
%.o: %.c
$(COMPILE) -c $^ -o $@
在基于 UNIX 的系统上,您可以使用
shell
指令和 UNIX find
命令递归查找目录或任何子目录中的所有 .c 文件,然后将结果放入名为 $(SRCS)
的变量中。我不确定 Windows 机器上的等效项是什么,因为我没有,但你可以通过 Google 找到它。定义如下:
SRCS := $(shell find . -name "*.c")
然后,将
$(OBJS)
定义为与 $(SRCS)
相同,但将每个 .c
替换为 .o
。这个定义应该是这样的:
OBJS := $(SRCS:.c=.o)
最后,您可以创建一个依赖于
$(OBJS)
的规则,并使用通用 %.o: %.c
规则将所有 C 文件编译为目标文件,就像之前所做的那样。每当规则依赖于 .o
文件并且不存在其他规则时,就会调用此通用规则。最终产品如下:
#Directories
#Files
FILENAME = blink
#Flags
MCU = atmega16a
WFLAGS = -Wall -Wextra -Werror -Wshadow
#Toolchain
COMPILE = avr-gcc -mmcu=$(MCU) -Os $(WFLAGS)
LINK = avr-gcc -mmcu=$(MCU)
SRCS := $(shell find . -name "*.c")
OBJS := $(SRCS:.c=.o)
# Linking
$(FILENAME): $(OBJS)
$(LINK) $^ -o $(FILENAME)
#Compiling
%.o: %.c
$(COMPILE) -c $^ -o $@