1、 什么是 make 工具?
make 工具是编译辅助工具。解决使用命令编译工程非常繁琐的问题。
调用这个命令工具:在 win 上编程使用 ide ,有图形界面,有相应的按钮,比如说 build 或者run 来编译。其实 make 这个编译辅助工具使用也是非常简单的,在控制台上直接输入命令,它就会自动调用 make 工具。
2、 怎么调用 make 工具?
直接在控制台输入 make 命令,就会调用 make 工具。
在这个目录下输入 make ,然后报错了,因为没有告诉 make 这个工具它按照什么规则来编
译程序。
3、 什么是 makefile ?
Makefile 就是描述了整个工程编译连接等规则的文件。在终端输入完 make 命令之后,调用 make工具,make 就会在当前目录按照文件名就会找 makefile 文件,Makefile 的命名必须是 makefile 或Makefile ,m 大写小写都是可以的。输入命令报的这个错就找到原因了,是因为在当前目录下是没有 makefile 这个文件的,新建一个 Makefile 文件,然后在当前目录下输入 make 命令,输入完 make 命令,调用 make 工具,make 工具就会在当前目录下找到 makefile 这个文件,这里又报错了,因为创建的 makefile 文件,虽然找到了但是里面是空的,因为没有包含任何的规则。如下图所示。
然后输入 make ,在当前这个目录下,我就成功的生成 hello 这个可执行文件,执行一下,可以看到成
功输出了,到这里我们的编译流程就已经讲完了,成功的利用 makefile 文件和 make 工具,把 hello.c
编译成了 hello 可执行文件。
vi /etc/vim/vimrc (rc 结尾的一般为配置文件)
在最后一行输入 set tabstop=4,保存后退出即可。便发现 vim 打开后的缩进变成四个空格了。
4、 Makefile 基本语法
语法格式:
目标:依赖
(tab)命令
举例:目标: all
依赖:空
命令: gcc hello.c -o hello
上面也可写成:
目标:all 和 hello.c
依赖:hello.o 和 hello.c
命令: gcc hello.c -o hello 和 gcc -c hello.c
因为 all 依赖 hello.o 文件,所以要先执行 gcc -c hello.c 得到 hello.o 文件,然后才可以执行 gcc hello.c -o hello 。所以输入 make 命令后执行顺序如下图所示。
在编译的时候,我们可以使用 make 目标来编译,如果不指定目标的话,默认执行的是第一个目标所对应的规则。也就是说 make 和 make all 是一样的。如上面的例子。使用 make 目标的方法来编译。修改 makefile 代码如下图所示:
然后输入命令 make clean 就可以直接执行 rm -rf *.o hello 命令。如下图所示。
在当前目录下不能和 makefile 目标名一样的文件。比如在当前目录下创建一个名为 clean的文件,然后执行 make clean 命令就会报错。如下图所示。
为了解决这个问题,makefile 引入了一个新的概念,叫做伪目标,使用伪目标来声明 clean 就可以
避免与当前目录下的同名文件发生冲突。
伪目标格式;.PHONY:目标
可以把上面的代码修改成如下图所示:
然后在执行 make clean 命令。尽管当前目录下有 clean 同名文件, make clean 命令也可以执行
成功。如下图所示。
5、 Makefile 变量和变量赋值
变量可以对许多地方使用,比如目标,依赖。或者命令。
变量的赋值可以使用: = ?= := +=
变量的使用:通过$() 来完成变量的引用。
使用 := 来赋值
使用 := 来给变量赋值,是立刻赋值,在执行 var:=aaa 的同时变量值已经被确定了,所以最后打印
为 aaabbb,而不是 cccbbb,如下图所示。
使用=来赋值
使用 =来赋值,是延迟赋值,使用他来赋值是 makefile 里面最后被指定的值。因为最后给变量 var1
赋值为 ccc ,所以最后打印为 cccbbb ,而不是 aaabbb ,如下图所示:
使用 ?=来赋值
使用?= 来赋值,如果 var1 变量前面没有被赋值,那么就给它赋值为 ccc ,如果前面已经赋值了,就适应前面的值,所以,打印为 aaabbb ,而不是 cccbbb ,如下图所示。
然后注释掉第一行代码,makefile 中的注释为 #
在运行就会打印 cccbbb ,因为前面没有给 var1 变量赋值。如下图所示
使用+=来赋值
使用+=赋值是追加赋值,在前面定义好的字符串里面在添加进去新的字符串,所以运行会打
印 aaa bbbccc 。不过中间会有空格,如下图所示:
使用+=也类似于我们这样赋值,如下图所示:
如果赋值很长,我们也可以使用换行符/,如下图所示
6、 自动化变量
自动化变量就是不用定义且会随着上下程序的不同而发生变化的变量叫做自动化变量。三个最常用的自动化变量:$@: 表示所有目标
$< :表示第一个依赖文件,如果依赖模式是%,表示一系列文件。(%为通配符,类似 linux 上的 *)
$^ :表示所有依赖。
在了解这三个自动化变量之前,先来写一个程序:
main.c
hello.c
hello.h
Makefile
使用这个 makefile 虽然也可以成功编译,但是,一旦编译的文件多了,还这样来编写 makefile就会变得非常复杂。简化这个 makefile 。
简化一:用变量表示依赖文件
后面如果在增加依赖文件的话,直接在变量 var 后面增加就可以了。
简化二:
使用通配符 % ,和自动化变量 $< 、$@ 代替依赖和目标,简化完如下图所示:
简化三:
使用自动化变量 $^ 表示所有文件依赖的列表,简化完如下图所示:
7、wildcard 函数
格式: $ (wildcard PATTENR)
功能: 展开指定的目录
在 /home/topeet/test 目录有一个 a.c 的 c 文件和一个 test 的文件夹,在/home/topeet/test/test 件夹下有一个 b.c 的文件。在当前目录下创建的 makefile 里面写下如下代码,echo 前面加了@ 符号,echo 这个命令就不显示:执行结果:
得到了 ./a.c 和 ./test/b.c ,所以 wildcard 函数会把指定的 ./ 和 ./test/ 目录下的 c 文件展
开。
8、 notdir 函数
格式: $ (notdir $ (var) )
功能:去掉路径。
在上面的 makefile 中加上以下代码,因为上面的例子得到的结果是 ./a.c 和 ./test/b.c 是有路
径的,可以直接使用这个变量。执行结果:
因为 notdir 函数可以去掉路径,所以 /a.c 和 ./test/b.c 去掉路径就得到了 a.c 和 b.c
9、 dir 函数
格式: $(dir
功能:取出目录,这里的目录指的是最后一个反斜杠/ 之前的部分,如果没有反斜杠/就返回当前。
在上面的例子中加入以下代码
因为 var2 的值为 ./a.c 和 ./test/b.c ,所以取出目录就是 ./ 和 ./test ,如下图所示:
10、 patsubst 函数
格式: $(patsubst 原文件,目标文件,文件列表)
功能:替换文件后缀
在上面的例子中加入以下代码
这个函数会把 var1 变量的 a.c 和 b.c 的 .c 后缀替换为 .o ,
但是这个替换并不会改变当前目录下的后缀名。可以用这个函数来替换后缀名,进行其他的操作,这个函数都是会配合其他函数来用的。替换可以使用这个函数,也可以使用 $(var:a=b) 这个格式来替换,var 代表要替换的文件的名字,a 是原文件,b 是目标文件。改一下上面的代码,
运行结果如下:
11、 foreach 函数
格式:$(
foreach ,,
功能:把参数中的单词逐一取出放到参数所指定的变量中,然后再执行
因为 var2 变量的值为 ./ 和 ./test ,所以先把 ./ 取出来放在 n 变量,然后再执行 wildcard 函数取
出 ./test 和 ./test 下面的 c 文件的路径。所以执行结果如下图所示: