您的位置:首页 > 运维架构 > Linux

学习Linux(29)MakeFile

2020-07-20 18:15 113 查看

make工具:它可以帮助我们找出项目里面修改变更过的文件,并根据依赖关系,找出受修改影响的其他相关文件,然后对这些文件按照规则进行单独的编译,这样一来,就能避免重新编译项目的所有的文件。
Makefile文件:上面提到的规则、依赖关系主要是定义在这个Makefile文件中的,我们在其中合理地定义好文件的依赖关系之后,make工具就能精准地进行编译工作。

从我们上面的介绍,大家可以知道,我们管理一个项目工程,实质上就是管理项目文件间的依赖关系。 所以我们在学习和使用Makefile的时候,一定要牢牢抓住它这种面向依赖的思想, 心里一定要谨记,Makefile中所有的复杂、晦涩的语法都是更好地为解决依赖问题而存在的。 理解了它的本质目的之后,我们以后在学习它的过程中就不用死记硬背各种语法了, 只要想想这个本质目的,你会觉得一切都是那么地顺理成章。

Makefile 三要素:
目标、命令、依赖

三要素的关系:
目标:依赖的文件或是其他目标

命令1
命令2
。。。。

示例代码

默认执行目标,以第一个目标为准

指定执行目标

未修改过的目标不会再执行

伪目标命令:指定伪目标

main.c

mp3.c

直接使用GCC编译程序并执行

使用Makefile来管理项目

为了避免每次修改任何一个文件,都要全部编译,对Makefile进行改造。

然并卯,我以为修改了main.c后在执行make,会自动只编译main.c,没想到压根就不执行编译了。因为main.o是存在的,就不会在编译了,也就是说要手动去编译main.c,在来执行make命令。。。我要你有何用!

好的,由于少写了依赖的.c文件,所以没有达到理想效果。
学到后面才发现,这样才是理想状态,只会编译修改过的.c文件。

系统变量(常用)

自定义变量
= 延迟赋值:只有系统调用它的时候才会赋值、

:= 立即赋值:在引用之前就已经有确定的值了。

?= 空赋值:只有当这个变量为空的时候才会赋值

+= 追加赋值:并不会改变原有的值,会在后面追加内容

自动化变量
符号 意义
$@ 匹配目标文件
% 与@类似,但$%仅匹配“库”类型的目标文件
$< 依赖中的第一个目标文件
$^ 所有的依赖目标,如果依赖中有重复的,只保留一份
$+ 所有的依赖目标,即使依赖中有重复的也原样保留
$? 所有比目标要新的依赖目标

$< 指向第一个依赖文件

$^ 指向全部的依赖文件

$@ 指向目标

用变量对Makefile进行改造

模式匹配
% 匹配任意多个非空字符

使用%通配符对Makefile进行改造

默认规则
.o文件默认使用.c文件来编译

条件分支
ifeq(arg1, arg2)
分支1
else
分支2
endif

使用gcc编译工具链

使用arm-linux-gnueabihf-gcc编译工具链

使用函数
https://www.gnu.org/manual/manual.html Makefile官网手册

patsubst函数功能为模式字符串替换。它的格式如下:
1 $(patsubst 匹配规则, 替换规则, 输入的字符串)
当输入的字符串符合匹配规则,那么使用替换规则来替换字符串,当匹配规则中有“%”号时,替换规 则也可以例程“%”号来提取“%”匹配的内容加入到最后替换的字符串中。有点抽象,请直接阅读以下示例:
#执行如下函数
$(patsubst %.c, build_dir/%.o, hello_main.c )#函数的输出为:
build_dir/hello_main.o

#执行如下函数$(patsubst %.c, build_dir/%.o, hello_main.xxx )#由于hello_main.xxx不符合匹配规则"%.c",所以函数没有输出
第一个函数调用中,由于“hello_main.c”符合“%.c”的匹配规则(%在Makefile中的类似于*通配符),而且“%”从“hello_main.c”中提取出了“hello_main”字符,把这部分内容放到替换规则“build_dir/%.o”的“%”号中,所以最终的输出为”build_di r/hello_main.o”。
第二个函数调用中,由于由于“hello_main.xxx”不符合“%.c”的匹配规则,“.xxx”与“.c”对不上,所以不会进行替换,函数直接返回空的内容。

7.8.1.1. notdir函数
notdir函数用于去除文件路径中的目录部分。它的格式如下:
KaTeX parse error: Expected 'EOF', got '#' at position 114: …保留 文件名。使用范例如下: #̲以下是范例(notdir ./sources/hello_func.c)
#上面的函数执行后会把路径中的“./sources/”部分去掉,输出为: hello_func.c

7.8.1.2. wildcard函数
wildcard函数用于获取文件列表,并使用空格分隔开。它的格式如下:
(wildcard匹配规则)例如函数调用“(wildcard 匹配规则) 例如函数调用“(wildcard匹配规则)例如函数调用“(wildcard *.c)”,函数执行后会把当前目录的所 有c文件列出。假设我们在上图中的Makefile目录下执行该函数,使用范例如下:

#在sources目录下有hello_func.c、hello_main.c、test.c文件#执行如下函数
$(wildcard sources/*.c)#函数的输出为:
sources/hello_func.c sources/hello_main.c sources/test.c

foreach函数
它是一个循环函数。类似于Linux的shell中的for语句。
$(foreach VAR,LIST,TEXT)

大改造,将Makefile打造成能通用的版本。

完美,老实说:刚看到视频上这么改造,我凌乱了,捋了半小时才消化。

Makefile解决头文件依赖
先取出头文件路径,然后在编译的时候添加头文件(gcc -I +“头文件”)

这样在编译的时候就不会提示警告了,会连头文件一起编译

在修改了头文件后,重新执行make命令,并没有重新编译

修改Makefile添加所有的.h文件,并在编译的时候也参与。

这样就能达到理想中,每次头文件修改,所有相关的文件都重新编译。

初探Makefile文件,头晕眼花,博大精深啊

Hankin
2020.07.15

注释。
Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“ #”字符,这个就
像 C/C++中的“// ”一样。如果你要在你的 Makefile 中使用“#”字符,可以用反斜框进行
转义,如:“# ”。
最后,还值得一提的是,在 Makefile 中的命令,必须要以 [Tab] 键开始。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: