Makefile 静态模式——$(objects): %.o: %.c

本文详细解释了Makefile中的静态模式规则,通过实例说明如何利用简单的模式匹配来定义多目标规则,提高规则设置的效率与灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

静态模式

最近看Makefile,正常依赖没什么问题,但是遇到一些特殊的符号就有点不明白了,例如:$(objects): %.o: %.c、$<之类的。最近看了篇文章写的不错,贴出来供大家分享。

静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法:

<targets ...>: <target-pattern>: <prereq-patterns ...>
  <commands>
...

如果我们的<target-parrtern>定义成“%.o”,意思是我们的<target>集合中都是以“.o”结尾的,而如果我们的<prereq-parrterns>定义成“%.c”,意思是对<target-parrtern>所形成的目标集进行二次定义,其计算方法是,取<target-parrtern>模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。所以,我们的“目标模式”或是“依赖模式”中都应该有“%”这个字符。

没看明白没有关系,看下面的例子:

objects = foo.o bar.o
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@

上面的例子中,指明了我们的目标从$objects中获取,“%.o”表明要所有以“.o”结尾的目标,也就是“foo.o bar.o”,也就是变量$object集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是,我们的依赖目标就是“foo.c bar.c”。而命令中的“$<”和“$@”则是自动化变量,“$<”表示所有的依赖目标集(也就是“foo.c bar.c”),“$@”表示目标集(也就是“foo.o bar.o”)。于是,上面的规则展开后等价于下面的规则:

foo.o : foo.c
$(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
$(CC) -c $(CFLAGS) bar.c -o bar.o

试想,如果我们的“%.o”有几百个,那种我们只要用这种很简单的“静态模式规则”就可以写完一堆规则,实在是太有效率了。“静态模式规则”的用法很灵活,如果用得好,那会一个很强大的功能。 

.c.o:
gcc -c -o $*.o $<
.c.o:
这句话的意思就是 %.o : %.c
也就是说,所有的.o文件,依赖于对应的.c文件
比如有三个a.c b.c c.c
那么就会有 a.o b.o c.o
a.o : a.c
b.o : b.c
c.o : c.c
这是makefile依赖的一种简写方法。makefile的依赖关系有很多种写法。这是其中一种。

龚志远 gold86522 Linux Makefile编译基本模块进阶 (已允许复制粘贴) 实验总用时:00:01:29 资源中心 数据集 nav 第1关:编译静态库 400 学习内容 参考答案 记录 评论11 任务描述 相关知识 源码文件说明 编译静态库分解步骤 指定头文件目录 Makefile目标与依赖的格式 编程要求 测试说明 任务描述 在当前目录下存在两个子目录: inc 和 src , inc 下面有static_develop.h和static_entry.h, src 下面有static_develop.c、static_entry.c和main.c。 本关任务: 分别利用static_develop.c、static_entry.c和main.c生成相应的.i、.s和.o文件; 利用前面的文件生成libMakeStatic.a; 直接利用static_develop.c、static_entry.c和main.c生成MakeStatic.out。 相关知识 我们通常把一些公用函数制作成函数库,供其它程序使用。函数库分为静态库和动态库两种。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。 静态库是一堆 object 对象的集合,使用 ar 命令可以将编译产生的.o文件打包成.a静态库。 对于模块中代码文件较少的来说,通常我们可以将该模块编写为一个静态库。 源码文件说明 Test.c是函数库的源程序,其中包含公用函数 test,该函数将在屏幕上输出Make a static library!。Test.h为该函数库的头文件。Main.c为测试库文件的主程序,在主程序中调用了公用函数 test 。 /*********************************************** ****************Test.h************************** ************************************************/ #ifndef HELLO_H #define HELLO_H void test(const char *name); #endif //HELLO_H /*********************************************** ****************Test.c************************** ************************************************/ #include <stdio.h> void test(const char *name) { printf("Make %s! ", name); } /*********************************************** ****************Main.c************************** ************************************************/ #include "Test.h" int main() { hello("a static library"); return 0; } 编译静态库分解步骤 我们将静态库取名为libTest.a。使用的主要命令是 gcc 和 ar , gcc主要用来产生.i,.s和. o文件, ar 主要用来将.o文件链接成静态库。 按照背景知识中介绍的编译步骤,编译生成静态库的步骤如下: 预编译:gcc -E Main.c -o Main.i && gcc -E Test.c -o Test.i 编译:gcc -s Main.i -o Main.s && gcc-s Test.i -o Test.s 汇编:gcc -c Test.s -o Test.o && gcc -c Test.s -o Test.o 链接:ar crv libTest.a Main.o Test.o 也可以将前面三步汇总为一步: gcc Main.c Test.c -o Test.out ar crv libTest.a Test.out 指定头文件目录 在编译的过程中,编译工具会根据源文件所#include的字符串去找头文件,默认是编译器里头文件的目录。如果需要添加额外的头文件目录,需要程序员自行制定。定义规则如下: LOCALDIR = . INCLUDE += -I${LOCALDIR}/include/ ......... gcc ${INCLUDE} hello.c -O hello ......... Makefile目标与依赖的格式 目标与依赖的格式非常重要,尤其是命令前面一定要使用**TAB键补全**。 格式如下: 目标:依赖文件 【tab】命令 示例如下: Test.out : Main.c Test.c gcc $^ -o $@ helloworld.c 编程要求 在当前目录下存在两个子目录: inc 和 src , inc 下面有static_develop.h和static_entry.h, src 下面有static_develop.c、static_entry.c和main.c。 本关的编程任务是补全右侧 Makefile 脚本片段中三段Begin至End中间的语句,具体要求如下: 在第一段指定头文件目录; 在第二段完成以下功能: 分别利用static_develop.c、static_entry.c和main.c生成相应的.i、.s和.o文件; 利用前面的文件生成libMakeStatic.a; 在第三段中,直接利用static_develop.c、static_entry.c和main.c生成MakeStatic.out。 注意:需要指定头文件目录,否则编译会失败。 测试说明 测试过程: 用户补全框架内的代码,实现功能性代码; 接着根据程序的输出判断程序是否正确。 以下是测试样例: 测试输入: 预期输出: *.i file generate successful! *.s file generate successful! *.o file generate successful! LibMakeStatic.a generate successful! MakeStatic.out generate successful! 生活赋予我们一种巨大的和无限高贵的礼品,这就是青春:充满着力量,充满着期待志愿,充满着求知和斗争的志向,充满着希望信心和青春。 —— 奥斯特洛夫斯基 开始你的任务吧,祝你成功! 如果你觉得这一关的内容对你有帮助,请你在下面点赞。 说点什么 1 resize-icon 12345678910111213141516171819202122232425262728293031 ###################################### # # ###################################### #target you can change test to what you want #静态库文件名,lib*.a TARGET := libMakeStatic.a TARGET_OUT := MakeStatic.out 测试结果 测试集1 本关最大执行时间:40秒 下一关 run 评测 AI翻译 ###################################### # # ###################################### #target you can change test to what you want #静态库文件名,lib*.a TARGET := libMakeStatic.a TARGET_OUT := MakeStatic.out #compile and lib parameter #编译参数 CC := gcc -lm -lc -lz AR = ar crv LIBS := LDFLAGS := -DEEP_DEV_BLOCK -DEEP_REPAIR_RECOVERY_IMAGE LDFLAGS += -Wno-error=maybe-uninitialized -Wno-error=uninitialized -Wno-error=unused-parameter CC += $(LDFLAGS) #头文件目录变量 INCLUDE := -I. CFLAGS := -g -Wall -O3 $(DEFINES) $(INCLUDE) CXXFLAGS:= $(CFLAGS) -DHAVE_CONFIG_H #################指定头文件目录############### #####################Begin#################### ######################End##################### .PHONY : clean all all : $(TARGET) $(TARGET_OUT) $(TARGET) : ############ 注意使用TAB ############### #####################Begin#################### ######################End##################### $(TARGET_OUT) : ############ 注意使用TAB ############### #####################Begin#################### ######################End##################### clean : rm -fr *.o *.i *.s rm -fr $(TARGET) $(TARGET_OUT)
最新发布
06-07
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值