当前位置: 首页> 科技> 互联网 > 微信公众号模板去哪找_濮阳网络运输证_微信营销平台有哪些_竞价托管sem服务

微信公众号模板去哪找_濮阳网络运输证_微信营销平台有哪些_竞价托管sem服务

时间:2025/8/14 5:31:23来源:https://blog.csdn.net/qq_45226456/article/details/147561885 浏览次数:0次
微信公众号模板去哪找_濮阳网络运输证_微信营销平台有哪些_竞价托管sem服务

系列文章目录

Make学习一:make初探

Make学习二:makefile组成要素

文章目录

  • 系列文章目录
  • 前言
  • 默认目标
  • 规则语法
  • order-only prerequisites
  • 文件名中的通配符
  • 伪目标 Phony Targets
  • 没有 Prerequisites 和 recipe
  • 内建特殊目标名
  • 一个目标多条规则或多个目标共享 prerequisites
  • 自动生成依赖
  • 总结


前言

前文 Make学习二:makefile组成要素 中提到,Makefile 组成中的重要成员就是显示规则。本文重点在编写规则上。

显示规则的格式如下:

target ... : prerequisites ...recipe...

引用前面 Make学习一:make初探 中的话,简单来说,一条规则就像一道菜。如果说 target 是我们的西红柿炒鸡蛋,那 prerequisites 就是西红柿炒鸡蛋的依赖,或者说输入,简单点就是西红柿和鸡蛋。而 recipe 就是西红柿炒鸡蛋的菜谱,也就是要做成这道菜,需要什么步骤,每一步要怎么做。 实际上,recipe 确实是菜谱的意思,prerequisites 意为先决条件。

默认目标

每一条规则在 Makefile 中的 书写顺序一般不影响功能,但会决定默认目标(default goal),即如果你运行 make 没有指定目标,默认会构建的那个目标。

默认目标的规则是:取第一个 Makefile 里第一条规则的第一个 target。

因此,通常会把整个程序编译的规则写在 Makefile 最前面,这个规则的目标经常叫做 all。类似,make 的约定。

如下示例,直接运行 make 输出 Hello, world!:

all: hellohello:@echo "Hello, world!"

规则语法

一条规则的基本写法是:

target ... : prerequisites ...recipe...

targets 一般是文件名,可以用空格分隔多个目标。也可以用 通配符(wildcards)。
配方(recipe)行必须以 Tab 开头(这一点非常重要!)。 也可以通过设置 .RECIPEPREFIX 变量来改成别的符号

一条规则可以有:

  • 多个依赖(prerequisites);
  • 多个目标(targets);
  • 也可以没有依赖(比如 .PHONY 规则);
  • 或者没有 recipe(表示目标是伪目标或不需要命令)。

多个依赖示例:

edit: main.o kbd.o command.o display.ogcc -o edit main.o kbd.o command.o display.o

多个目标示例:

clean temp:rm -f *.o temp

这里 clean 和 temp 是 两个目标,共享同一个配方。

长行可以用 \ 续行,但 recipe 不需要续行,必须每行一个 Tab。

规则的作用:如果目标不存在或目标的修改时间早于任何一个依赖,则按照 recipe 去更新它们

order-only prerequisites

有时你会想要某个依赖在目标之前被构建,但不希望因为这个依赖的更新导致目标被重建。这就需要用 order-only prerequisite(仅顺序依赖)。

简单一句话概括:该依赖必须存在,但同时它的更新不能影响到 target 的更新。那么你就需要 order-only prerequisite

写法:target : normal-prerequisites | order-only-prerequisites 使用管道符把 order-only-prerequisites 放在右边即可。

例如:我们想把当前目录下的 foo.c 和 bar.c 文件构建出来的 foo.o 和 bar.o 放在 obj 目录中。但这个目录可能一开始不存在。我们需要:先保证 obj/ 目录存在;但不要因为 obj/ 目录变化而导致目标重建。则 Makefile 的内容如下所示:

OBJDIR := obj
OBJS := $(OBJDIR)/foo.o $(OBJDIR)/bar.oall: $(OBJS)# 创建 obj/ 目录(order-only)
$(OBJDIR)/%.o : %.c | $(OBJDIR)@echo "Compiling $< to $@"@cp $< $@# 仅顺序依赖:保证 obj/ 目录存在,但不影响重建判断
$(OBJDIR):@echo "Creating directory $@"@mkdir -p $@

第一次执行 make,输出如下:

Creating directory obj
Compiling foo.c to obj/foo.o
Compiling bar.c to obj/bar.o

即便我们在 obj 目录下通过命令touch obj/temp创建文件,执行 make 依旧不会有任何更新:make: 对“all”无需做任何事。

文件名中的通配符

