当前位置: 首页> 教育> 就业 > 全国好的视频制作_传奇手游盒子app平台排行榜_百度推广运营工作是什么_网络营销八大目标是什么

全国好的视频制作_传奇手游盒子app平台排行榜_百度推广运营工作是什么_网络营销八大目标是什么

时间:2025/7/13 14:36:59来源:https://blog.csdn.net/Small_entreprene/article/details/144635350 浏览次数:1次
全国好的视频制作_传奇手游盒子app平台排行榜_百度推广运营工作是什么_网络营销八大目标是什么

简单样例演示

我们一句话来概括make/Makefile是什么:

  • make是一个命令;
  • Makefile是一个文件。(我们的makefile首字母既可以大写也可以小写:M/m)

我们来快速的见见Makefile,make:

注意:

  • 图中的Tab键开头是语法,不可以弄错了;
  • Makefile是当前目录下的文件。

Makefile的基本概念

依赖关系与依赖方法

code:code1:这个为依赖关系

        gcc -o code code1:这个为依赖方法

我们的依赖对象可以有许多个,这个称为依赖列表:code1 code2 code3........ 

依赖关系不可以出现问题,依赖方法更不能无法无天🤕

完善Makefile

对于上述代码,我们不仅仅想要编译我们的代码,也想对代码进行清理,我们可以打开Makefile

在Makefile中,.PHONY是一个特殊的伪目标,用来声明那些不对应实际文件的目标。这样,即使存在同名的文件,make命令也会执行这些伪目标后面的命令。这对于定义清理(clean)任务特别有用,因为清理任务通常需要删除文件,而这些文件可能与Makefile中的目标同名。 

# 声明.PHONY,使得clean成为一个伪目标
.PHONY: clean# 定义clean目标,用于清理工作
clean:rm -f code

运用.PHONY,我们可以理解为.PHONY是Makefile当中的一个修饰符:

.PHONY后面修饰的东西,我们将其称为伪目标

我们就可以使用该目标:clean进行依赖关系,依赖关系是可以为空的,后面的代码就是clean的依赖方法。

在这个Makefile中,我们定义了一个名为clean的伪目标,它执行rm -f code命令来删除名为code的文件。这里有几个要点:

  1. .PHONY: clean:这行声明了clean是一个伪目标,这样即使存在名为code的文件,make clean命令也会执行。

  2. clean::这行定义了clean目标的开始。

  3. rm -f code:这是实际执行删除文件code的命令。-f选项表示强制删除,并且不提示。

要使用这个Makefile,只需在命令行中输入make clean,就会执行定义在clean目标下的命令,删除code文件:

lfz@hcss-ecs-ff0f:~/lesson/mk$ make clean
rm -f code

如果想要在清理时删除更多的文件或目录,可以在rm -f code命令后面添加更多的删除命令

我们的到此,Makefile的内容是:

code:code.cgcc -o code code.c
.PHONY:clear
clear:rm -f code

我们使用make就会执行gcc操作,我们make clean就会执行rm操作,我们对于该Makefile的内容不需要make code就可以进行gcc操作,我们将Makefile的相关代码位置交换,我们发现:

make命令在处理Makefile时,会从上到下扫描文件,并默认执行第一个目标(目标规则)。如果你不指定任何目标,make就会执行Makefile中的第一个目标。如果你指定了特定的目标,make就会执行与该目标相关联的命令。

.PHONY:

我们来谈谈.PHONY: clean,如果我们将该代码在Makefile中删除,我们发现其实再make clean也是可以进行很好的使用的,那我们为什么在Makefile中还要写.PHONY: clean呢?

即使在Makefile中删除了.PHONY: clean这一行,make clean命令仍然可以工作,这是因为make默认会认为所有的目标都是文件名,如果这些文件不存在,make就会尝试创建它们。但是,对于clean这样的目标,我们并不希望make去创建一个名为clean的文件,就像make code,而是希望执行一系列清理命令。

使用.PHONY: clean有几个好处:

  1. 明确意图:它明确告诉makeclean不是一个实际的文件,而是一个需要执行的命令序列。

  2. 避免冲突如果没有.PHONY声明,而当前目录下恰好有一个名为clean的文件,make就会认为make clean的目的是更新这个文件,而不是执行清理操作。

  3. 防止误操作如果没有.PHONY声明,make在执行make clean时会检查clean文件是否存在以及是否比依赖文件新。如果clean文件存在且较新,make会认为目标是最新的,不会执行任何操作,这可能会导致清理命令不被执行

  4. 依赖关系在复杂的Makefile中,clean目标可能依赖于其他目标。使用.PHONY可以确保即使这些依赖目标是文件,make clean也会被执行。

  5. 跨目录构建在多目录构建系统中,.PHONY目标可以确保在任何子目录中调用make clean都会执行清理操作,而不受文件系统结构的影响。

总的来说,虽然在某些情况下不声明.PHONY也能工作,但为了代码的清晰性和可维护性,以及避免潜在的错误,最好还是在Makefile中声明.PHONY: clean

make的时间戳:

make 通过比较文件的时间戳来判断文件是否需要重新编译。如果源文件的时间戳没有更新(例如,通过某些工具修改文件内容但没有改变时间戳),make 就可能认为文件没有变化,从而不进行重新编译:

在Linux下,一切皆文件,文件=内容+属性,所以我们修改文件无非就是修改内容或者修改属性,要们就全部修改,我们可以使用:

stat 文件名

stat 命令是一个用于显示文件或文件系统状态信息的命令行工具

查看文件导致的Access比较特殊,我们待会儿再谈。

我们在此基础上,通过vim打开code.c文件进行修改,再次stat发现:

我们通过vim指令达到了对code.c文件内容的修改,Modify时间戳变化是应该的,但是我们好像也没有刻意的去修改文件属性,为什么Change的时间戳也会发生变化?

因为我们修改文件的同实,我是在code.c文件中加入了一行printf代码,这样文件的size(大小)就发生了变化,所以在我们修改文件内容的时候,文件内容和文件属性被同时修改了,导致了Modify和Change的时间戳发生了变化,其实Modify的时间戳也是文件的属性,所以通过文件内容的修改,他们两者是同时变化的。

我们只想修改文件属性,可以使用权限的变化:chmod:

现在我们来说说Access时间戳:atime=Access Time的缩写

访问时间戳(atime)记录了文件最后一次被读取的时间。虽然它在某些情况下有用,但每次文件被访问时,操作系统都需要更新atime,这会导致额外的磁盘I/O开销,降低系统性能,尤其是在高并发的文件访问场景下,会增加磁盘I/O压力,影响文件访问效率。此外,维护atime还会占用一定的存储空间和管理成本。为了提高性能,可以考虑禁用atime更新或使用relatime等优化策略,以减少atime更新的频率和开销。(因为我们其实对文件的访问是占比很大的,相对于文件内容,属性的修改)
 (为了提高性能,文件系统可能会对 atime 的更新进行优化,但这种优化通常不会影响 ctime 的更新机制,因为时间戳也是属性)

我们make对新老文件编译的更新本质就是根据Modfiy Time时间戳

注意:是更新,不是再生 

之前学习过:touch是用来新建文件的,但是touch的核心作用是更改文件对应的时间,我们可以使用man touch进行查看:

我们可以:

touch 当前目录下存在的文件##默认更新该文件的所有时间戳
touch 当前目录下不存在的文件##新建一个文件

我们上图的时间轴也是PHONT的原理:也就是.PHONY修饰的伪目标为什么总能被执行:

我们用.PHONY修饰code:

.PHONY:code

那么,我们的make(make code)就可以总被执行了:

 但是对于形成我们自己的可执行程序,我们一般不要使用.PHONY修饰, 因为我们就是要使用时间对比来区分新旧,使编译过的代码不要再编译了,节省编译时间。

Makefile的推导规则:

Makefile在翻译的时候,可以理解为Makefile在自己的内部会维护一个类似于栈的东西,Makefile文件会被make命令从上到下进行扫描,扫描到第一个依赖关系(要形成code,需要依赖code.o)但是当前的code.o根本就不存在,这时候将code.o所依赖的方法先入栈,然后跳过该依赖方法找到下一个要形成的目标code.o,需要依赖code.s.........(不存在的依赖对象的依赖方法先无脑入栈)

一直到依赖对象是code.c是存在的,那么就开始依次出栈并执行:

所以我们的Makefile的推导方法就是根据依赖链,不存在的先将其依赖方法进行入栈,最后出栈实现,将整体的依赖链进行链接,上面这么麻烦的去写是为了理解其推导逻辑,正常我们是就刚刚开始写的那样就ok了的。

变量版的Makefile:

变量版的 Makefile 是指在 Makefile 中使用变量来简化和优化构建规则。使用变量可以提高 Makefile 的可读性、可维护性和可复用性。以下是关于变量版 Makefile 的详细介绍:

  • 定义变量:在 Makefile 中,可以使用 = 或 := 来定义变量。例如:
    CC = gcc
    CFLAGS = -g -Wall
    这里定义了两个变量:CC 表示编译器,CFLAGS 表示编译选项。
  • 使用变量:在规则中,可以通过 $(变量名) 或 ${变量名} 的方式来引用变量。例如:
    all: hello
    hello: hello.o$(CC) $(CFLAGS) -o hello hello.o
    hello.o: hello.c$(CC) $(CFLAGS) -c hello.c
    在这里,$(CC) 和 $(CFLAGS) 分别被替换为 gcc 和 -g -Wall,从而简化了命令的书写。

作用:

  • 提高可读性:使用变量可以将复杂的命令分解为多个部分,使 Makefile 更加清晰易懂。例如,将编译器和编译选项分别定义为变量,可以避免在命令中重复书写复杂的参数。
  • 提高可维护性:当需要修改编译器或编译选项时,只需在变量定义处进行修改,而不需要逐个修改每个命令。这大大减少了维护的工作量,降低了出错的可能性。
  • 提高可复用性:通过定义通用的变量,可以在多个规则中复用相同的设置。例如,可以在不同的目标文件中使用相同的编译器和编译选项,避免了重复定义。

以下是一个简单的变量版 Makefile 示例:

BIN:=code
CC:=gcc
SRC:=code.c
FLAGS:=-o
RM=rm -f$(BIN):$(SRC)@$(CC) $(FLAGS) $@ $^@echo "linking $^ to $@".PHONY:clean
clean:@$(RM) $(BIN)@echo "remove... $(BIN)".PHONY:test
test:@echo $(BIN)@echo $(CC)@echo $(SRC)@echo $(FLAGS)@echo $(RM)

%.o: %.cMakefile 中的一种模式规则(pattern rule),用于定义如何从 .c 文件生成对应的 .o 文件。这种规则使用了通配符 % 来表示文件名的模式匹配:

BIN:=code
CC:=gcc
SRC:=code.c
OBJ:=code.o
LFLAGS:=-o
FLAGS:=-c
RM=rm -f$(BIN):$(OBJ)$(CC) $(LFLAGS) $@ $^
%.o:%.c$(CC) $(FLAGS) $<

这种模式规则可以应用于多个文件,而不需要为每个文件单独编写规则。例如,如果在当前目录下有 main.c 和 utils.c,那么 make 会自动应用这条规则来生成 main.o 和 utils.o。(如果有1000个.c文件,我们就不需要自己手写了)

当然,我们当前的SRC只是code.c这一个文件,为了传入更多.c文件,我们有以下两种方法:

$(shell ...)

我们可以使用shell来达到对外部命令使用后文件的提取,也可以达到(如果有1000个.c文件,我们就不需要自己手写了):

SRC:=$(shell ls *.c)

SRC:=$(shell ls *.c)Makefile 中的一行代码,用于将当前目录下所有 .c 文件的列表赋值给变量 SRC。

$(shell ...):这是一个 make 函数,用于执行 shell 命令并捕获其输出。shell 函数将命令的输出作为字符串返回。

还可以使用:

$(wildcard ...)

Makefile 中,wildcard 函数用于展开通配符模式,并返回匹配该模式的所有文件名的列表。它是一个内置的 make 函数,通常用于动态地获取文件列表,而不需要执行外部的 shell 命令。

SRC := $(wildcard *.c)

使用 wildcard 函数来获取当前所在目录的所有 .c 文件的列表

接下来对于OBJ这.o文件的变量,我们该这么获取.o文件呢?准确来说是需要所有源文件的.o,这样的话,就会根据所有的.c生成.o时,就可以自动化的进行编译,就可以将所有的OBJ链接成可执行程序,我们可以使用:

OBJ:=$(SRC:.c=.o)

我们结合以上代码:

BIN:=code
CC:=gcc
SRC:=$(shell ls *.c)
OBJ:=$(SRC:.c=.o)
LFLAGS:=-o
FLAGS:=-c
RM=rm -f$(BIN):$(OBJ)$(CC) $(LFLAGS) $@ $^
%.o:%.c$(CC) $(FLAGS) $<.PHONY:clean
clean:$(RM) $(BIN) $(OBJ).PHONY:test
test:@echo $(SRC)@echo $(OBJ)

 测试:

常用的预定义变量: 

  • $@:表示规则中的目标文件名。例如,在规则 hello: hello.o 中,$@ 表示 hello
  • $<:表示规则中的第一个依赖文件名。例如,在规则 hello.o world.o: hello.c world.c  中,$< 表示 hello.c。(喂完后接着下一个world.c)(%.o:%.c )
  • $^:表示规则中的所有依赖文件名,以空格分隔。例如,在规则 hello: hello.o another.o 中,$^ 表示 hello.o another.o
  • $?:表示规则中所有比目标文件新的依赖文件名,以空格分隔。例如,在规则 hello: hello.o another.o 中,如果 another.o 比 hello 新,则 $? 表示 another.o

我们可以在依赖方法前添加@符号,可以达到回显隐藏的功能,可以是Makefile的执行输入更加的简洁和美观。(隐藏的是命令

总之,变量版的 Makefile 是一种更加高效和灵活的构建方式,能够帮助开发者更好地管理项目的构建过程。

关键字:全国好的视频制作_传奇手游盒子app平台排行榜_百度推广运营工作是什么_网络营销八大目标是什么

版权声明:

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

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

责任编辑: