我仍在学习Makefile,但我在理解如何正确使用它时遇到了问题.

我有一个简单的项目, struct 如下:

enter image description here

我想使用我的Makefile来编译子目录McalEcual中的所有源文件,而不需要为使用的每个.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指令和UNIXfind命令递归地查找目录或任何子目录中的所有.c文件,然后将结果放入名为$(SRCS)的变量中.我不确定Windows电脑上有什么对应的,因为我没有,但你可以在谷歌上找到.其定义如下所示:

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 $@

C++相关问答推荐

编译SDL 2时缺少SDL_ttf

ZED for SDL上的C语言服务器

如何将字符串传递给函数并返回在C中更改的相同字符串?

Clang:如何强制运行时错误的崩溃/异常由于-fsanitize=undefined

Ruby C Api处理异常

自定义变参数函数的C预处置宏和警告 suppress ?

Vcpkg的配置文件

在编写代码时,Clion比vscode有更多的问题指示器

如何用C语言为CLI应用程序编写按键检测系统?

将数组插入数组

使用%f格式说明符打印整数值

将回调/基于事件的C API转换为非回调API

链表删除 node 错误

Fprintf正在写入多个 struct 成员,并且数据过剩

赋值两侧的后置增量,字符指针

可以对两种 struct 类型中的任何一种进行操作的C函数

struct 中的qsort,但排序后的 struct 很乱

如何在Rust中处理C的longjmp情况?

C99 的 %zu 格式说明符不起作用

窗口消息处理函数以某种方式更改了应保持不变的 int 变量的值