Makefile文件 | 进阶指南

简介: Makefile文件 | 进阶指南

1.Makefile文件的语法


      咕咕咕.......鸽王终于回来啦,最近由于自己的事情比较多所以拖更了两周还请大家见谅。本篇文章还将继续学习Makefile文件的编写,之前的文章小伙伴们还没来得及看的话,请点击此处Makefile文件 | 编写指南开始愉快的学习


1.1 注释


     #符号在Makefile文件中表示注释,如下面的代码所示:


[njust@njust Make_Tutorials]$ cat Makefile 
demo:demo.c
 gcc -g demo.c -o demo
# 此处是注释    
.PHONY:clean
clean:
 rm *.o
result.txt:source.txt
 cp source.txt result.txt
source.txt:
 echo "This is a demo!" > source.txt
.ONESHELL:
var:
 # export foo=bar;echo "foo=[$$foo]"
 # export foo=bar;\
 # echo "foo=[$$foo]"
 export foo=bar;
 export "foo=[$$foo]"



1.2 回声echo


正常情况下,make命令会先打印出每条命令,然后再执行命令,这个过程叫做回声。如下面的代码,执行make命令后会得到如下结果:


[njust@njust Make_Tutorials]$ ls
a.o  b.o  Makefile
[njust@njust Make_Tutorials]$ make test
# delete all object files. 
rm *.o
[njust@njust Make_Tutorials]$ ls
Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
test:
 # delete all object files. 
 rm *.o
 export "foo=[$$foo]"


如果想关闭回声功能,可以在每条命令前加上@,这样执行make test构建命令时就不会打印出每条命令了,直接得到每条命令的执行结果。由于make在构建过程中,需要知道当前已执行到Makefile文件中哪条命令,因此通常只需要在注释和echo命令(类似于打印功能)前加上@关闭回声功能


[njust@njust Make_Tutorials]$ ls
a.o  b.o  Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
test:
 @# delete all object files. 
 @rm *.o
[njust@njust Make_Tutorials]$ make test
[njust@njust Make_Tutorials]$ ls
Makefile


1.3 正则表达式


正则表达式用来匹配一组符合特定条件的文件名,Makefile文件中的正则表达式用法与其他编程语言中的类似,基本的通配符有*、[...]、?等,具体使用如下所示:


[njust@njust Make_Tutorials]$ ls
a.o  b.o  Makefile
[njust@njust Make_Tutorials]$ make test
# delete all object files. 
rm *.o
[njust@njust Make_Tutorials]$ ls
Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
test:
 # delete all object files. 
 rm *.o

Make命令还允许对文件名,进行类似正则运算的匹配。主要使用的匹配符是%。例如,将当前目录下的两个源文件foo.c、bar.c编译为对应的目标文件,可以简单用如下的一条语句就行:


[njust@njust Make_Tutorials]$ ls
bar.c  foo.c  Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
%.o:%.c  
 @echo source file has been converted to object file. 
[njust@njust Make_Tutorials]$ make foo.o
source file has been converted to object file.
[njust@njust Make_Tutorials]$ make bar.o
source file has been converted to object file.
[njust@njust Make_Tutorials]$ make bbb.o
make: *** 没有规则可以创建目标“bbb.o”。 停止。
Makefile


值得注意的是:%.o:%.c可以等同于bar.o:bar.c、foo.o:foo.c,但绝不等于bbb.o:bar.c/foo.c,否则会出现上面的构建错误。


1.4 变量和赋值符


   Makefile文件中也允许使用等号、自定义变量。具体如下例所示:


[njust@njust Make_Tutorials]$ ls
bar.c  foo.c  Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
txt = Hello CurryCoder
test:
 @echo $(txt)
%.o:%.c
 @echo source file has been converted to object file. 
[njust@njust Make_Tutorials]$ make test
Hello CurryCoder


在上面的代码段中,我们发现变量txt等于Hello CurryCoder。使用变量txt时,需要将变量放在$()中。此外,调用shell中的变量时,需要注意在美元符号前再加一个美元符号,这表示Make构建命令会对美元符号进行转义。如下所示:


[njust@njust Make_Tutorials]$ ls
bar.c  foo.c  Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
txt = Hello CurryCoder
test:
 @echo $(txt)
 @echo $$HOME
%.o:%.c
 @echo source file has been converted to object file. 
[njust@njust Make_Tutorials]$ make test
Hello CurryCoder
/home/njust

此外,一个变量的值可以赋值给另一个变量,如v1 = $(v2)。值得思考的是,变量v1的值是静态扩展(类似于静态语言类型如C语言)的,还是动态扩展(类似于动态语言类型如Python)的?为了解决这个问题,Makefile文件中提供了四种赋值运算符,如下所示:


VARIABLE = value
# 在执行时扩展,允许递归扩展
VARIABLE := value
# 在定义时扩展
VARIABLE ?= value
# 只有在该变量为空时才设置值
VARIABLE += value
# 将值追加到变量的尾端


1.5 内置变量


Make构建命令提供了一系列内置变量,如$(CC)表示当前使用的编译器;$(MAKE)表示当前使用Make工具,设置这两个内置变量的目的主要是考虑到跨平台的兼容性问题。更多内置变量请见参考资料[2]


[njust@njust Make_Tutorials]$ ls
bar.c  foo.c  Makefile
[njust@njust Make_Tutorials]$ cat Makefile 
txt = Hello CurryCoder
test:
 @echo $(txt)
 @echo $$HOME
demo:
 $(CC) -o demo bar.c
%.o:%.c
 @echo source file has been converted to object file. 
[njust@njust Make_Tutorials]$ make demo
cc -o demo bar.c
[njust@njust Make_Tutorials]$ ls
bar.c  demo  foo.c  Makefile


1.6 自动变量


Make构建命令还提供了一些自动变量,它们的值与当前构建规则有关,主要有如下几个。更多自动变量请见参考资料[3]


(1).$@:表示当前目标,例如make demo时,$@就表示demo;

(2).$<:表示第一个依赖条件,例如test:source1.txt source2.txt,则$<就表示source1.txt;

(3).$?:表示比目标的时间戳更加新的所有依赖条件,之间以空格分开。例如,t:p1 p2,其中p2的时间戳比t新,则$?表示p2;

(4).$^:表示所有的依赖条件,它们之间以空格分开。例如,t:p1 p2,则$?表示p1 p2;
       (5).$*:表示匹配符%所匹配的部分,例如,%匹配file.o中的file,则$*表示file;


1.7 判断和循环


Makefile文件中使用Bash语法,实现判断和循环。下面的代码判断当前编译器是否为gcc,然后指定不同的库文件。


ifeq ($(CC),gcc)
  libs=$(libs_for_gcc)
else
  libs=$(normal_libs)
endif


Makefile文件中的循环示例代码如下所示:


LIST = one two three
all:
    for i in $(LIST); do \
        echo $$i; \
    done
# 等同于
all:
    for i in one two three; do \
        echo $i; \
    done


1.8 函数


Makefile文件中也可以使用函数,具体的格式如下所示。更多内置函数请见参考资料[4]


$(function arguments)
# 或者
${function arguments}


2.参考资料


[1].http://www.ruanyifeng.com/blog/2015/02/make.html

[2].https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html

[3].https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html

[4].https://www.gnu.org/software/make/manual/html_node/Functions.html

相关文章
|
缓存 安全 Java
为什么全局变量可能成为多线程环境中的安全隐患
为什么全局变量可能成为多线程环境中的安全隐患
|
机器学习/深度学习 人工智能 自然语言处理
一文尽览 | 开放世界目标检测的近期工作及简析!(基于Captioning/CLIP/伪标签/Prompt)(上)
人类通过自然监督,即探索视觉世界和倾听他人描述情况,学会了毫不费力地识别和定位物体。我们人类对视觉模式的终身学习,并将其与口语词汇联系起来,从而形成了丰富的视觉和语义词汇,不仅可以用于检测物体,还可以用于其他任务,如描述物体和推理其属性和可见性。人类的这种学习模式为我们实现开放世界的目标检测提供了一个可以学习的角度。
一文尽览 | 开放世界目标检测的近期工作及简析!(基于Captioning/CLIP/伪标签/Prompt)(上)
|
存储 算法 网络安全
二进制加密PHP Webshell原理及简单实现
二进制加密PHP Webshell原理及简单实现
311 8
|
设计模式 算法 搜索推荐
C语言设计模式之道:高效实现和优化技巧
C语言设计模式之道:高效实现和优化技巧
395 0
新版本ARM交叉编译器官网下载地址(arm-none-eabi、arm-none-linux-gnueabihf、aarch64-none-elf、aarch64-none-linux-gnu)
新版本ARM交叉编译器官网下载地址(arm-none-eabi、arm-none-linux-gnueabihf、aarch64-none-elf、aarch64-none-linux-gnu)
5540 0
新版本ARM交叉编译器官网下载地址(arm-none-eabi、arm-none-linux-gnueabihf、aarch64-none-elf、aarch64-none-linux-gnu)
|
Shell
makefile 自定义,预定义函数
makefile 自定义,预定义函数
244 0
如何从 Debian 系统中的 DEB 包中提取文件?
如何从 Debian 系统中的 DEB 包中提取文件?
614 0
如何从 Debian 系统中的 DEB 包中提取文件?
|
Kubernetes 网络协议 Linux
容器管理平台Rancher解析
Rancher是What?一个开源的企业级容器管理平台。通过Rancher,企业再也不必自己使用一系列的开源软件去从头搭建容器服务平台。Rancher提供了在生产环境中使用的管理Docker和Kubernetes的全栈化容器部署与管理平台。
768 0
|
存储 编译器 C语言
重定义/自定义printf到串口输出实现的三种方法(cubeide)
重定义/自定义printf到串口输出实现的三种方法(cubeide)
1864 0
|
持续交付
《必致(BizDevOps)白皮书2022》——03必致(BizDevOps)实践体系——3.1 BizDevOps实践的总体介绍
《必致(BizDevOps)白皮书2022》——03必致(BizDevOps)实践体系——3.1 BizDevOps实践的总体介绍
349 0