在 Makefile 里,一个文件名可以使用通配符(wildcard characters)来匹配多个文件。支持的通配符和 Linux shell 里的一样:* 匹配 任意长度的任意字符,? 匹配任意单个字符,[abc] 匹配括号中任意一个字符。~(波浪号)在文件名开头(单独出现或后跟 /)代表当前用户根目录。

一条规则分 target,prerequisite 和 recipe。target 和 prerequisite 中的 通配符由 make 来展开。而 recipe 中的通配符会把命令传递给 shell 由 shell 来处理。

例如:以下 Makefile 执行 make 之后会打印出所有更新之后的 .c 文件内容。$? = 依赖中比目标 print 新的文件。

print: *.c@echo $?

但变量中的通配符不会自动展开,需要使用函数 $(wildcard)。 例如:objects = *.o 中变量赋值并不会展开,objects 只是 “*.o” 字符串。

此时,当我们通过以下 Makefile 来执行 make 命令:

objects = *.ofoo : $(objects)cc -o foo $(CFLAGS) $(objects)

若当前目录下没有任何 .o 文件,则 *.o 就不会展开,则会出错:make: *** 没有规则可制作目标“*.c”,由“*.o” 需求。 停止。

为了解决这个问题,则需要在变量定义时则进行通配符展开为文件名列表。使用 wildcard 函数,格式:$(wildcard pattern...)

objects := $(wildcard *.o)
foo : $(objects)  cc -o foo $(CFLAGS) $(objects)

若当前目录下没有任何 .o 文件,则 *.o 仍旧会展开,只是变量 objects 为空字符串。报错:cc -o foo cc: fatal error: no input files

伪目标 Phony Targets

所谓 伪目标(phony target),指的是根本就不是某个实际文件名的目标,而是一个用于明确执行某个配方(recipe)的名字。

使用伪目标的两个主要原因是:避免与同名文件冲突 和 提高性能。例如,如下 Makefile 内容:

clean:rm *.o temp

上面例子中,clean 不是实际会被创建的文件。因此,每次运行 make clean 时,都会执行 rm 命令。

如果当前目录里真有一个名字叫 clean 的文件,make clean 就会误以为 clean 已是最新,不执行删除操作

使用 .PHONY: clean 后,clean 的配方 总是会执行,不会被任何文件阻止。

没有 Prerequisites 和 recipe

如果一个规则 既没有依赖(prerequisite)也没有配方(recipe),并且它的目标文件不存在,那么每次 make 运行时都会认为这个目标已经“更新”。这意味着:所有依赖于这个目标的规则,每次都会执行它们自己的配方。

这个机制常用于强制重新构建(不论文件是否真正变化)。例如以下示例:

clean: FORCErm $(objects)FORCE:

内建特殊目标名

有一些目标名称如果出现在 Makefile 中,会具有特殊的含义。这些名字通常以 . 开头。

.PHONY(伪目标声明),.PHONY 后面列出的所有目标都被认为是伪目标(phony targets)。

.SUFFIXES 目标后面列出的是用于后缀规则 suffix rules的后缀列表。可以用 .SUFFIXES: 清除所有后缀规则(这样就不会自动匹配如 .c → .o 这些规则了)。

.DEFAULT(没有匹配规则时的最后手段),如果一个目标没有任何匹配的规则(无显式也无隐式规则),就会使用 .DEFAULT 提供的配方。

.DEFAULT:@echo "No rule for $@"

等等等等

一个目标多条规则或多个目标共享 prerequisites

例如:kbd.o command.o files.o: command.h 这条 Makefile 内容中,多个目标同时依赖同一个头文件。此时可以用 $@ 来区分当前到底是哪个目标。

一个文件可以同时是多条规则的目标(target)。来自不同规则的所有依赖(prerequisites)会合并成一个总的依赖列表。只要目标比任何一个依赖旧,就会执行配方(recipe)。

例如以下 Makefile 的内容:

objects = foo.o bar.ofoo.o : defs.hbar.o : defs.h test.h$(objects) : config.h

foo.o 的依赖会合并成一个列表:config.h + defs.h

自动生成依赖

在程序的 Makefile 中,你通常需要写很多这种规则:main.o: defs.hmain.c 里用了 #include "defs.h",那么你就得写 main.o: defs.h

你写这个规则是为了让 make 知道:如果 defs.h 变了,就得重新编译 main.o。如果你的程序很大,#include 很多,每次增加或删掉头文件都得手动改 Makefile,非常麻烦,容易出错。

为了解决这个问题,现代 C 编译器可以自动帮你生成这些依赖规则。它们会扫描你的源码里的 #include 语句,通常使用 -M 选项来实现。例如:cc -M main.c 它会输出:main.o : main.c defs.h 所以你不再需要自己写这些规则,编译器会帮你搞定。

总结

完结撒花!!

关键字:微信公众号模板去哪找_濮阳网络运输证_微信营销平台有哪些_竞价托管sem服务

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: