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

相关文章
|
1月前
|
编译器 Shell Linux
Makefile(3)进阶
Makefile(3)进阶
30 0
|
1月前
|
Shell Linux C++
Makefile编译实战
Makefile编译实战
64 0
|
8月前
|
C语言
Makefile教程(Makefile的结构)
Makefile教程(Makefile的结构)
49 0
|
8月前
|
Java 编译器 Linux
Makefile教程(入门介绍)
Makefile教程(入门介绍)
84 0
|
1月前
Makefile(1)入门
Makefile(1)入门
29 0
|
6月前
|
Shell
Makefile学习2
Makefile学习2
|
6月前
|
编译器 Shell Linux
Makefile学习1
Makefile学习1
|
7月前
|
Shell
如何使用makefile
如何使用makefile
|
Shell vr&ar C语言
makefile知识再整理(超详细)
makefile知识再整理(超详细)
190 0
makefile知识再整理(超详细)
|
Java Linux 程序员
玩转Makefile | 一文入门Makefile
玩转Makefile | 一文入门Makefile
219 0
玩转Makefile | 一文入门Makefile