Makefile 描述了整个工程的编译、链接规则。当源码文件比较多的时候就不适合通过输入 gcc 命令来编译,Makefile 文件描述了编译哪些源码文件、如何编译,每次需要编译工程时只需要使用这个文件就行了。
(1)make命令本质上是一个shell命令,和ls、cd这些命令没有什么区别,只是make命令会根据当前目录下的Makefile来进行工作,而Makefile文件又有自身的编写要求。
- xjh@ubuntu:~/iot/tmp$ which make
- /usr/bin/make
- xjh@ubuntu:~/iot/tmp$ man 1 make #执行时会弹出make命令的用法
(2)Makefile的规则中,命令行必须以Tab键开始,不能用几个空格表示。
(3)Makefile中只能使用#进行注释,不能使用//进行注释,而且只能一行一行地注释。
(4)在命令行中输入“make”,make 命令会在当前目录下查找是否存在 Makefile 文件。博文Makefile中的文件搜索路径(VPATH和vpath)说的是Makefile如何找到那些待编译的源文件。
我们可以直接在shell窗口中输入很多命令来完成某个需求,但是每次用到相同需求时都需要重新输入这些命令,效率比较低下,为此我们可以把这些命令记录在一个文档中,然后去执行这个文档中的命令,这样就能一步操作完成。记录着这些命令的文档,就是shell脚本。换言之,shell脚本就是一些命令的集合,它是一个纯文本文件。
(1)shell 脚本中,命令是从上到下,从左到右,一行行、一句句地开始执行的。
(2)shell 脚本提供数组、循环、条件判断等功能。
(3)shell 脚本扩展名为 .sh,但其实扩展名并不影响脚本执行,见名知意就好。
(4)shell 脚本第一行一般为“#!/bin/bash”,这表示使用bash这个shell程序。
(5)执行shell脚本的方法,其中一种是“./xxx.sh”(首先要给xxx.sh添加可执行权限),另外一种方法是“bash xxx.sh”,或者“. xxx.sh”,或者“source xxx.sh”。它们的区别见https://www.cdsy.xyz/computer/programme/shell/230325/cd41939.html。
1、在Makefile中可以调用shell命令。
(1)比如Makefile规则中的命令行就是由shell命令组成的。
- x210_sd_config : unconfig
- @$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
- @echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
(2)比如xxx = $(shell紧接着的是shell代码)。
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- usr_num = $(shell who | wc -l)
-
- all:
- @echo "用户数目是${usr_num}"
-
- xjh@ubuntu:~/iot/tmp$ make
- 用户数目是2
- xjh@ubuntu:~/iot/tmp$
(3)执行 Makefile 规则中的命令时,通过创建一个进程来执行一行的内容,即每一行命令对应着一个进程,不同命令行对应着不同进程,因此不同命令行之间的变量不能传递。有时候一行的命令很长,为了确保一行的shell命令都在同一个进程中执行,我们需要在末尾添加“\”。另外,一行的命令中,不同的命令语句之间用分号进行连接。
- MPC8360ERDK_33_config \
- MPC8360ERDK_66_config \
- MPC8360ERDK_config: unconfig
- @mkdir -p $(obj)include
- @if [ "$(findstring _33_,$@)" ] ; then \
- $(XECHO) -n "... CLKIN 33MHz " ; \
- echo "#define CONFIG_CLKIN_33MHZ" >>$(obj)include/config.h ;\
- fi ;
- @$(MKCONFIG) -a MPC8360ERDK ppc mpc83xx mpc8360erdk freescale
2、在shell中通配符是“*”,在Makefile中通配符是“ %”。
3、在shell中不允许 “=” 号两边有空格,在Makefile中允许变量赋值时,“=” 号两边有空格。
4、在shell中,$() 放命令,${} 放变量;在Makefile中,$() 和 ${} 都能引用变量,如果不加()或者{},则$会与$后面字符串的第一个字符组合,比如下面代码的$VAR,其实是${V}AR,因为变量V没有定义,则${V}为空。
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- VAR = value
-
- all:
- @echo $VAR
- @echo ${VAR}
- @echo $(VAR)
-
- xjh@ubuntu:~/iot/tmp$ make
- AR
- value
- value
- xjh@ubuntu:~/iot/tmp$
5、如果在Makefile中定义了一个变量,而Makefile中所调用的shell命令也定义了一个同名的变量,在使用变量的时候,如何区分它是引用shell的变量还是Makefiel中的变量呢?Makefile规定,如果在Makfile中引用shell变量,那么该shell变量前应该添加两个美元符号。
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- SUBDIR = src example
- subdir = xxx
-
- all:
- @for subdir in $(SUBDIR);\
- do\ # $$subdir表示引用shell中的变量subdir
- echo "building " $$subdir $${subdir};\ #$$(subdir)实测不行
- echo ${subdir} $(subdir);\ #${subdir}表示引用Makefile中的变量subdir
- done
-
- xjh@ubuntu:~/iot/tmp$ make
- building src src
- xxx xxx
- building example example
- xxx xxx
- xjh@ubuntu:~/iot/tmp$
-
-
6、在Makefile中,shell命令需要放在规则的命令中,直接放在规则之外是不允许的。
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- VAR = Hello
- echo ${VAR} #这一条shell命令直接放在规则之外是不允许的
-
- all:
- echo ${VAR}
- xjh@ubuntu:~/iot/tmp$ make
- Makefile:2: *** missing separator. Stop.
- xjh@ubuntu:~/iot/tmp$
如果想把shell命令放在规则之外,需要使用 xxx = $(shellshell命令列表)的形式。
- xjh@ubuntu:~/iot/tmp$ cat Makefile
- VAR = Hello
- print_string=$(shell echo ${VAR})
-
- all:
- @echo ${VAR}
- @echo ${print_string}
-
- xjh@ubuntu:~/iot/tmp$ make
- Hello
- Hello
- xjh@ubuntu:~/iot/tmp$
7、shell中执行命令时没有回显,执行Makefile中规则的命令行时,如果命令行之前没有@符号,则一般会先打印出要执行的命令,然后执行命令。