makefile语法规则
makefile正则表达式
makefile正则表达式makefile是一种常用的工具,可以用于自动化构建和管理项目。
在makefile中,正则表达式是一个强大的工具,可以帮助我们更方便地匹配和处理文本内容。
makefile中常用的正则表达式包括:1. ^(起始符):匹配字符串的开头。
2. $(结束符):匹配字符串的结尾。
3. .(点号):匹配除了换行符外的任意一个字符。
4. *(星号):匹配前面的字符出现0个或多个。
5. +(加号):匹配前面的字符出现1个或多个。
6. ?(问号):匹配前面的字符出现0个或1个。
7. [ ](中括号):匹配中括号中任意一个字符。
8. [^ ](中括号取反):匹配不在中括号中的任意一个字符。
9. ( )(圆括号):将括号中的内容视为一个整体,可以和其他正则表达式一起使用。
除了这些常用的正则表达式外,还有一些特殊的符号和语法可以帮助我们更精确地匹配文本内容,比如:1. (反斜杠):转义符,可以将特殊字符转义为普通字符。
2. |(竖线):或运算符,可以匹配多个表达式中的一个。
3. { }(花括号):重复次数符号,可以指定一个字符或表达式的重复次数。
在使用正则表达式时,我们需要注意一些事项,比如:1. 正则表达式是区分大小写的。
2. 正则表达式中的空格和换行符也会被匹配。
3. 正则表达式可能会匹配到我们不需要的内容,因此需要通过进一步筛选和处理来达到我们的目的。
总之,正则表达式在makefile中的应用非常广泛,可以帮助我们更方便地编写自动化构建和管理脚本。
熟练掌握正则表达式的使用方法,可以极大地提高我们的工作效率。
makefile后缀规则
makefile后缀规则在Makefile中,后缀规则(Suffix Rules)用于指定文件的依赖关系和生成规则。
它可以帮助我们避免重复编写相似的规则,提高Makefile的可读性和可维护性。
后缀规则的一般语法如下:```<target-pattern>: <stem-patterns> | <suffixes><commands>```其中:- `<target-pattern>`是目标文件的模式,通常使用`%`来表示一个或多个字符的通配符。
- `<stem-patterns>`是关联目标文件的模式,通常也使用`%`来表示相同的通配符。
它用于指定目标文件与依赖文件的对应关系。
- `<suffixes>`是一组文件后缀,用于表示输入文件的后缀。
- `<commands>`是生成目标文件的命令。
例如,假设我们有一组C源文件(.c文件),我们可以使用后缀规则来指定如何将它们编译为目标文件(.o文件):```makefile# 后缀规则%.o: %.cgcc -c $< -o $@```在上面的例子中,`%.o: %.c`表示目标文件的模式是以`.o`为后缀的文件,而依赖文件的模式是以`.c`为后缀的文件。
`$<`和`$@`分别表示第一个依赖文件和目标文件。
通过这个后缀规则,我们可以将所有的`.c`文件自动编译为对应的`.o`文件。
例如,当我们运行`make foo.o`时,Make会自动查找`foo.c`文件并执行对应的命令。
需要注意的是,后缀规则在GNU Make 4.0版本之后已经被淘汰,推荐使用模式规则(Pattern Rules)来代替。
模式规则更灵活且更易读,可读性更好。
因此,在编写新的Makefile时,建议使用模式规则来代替后缀规则。
Makefile 语法分析
Makefile 语法分析第一部分VERSION = 2# 给变量VERSION赋值PATCHLEVEL = 6# 给变量PATCHLEVEL赋值SUBLEVEL = 22# 给变量SUBLEVEL赋值EXTRAVERSION = .6# 给变量EXTRAVERSION赋值NAME = Holy Dancing Manatees, Batman!# 给变量NAME赋值# *DOCUMENTATION*# To see a list of typical targets execute "make help"# More info can be located in ./README# Comments in this file are targeted only to the developer, do not# expect to learn how to build the kernel reading this file.# Do not:# o use make's built-in rules and variables# (this increases performance and avoid hard-to-debug behavour);# o print "Entering directory ...";MAKEFLAGS += -rR --no-print-directory# 操作符“+=”的作用是给变量(“+=”前面的MAKEFLAGS)追加值。
# 如果变量(“+=”前面的MAKEFLAGS)之前没有定义过,那么,“+=”会自动变成“=”;# 如果前面有变量(“+=”前面的MAKEFLAGS)定义,那么“+=”会继承于前次操作的赋值符;# 如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符# 在执行make时的命令行选项参数被通过变量“MAKEFLAGS”传递给子目录下的make程序。
makefile编写规则
makefile编写规则⼀、makefile 规则:⼀般开头都是 Tab ,不能空格, include 前⾯不能是 Tab; 1、如果没编译过,将所有的(.c)⽂件编译并且链接; 2、如果有其中的(.c)⽂件改变,编译并链接改变的⽂件; 3、如果(.h)⽂件被修改,编译引⽤相应的(.c)⽂件, 链接; 4、在随意修改时间的情况下,会导致编译过程中⽣成的(.o 中间⽂件)与可执⾏⽂件时间不⼀致,此时会编译相应的⽂件,并链接,最终编译成可执⾏⽂件;⼆、第⼀版 makefile: 例如有2个 .h ⽂件(utils.h, player.h, actor.h)和 3个 .c ⽂件( main.c, player.c, actor.c)需要编译链接:/*****main.c*********/#include "utils.h"#include "player.h"void main() {// do something}/*******player.c**********/#include "utils.h"#include "actor.h"bool create_player() {// do something}/****actor.c************/#include "utils.h"bool create_actor() {// do something}/********* makefile *****************/test : main.o actor.occ -o test main.o actor.omain.o : main.c utils.h player.h actor.hcc -c main.cpalyer.o: player.c player.h actor.h utils.hcc -c player.cactor.o: actor.h utils.hcc -c actor.cclean:rm test ain.o player.o actor.o 优点:可毒性很强,思路清晰明了; 缺点:⿇烦,重复的依赖过多,当需要编译⼤量⽂件时容易出错;第⼆版:利⽤ makefile 的变量;/********* makefile *****************/OBJ = main.o actor.o // 跟第⼀版⽐较,唯⼀的区别在这test : $(OBJ) // 这⼉cc -o test $(OBJ) // 这⼉main.o : main.c utils.h player.h actor.hcc -c main.cpalyer.o: player.c player.h actor.h utils.hcc -c player.cactor.o: actor.h utils.hcc -c actor.c .PHONY : clean // 伪⽬标,避免:如果当前⽬录下存在 clean rm 指令不执⾏clean:-rm test $(OBJ) // 前⾯的(-)表⽰,执⾏过程中不 care 出错;第三版:利⽤ GUN make 的⾃动推导规则 当 make 看到(.o )⽂件,他会⾃动把(.c)⽂件加上依赖关系,包括执⾏的语句(cc -c xx.c);/********* makefile *****************/OBJ = main.o actor.o // 跟第⼀版⽐较,唯⼀的区别在这test : $(OBJ) // 这⼉cc -o test $(OBJ) // 这⼉main.o : utils.h player.h actor.hpalyer.o: player.h actor.h utils.hactor.o: actor.h utils.h .PHONY : clean // 伪⽬标,避免:如果当前⽬录下存在 clean rm 指令不执⾏clean:-rm test $(OBJ)第四版:对第三版的整理(有⼀些重复的 .h) 公共的⼀起依赖,单独的单独依赖/********* makefile *****************/OBJ = main.o actor.o // 跟第⼀版⽐较,唯⼀的区别在这test : $(OBJ) // 这⼉cc -o test $(OBJ) // 这⼉$(OBJ) : utils.h actor.omain.o player.o .PHONY : clean // 伪⽬标,避免:如果当前⽬录下存在 clean rm 指令不执⾏clean:-rm test $(OBJ)优点:简洁缺点:不好理解以上的makefike⽂件的基本写法;或许你也发现了,如果有⼏百个源⽂件咋整呢,光是⽬录就要晕死,下⾯就是针对这种情况来说⼀下⼤型⼯程 makefile 的编写设计⼆、⼤型项⽬makefile编写: Makefile 同样也有像 c / c++ 类似的include功能; 例如我们有⼀堆 a.mk , b.mk以及 foo.make和⼀个变量 $(bar),其包含了 e.mk,f.mk, 那么 include foo.make *.mk $(bar) ------- 等价-------》 include foo.make a.mk b.mk e.mk f.mk。
makefile文件语法
makefile文件语法Makefile是一种用于自动化构建过程的工具,它使用一种特定的语法来定义构建规则和依赖关系。
下面是一些Makefile的基本语法规则:1. 目标(Target):目标是指要构建的程序或文件。
它通常以冒号(:)开头,后面跟着一个或多个依赖项(dependencies)。
```makefiletarget: dependenciescommands```2. 依赖项(Dependencies):依赖项是指要构建目标所必需的文件或目标。
在Makefile中,依赖项以空格分隔。
3. 命令(Commands):命令是指在构建目标时执行的命令行指令。
这些命令可以是编译、链接或其他任何必要的操作。
4. 变量(Variables):Makefile允许使用变量来存储值,以便在构建过程中重复使用。
变量以符号开头,后面跟着变量名。
```makefileVAR = value```5. 模式规则(Pattern Rules):模式规则允许根据文件模式匹配来构建目标。
它们使用通配符来匹配文件名,并在匹配的文件上执行相应的命令。
```makefiletargets : patterncommands```6. 条件语句(Conditionals):Makefile支持条件语句,可以根据条件执行不同的命令或规则。
条件使用ifdef、ifndef、ifeq等关键字定义。
7. 注释(Comments):Makefile使用井号()作为注释标记,任何在该符号之后的内容都会被视为注释,并被忽略。
8. 自动变量(Automatic Variables):Makefile提供了一些自动变量,可以在命令中使用,以获取有关目标、依赖项或文件名的信息。
例如,$表示当前目标,$<表示第一个依赖项等。
这些是Makefile的一些基本语法规则,但还有更多高级特性和用法,可以参考Make工具的文档或相关教程进行深入学习。
Makefile
MakefileMake的基本规则:Target [属性] 分隔符 [依赖文件] [;命令行 ]{Tab 命令行}注:命令行间可以加入任意多个空行,但空行也要以tab开头。
Cat –v -t -e Makefile会使Makefile文件中tab以^]显示,行尾以$显示。
注:命令过长,用\来连接多行成一行。
注释以#开头,如果#要用作字符符号,―#‖。
分隔符:::目标有多个规则。
哪条规则中的依赖文件比目标新,执行哪条规则。
如果多条规则的依赖文件都比目标新,多条规则都执行。
由于后面的规则可能覆盖前面规则的执行结构,所以规则顺序不同,执行结构也不同。
:^把本规则依赖文件和目标文件已有的依赖文件合起来,生成目标新的依赖文件列表。
:-清除目标已有依赖文件,把本规则依赖文件作为目标依赖文件列表。
:!对每个更新过的依赖文件都执行一次命令菜单。
:|内部规则专用。
如:file.o :file.cfile.o :^ filef.c现依赖文件为file.c filef.cfile.o :- filef.c现依赖文件为 filef.c令行属性:- 若本命令的执行错误,忽略掉,继续向下执行。
(不加该标志,make会停止)+ 始终执行本命令,即使make参数使用了-n-q-t。
(前提是本规则中依赖文件新与目标文件,命令行需要执行)@ 本命令行不在标准输出显示。
Target属性:指定多个目标文件属性:属性属性…… :目标目标……规则中指定单个目标属性:目标属性:[依赖文件] ……·IGNORE 类似与命令行属性-·SILENT 类似与命令行属性@·PRECIOUS 保留中间文件·LIBRARY 目标是一个库。
如果make发现目标是lib(member)或lib((entry))形式,会自动给名为lib的目标加上该属性。
·LIBRARYM 目标是库的一个成员。
如果make发现目标是lib(member)形式,会自动给lib目标加上·LIBRARY,被member目标加上·LIBRARYM。
makefile中if then写法
makefile中if then写法如何在Makefile 中使用if-then 写法Makefile 是一种软件构建工具,广泛用于管理和构建软件项目。
它使用一系列规则和命令来指导构建过程。
其中,条件语句if-then 是Makefile 中常用的控制语句之一。
在本文中,我们将逐步介绍如何在Makefile 中使用if-then 写法,以及它的用途和常见示例。
一、if-then 写法的基本语法在Makefile 中,if-then 语句的基本语法如下所示:ifeq (条件, 值)#条件为真时执行的命令else#条件为假时执行的命令endif在上述语法中,ifeq 是条件语句的关键字,用于判断一个条件是否为真。
条件是通过与指定的值进行比较来确定的。
若条件为真,则执行ifeq 和else 之间的命令块;若条件为假,则执行else 和endif 之间的命令块。
二、if-then 语句的使用场景if-then 语句在Makefile 中具有广泛的应用场景。
它可以用于实现以下功能:1. 根据不同的条件选择性地执行命令。
2. 根据环境变量的值选择性地执行命令。
3. 根据文件存在与否选择性地执行命令。
4. 根据命令执行结果选择性地执行不同的命令。
下面让我们逐步来看每个使用场景的示例。
三、根据不同的条件选择性地执行命令首先,我们来看一个根据不同的条件选择性地执行命令的示例。
假设我们有一个变量MODE,它的值可以是release 或debug。
根据MODE 的不同,我们可以选择性地执行不同的命令。
makefileMODE := releaseifeq ((MODE), release)# release 模式下执行的命令(info Building release version...)gcc -O3 -o myprogram main.celse# debug 模式下执行的命令(info Building debug version...)gcc -g -o myprogram main.cendif在上述示例中,(info ...) 是一个内置函数,用于在Makefile 执行过程中打印文本消息。
makefile文件语法规则
makefile文件语法规则Makefile文件的基本语法规则包括以下几点:1. 注释:以井号(#)开头的行被视为注释,不会被执行。
2. 规则:每条规则由一个目标文件和一组依赖文件组成,以及一个用于构建目标文件的命令。
规则的格式如下:Css:目标文件:依赖文件命令目标文件和依赖文件之间用冒号(:)分隔,命令部分指定了如何从依赖文件生成目标文件。
3. 变量:Makefile中可以使用变量来存储值,变量的值可以包含文本、空格、数字等。
变量名以美元符号($)开头,例如:Makefile:VAR = value命令= $VAR4. 函数:Makefile支持使用函数来执行更复杂的操作。
函数的语法如下:Scss:函数名(参数)Makefile中内置了一些常用的函数,如字符串操作函数、条件判断函数等。
也可以自定义函数。
5. 通配符:Makefile中可以使用通配符来匹配多个文件,常见的通配符有“*”和“?”。
例如,“*.c”表示匹配所有以“.c”结尾的文件,“a?b”表示匹配“ab”、“axb”、“ayb”等字符串。
6. 回声:在Makefile中,命令前面加上“@”符号可以关闭回声,即不会在执行命令时显示该命令。
例如:Makefile:@echo Hello, world!这条命令执行时不会输出“Hello, world!”的文本。
7. 模式规则:Makefile中的模式规则允许根据一组通配符匹配的文件来定义规则,格式如下:Makefile:模式:目标文件命令1命令2模式匹配的文件将按照指定的命令构建目标文件。
makefile循环语句
makefile循环语句(原创版)目录1.Makefile 简介2.Makefile 循环语句的作用3.Makefile 循环语句的语法4.Makefile 循环语句的示例5.Makefile 循环语句的注意事项正文1.Makefile 简介Makefile 是一种构建脚本,用于自动构建和编译源代码。
它最初用于 Unix 系统,但现在已经广泛应用于各种操作系统,如 Linux、macOS 等。
Makefile 可以根据源代码的变化自动重新编译目标文件,从而提高了开发效率。
2.Makefile 循环语句的作用在 Makefile 中,循环语句用于处理一系列相似的任务。
通过使用循环语句,可以避免重复编写相同的代码,使 Makefile 更加简洁和易于维护。
3.Makefile 循环语句的语法Makefile 循环语句的基本语法如下:```循环名:for 变量名 in 列表; do# 循环体内容done```其中,循环名是一个标识符,用于表示循环的开始和结束。
变量名是要迭代的变量,列表是一个包含多个元素的列表,用空格分隔。
循环体内容是循环执行的任务。
4.Makefile 循环语句的示例以下是一个 Makefile 循环语句的示例:```all:for src in src1 src2 src3; doobj := $(src).o$(CC) $(CFLAGS) -c $src -o $objdone```在这个示例中,循环名为“all”,变量名为“src”,列表为“src1 src2 src3”。
循环体内容是使用 C 编译器编译源代码文件并生成目标文件。
5.Makefile 循环语句的注意事项在使用 Makefile 循环语句时,需要注意以下几点:- 循环名应该具有唯一性,避免重复定义。
- 列表中的元素应该使用空格分隔,而不是逗号或其他分隔符。
- 在循环体内,可以使用自动变量(如$@、$%等)来表示当前迭代的变量。
makefile 中文手册 第四章 _ Makefile的规则
第四章:Makefile的规则本章我们将讨论Makefile的一个重要内容,规则。
熟悉规则对于书写Makefile至关重要。
Makefile中,规则描述了在何种情况下使用什么命令来重建一个特定的文件,此文件被称为规则“目标”(通常规则中的目标只有一个)。
规则中出目标之外的罗列的其它文件称为“目标”的依赖,而规则的命令是用来更新或者创建此规则的目标。
除了makefile的“终极目标”所在的规则以外,其它规则的顺序在makefile文件中没有意义。
“终极目标”就是当没有使用make 命令行指定具体目标时,make默认的更新的哪一个目标。
它是makefile文件中第一个规则的目标。
如果在makefile中第一个规则有多个目标的话,那么多个目标中的第一个将会被作为make的“终极目标”。
有两种情况的例外:1. 目标名以点号“.”开始的并且其后不存在斜线“/”(“./”被认为是当前目录;“../”被认为是上一级目录);2. 模式规则的目标。
当这两种目标所在的规则是Makefile的第一个规则时,它们并不会被作为“终极目标”。
“终极目标”是执行make的唯一目的,其所在的规则作为第一个被执行的规则。
而其它的规则是在完成重建“终极目标”的过程中被连带出来的。
所以这些目标所在规则在Makefile中的顺序无关紧要。
因此,我们书写的makefile的第一个规则应该就是重建整个程序或者多个程序的依赖关系和执行命令的描述。
4.1 一个例子我们来看一个规则的例子:foo.o : foo.c defs.h # module for twiddling the frobscc -c -g foo.c这是一个典型的规则。
看到这个例子,大家应该能够说出这个规则的各个部分之间的关系。
不过我们还是要把这个例子拿出来讨论。
目的是让我们更加明确地理解Makefile的规则。
本例第一行中,文件“foo.o”是规则需要重建的文件,而“foo.c”和“defs.h”是重建“foo.o”所要使用的文件。
makefile规则
makefile规则makefile规则是指在编译和链接源程序时使用的指令说明集合,它主要实现对源程序进行编译和链接操作。
makefile规则通常包括定义、变量( macro )、条件语句、文件名模式、关系性质,以及各种命令的执行。
定义是指在 makefile 中定义一些环境变量,这样可以同时供make 命令和源程序使用。
变量就是把变量名称定义为字符内容或者字符串。
条件语句是指在 makefile 中可以使用 if-then-else 语句条件判断,实现对不同平台的兼容和不同编译器的支持。
文件名模式是指在 makefile 中,可以使用文件名模式来精确针对特定文件和目录,完成不同操作。
关系性质是指 makefile 支持多个文件之间的依赖关系,即如果文件 A 依赖于文件 B,当文件 B 的内容发生变化时,系统自动执行文件 A 的操作。
makefile 还支持各种命令的执行,包括编译、链接、拷贝、安装等操作。
通过这些命令的执行,可以非常方便地把源程序编译和链接,实现最终的编译和链接结果。
通常,makefile 规则是由多个项目构成的,每一项都有一个名称,每一个项目都可以包含一些变量,关系和命令等,用于指定 make 命令的行为。
每个规则以一个制表符开头,然后是目标文件、依赖文件、变量名和命令,分别以冒号、逗号、空格和分号等符号隔开。
每个 makefile 都有一个默认的目标,如果在编译和链接时没有指定特定的目标,则 make 命令会执行默认的目标。
因此,完整的makefile 是必须设置默认目标的,才能在执行 make 命令时得到正确的结果。
Makefile使用总结
Makefile使⽤总结1. Makefile 简介Makefile 是和 make 命令⼀起配合使⽤的.很多⼤型项⽬的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项⽬中各种库和代码之间的依赖关系不知会多复杂. Makefile的组织流程的能⼒如此之强, 不仅可以⽤来编译项⽬, 还可以⽤来组织我们平时的⼀些⽇常操作. 这个需要⼤家发挥⾃⼰的想象⼒.本篇博客是基于⽽整理的, 有些删减, 追加了⼀些⽰例.⾮常感谢 gunguymadman_cu 提供如此详尽的Makefile介绍, 这正是我⼀直寻找的Makefile中⽂⽂档.1.1 Makefile 主要的 5个部分 (显⽰规则, 隐晦规则, 变量定义, ⽂件指⽰, 注释)Makefile基本格式如下:target ... : prerequisites ...command......其中,target - ⽬标⽂件, 可以是 Object File, 也可以是可执⾏⽂件prerequisites - ⽣成 target 所需要的⽂件或者⽬标command - make需要执⾏的命令 (任意的shell命令), Makefile中的命令必须以 [tab] 开头1. 显⽰规则 :: 说明如何⽣成⼀个或多个⽬标⽂件(包括⽣成的⽂件, ⽂件的依赖⽂件, ⽣成的命令)2. 隐晦规则 :: make的⾃动推导功能所执⾏的规则3. 变量定义 :: Makefile中定义的变量4. ⽂件指⽰ :: Makefile中引⽤其他Makefile; 指定Makefile中有效部分; 定义⼀个多⾏命令5. 注释 :: Makefile只有⾏注释 "#", 如果要使⽤或者输出"#"字符, 需要进⾏转义, "\#"1.2 GNU make 的⼯作⽅式1. 读⼊主Makefile (主Makefile中可以引⽤其他Makefile)2. 读⼊被include的其他Makefile3. 初始化⽂件中的变量4. 推导隐晦规则, 并分析所有规则5. 为所有的⽬标⽂件创建依赖关系链6. 根据依赖关系, 决定哪些⽬标要重新⽣成7. 执⾏⽣成命令2. Makefile 初级语法2.1 Makefile 规则2.1.1 规则语法规则主要有2部分: 依赖关系和⽣成⽬标的⽅法.语法有以下2种:target ... : prerequisites ...command...或者target ... : prerequisites ; commandcommand...*注* command太长, 可以⽤ "\" 作为换⾏符2.1.2 规则中的通配符* :: 表⽰任意⼀个或多个字符:: 表⽰任意⼀个字符[...] :: ex. [abcd] 表⽰a,b,c,d中任意⼀个字符, [^abcd]表⽰除a,b,c,d以外的字符, [0-9]表⽰ 0~9中任意⼀个数字~ :: 表⽰⽤户的home⽬录2.1.3 路径搜索当⼀个Makefile中涉及到⼤量源⽂件时(这些源⽂件和Makefile极有可能不在同⼀个⽬录中),这时, 最好将源⽂件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量VPATH就是完成这个功能的.指定了VPATH之后, 如果当前⽬录中没有找到相应⽂件或依赖的⽂件, Makefile 回到VPATH指定的路径中再去查找.. VPATH使⽤⽅法:vpath <directories> :: 当前⽬录中找不到⽂件时, 就从<directories>中搜索vpath <pattern> <directories> :: 符合<pattern>格式的⽂件, 就从<directories>中搜索vpath <pattern> :: 清除符合<pattern>格式的⽂件搜索路径vpath :: 清除所有已经设置好的⽂件路径# ⽰例1 - 当前⽬录中找不到⽂件时, 按顺序从 src⽬录 ../parent-dir⽬录中查找⽂件VPATH src:../parent-dir# ⽰例2 - .h结尾的⽂件都从 ./header ⽬录中查找VPATH %.h ./header# ⽰例3 - 清除⽰例2中设置的规则VPATH %.h# ⽰例4 - 清除所有VPATH的设置VPATH2.2 Makefile 中的变量2.2.1 变量定义 ( = or := )OBJS = programA.o programB.oOBJS-ADD = $(OBJS) programC.o# 或者OBJS := programA.o programB.oOBJS-ADD := $(OBJS) programC.o其中 = 和 := 的区别在于, := 只能使⽤前⾯定义好的变量, = 可以使⽤后⾯定义的变量测试 =# Makefile内容OBJS2 = $(OBJS1) programC.oOBJS1 = programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使⽤$ makeprogramA.o programB.o programC.o测试 :=# Makefile内容OBJS2 := $(OBJS1) programC.oOBJS1 := programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出 OBJS2 中的 $(OBJS1) 为空$ makeprogramC.o2.2.2 变量替换# Makefile内容SRCS := programA.c programB.c programC.cOBJS := $(SRCS:%.c=%.o)all:@echo "SRCS: " $(SRCS)@echo "OBJS: " $(OBJS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.cOBJS: programA.o programB.o programC.o2.2.3 变量追加值 +=# Makefile内容SRCS := programA.c programB.c programC.cSRCS += programD.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.c programD.c2.2.4 变量覆盖 override作⽤是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量语法:override <variable> = <value>override <variable> := <value>override <variable> += <value>下⾯通过⼀个例⼦体会 override 的作⽤:# Makefile内容 (没有⽤override)SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: nothing################################################## Makefile内容 (⽤override)override SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: programA.c programB.c programC.c2.2.5 ⽬标变量作⽤是使变量的作⽤域仅限于这个⽬标(target), ⽽不像之前例⼦中定义的变量, 对整个Makefile都有效.语法:<target ...> :: <variable-assignment><target ...> :: override <variable-assignment> (override作⽤参见变量覆盖的介绍)⽰例:# Makefile 内容SRCS := programA.c programB.c programC.ctarget1: TARGET1-SRCS := programD.ctarget1:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)target2:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)# bash中执⾏make$ make target1SRCS: programA.c programB.c programC.cSRCS: programD.c$ make target2 <-- target2中显⽰不了 $(TARGET1-SRCS)SRCS: programA.c programB.c programC.cSRCS:2.3 Makefile 命令前缀Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不⽤前缀.3种格式的shell命令区别如下:不⽤前缀 :: 输出执⾏的命令以及命令执⾏的结果, 出错的话停⽌执⾏前缀 @ :: 只输出命令执⾏的结果, 出错的话停⽌执⾏前缀 - :: 命令执⾏有错的话, 忽略错误, 继续执⾏⽰例:# Makefile 内容 (不⽤前缀)all:echo"没有前缀"cat this_file_not_existecho"错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 @)all:@echo "没有前缀"@cat this_file_not_exist@echo "错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ make没有前缀 <-- 只有命令执⾏的结果, 不显⽰命令本⾝cat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 -)all:-echo"没有前缀"-cat this_file_not_exist-echo"错误之后的命令" <-- 这条命令会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: [all] Error 1 (ignored)echo"错误之后的命令" <-- 出错之后的命令也会显⽰错误之后的命令 <-- 出错之后的命令也会执⾏2.4 伪⽬标伪⽬标并不是⼀个"⽬标(target)", 不像真正的⽬标那样会⽣成⼀个⽬标⽂件.典型的伪⽬标是 Makefile 中⽤来清理编译过程中中间⽂件的 clean 伪⽬标, ⼀般格式如下: .PHONY: clean <-- 这句没有也⾏, 但是最好加上clean:-rm -f *.o2.5 引⽤其他的 Makefile语法: include <filename> (filename 可以包含通配符和路径)⽰例:# Makefile 内容all:@echo "主 Makefile begin"@make other-all@echo "主 Makefile end"include ./other/Makefile# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 20K-rw-r--r-- 1 wangyubin wangyubin 125 Sep 2316:13 Makefile-rw-r--r-- 1 wangyubin wangyubin 11K Sep 2316:15 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2316:11 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile'主 Makefile end2.6 查看C⽂件的依赖关系写 Makefile 的时候, 需要确定每个⽬标的依赖关系.GNU提供⼀个机制可以查看C代码⽂件依赖那些⽂件, 这样我们在写 Makefile ⽬标的时候就不⽤打开C源码来看其依赖那些⽂件了.⽐如, 下⾯命令显⽰内核源码中 virt/kvm/kvm_main.c 中的依赖关系$ cd virt/kvm/$ gcc -MM kvm_main.ckvm_main.o: kvm_main.c iodev.h coalesced_mmio.h async_pf.h <-- 这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系2.7 make 退出码Makefile的退出码有以下3种:0 :: 表⽰成功执⾏1 :: 表⽰make命令出现了错误2 :: 使⽤了 "-q" 选项, 并且make使得⼀些⽬标不需要更新2.8 指定 Makefile,指定特定⽬标默认执⾏ make 命令时, GNU make在当前⽬录下依次搜索下⾯3个⽂件 "GNUmakefile", "makefile", "Makefile",找到对应⽂件之后, 就开始执⾏此⽂件中的第⼀个⽬标(target). 如果找不到这3个⽂件就报错.⾮默认情况下, 可以在 make 命令中指定特定的 Makefile 和特定的⽬标.⽰例:# Makefile⽂件名改为 MyMake, 内容target1:@echo "target [1] begin"@echo "target [1] end"target2:@echo "target [2] begin"@echo "target [2] end"# bash 中执⾏make$ lsMakefile$ mv Makefile MyMake$ lsMyMake$ make <-- 找不到默认的 Makefilemake: *** No targets specified and no makefile found. Stop.$ make -f MyMake <-- 指定特定的Makefiletarget [1] begintarget [1] end$ make -f MyMake target2 <-- 指定特定的⽬标(target)target [2] begintarget [2] end2.9 make 参数介绍make 的参数有很多, 可以通过 make -h 去查看, 下⾯只介绍⼏个我认为⽐较有⽤的.参数含义--debug[=<options>]输出make的调试信息, options 可以是 a, b, v-j --jobs同时运⾏的命令的个数, 也就是多线程执⾏ Makefile-r --no-builtin-rules禁⽌使⽤任何隐含规则-R --no-builtin-variabes禁⽌使⽤任何作⽤于变量上的隐含规则-B --always-make假设所有⽬标都有更新, 即强制重编译2.10 Makefile 隐含规则这⾥只列⼀个和编译C相关的.编译C时,<n>.o 的⽬标会⾃动推导为 <n>.c# Makefile 中main : main.ogcc -o main main.o#会⾃动变为:main : main.ogcc -o main main.omain.o: main.c <-- main.o 这个⽬标是隐含⽣成的gcc -c main.c2.11 隐含规则中的命令变量和命令参数变量2.11.1 命令变量, 书写Makefile可以直接写 shell时⽤这些变量.下⾯只列出⼀些C相关的变量名含义RM rm -fAR arCC ccCXX g++⽰例:# Makefile 内容all:@echo $(RM)@echo $(AR)@echo $(CC)@echo $(CXX)# bash 中执⾏make, 显⽰各个变量的值$ makerm -farccg++2.11.2 命令参数变量变量名含义ARFLAGS AR命令的参数CFLAGS C语⾔编译器的参数CXXFLAGS C++语⾔编译器的参数⽰例: 下⾯以 CFLAGS 为例演⽰# test.c 内容#include <stdio.h>int main(int argc, char *argv[]){printf ("Hello Makefile\n");return 0;}# Makefile 内容test: test.o$(CC) -o test test.o# bash 中⽤make来测试$ lltotal 24K-rw-r--r-- 1 wangyubin wangyubin 69 Sep 2317:31 Makefile-rw-r--r-- 1 wangyubin wangyubin 14K Sep 2319:51 <-- 请忽略这个⽂件-rw-r--r-- 1 wangyubin wangyubin 392 Sep 2317:31 test.c$ makecc -c -o test.o test.ccc -o test test.o <-- 这个是⾃动推导的$ rm -f test test.o$ make CFLAGS=-Wall <-- 命令中加的编译器参数⾃动追加⼊下⾯的编译中了cc -Wall -c -o test.o test.ccc -o test test.o2.12 ⾃动变量Makefile 中很多时候通过⾃动变量来简化书写, 各个⾃动变量的含义如下:⾃动变量含义$@⽬标集合$%当⽬标是函数库⽂件时, 表⽰其中的⽬标⽂件名$<第⼀个依赖⽬标. 如果依赖⽬标是多个, 逐个表⽰依赖⽬标$?⽐⽬标新的依赖⽬标的集合$^所有依赖⽬标的集合, 会去除重复的依赖⽬标$+所有依赖⽬标的集合, 不会去除重复的依赖⽬标$*这个是GNU make特有的, 其它的make不⼀定⽀持3. Makefile ⾼级语法3.1 嵌套Makefile在 Makefile 初级语法中已经提到过引⽤其它 Makefile的⽅法. 这⾥有另⼀种写法, 并且可以向引⽤的其它 Makefile 传递参数.⽰例: (不传递参数, 只是调⽤⼦⽂件夹 other 中的Makefile)# Makefile 内容all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 28K-rw-r--r-- 1 wangyubin wangyubin 104 Sep 2320:43 Makefile-rw-r--r-- 1 wangyubin wangyubin 17K Sep 2320:44 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2320:42 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end⽰例: (⽤export传递参数)# Makefile 内容export VALUE1 := export.c <-- ⽤了 export, 此变量能够传递到 ./other/Makefile 中VALUE2 := no-export.c <-- 此变量不能传递到 ./other/Makefile 中all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "VALUE1: " $(VALUE1)@echo "VALUE2: " $(VALUE2)@echo "other makefile end"# bash中执⾏make$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginVALUE1: export.c <-- VALUE1 传递成功VALUE2: <-- VALUE2 传递失败other makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end*补充* export 语法格式如下:export variable = valueexport variable := valueexport variable += value3.2 定义命令包命令包有点像是个函数, 将连续的相同的命令合成⼀条, 减少 Makefile 中的代码量, 便于以后维护.语法:define <command-name>command...endef⽰例:# Makefile 内容define run-hello-makefile@echo -n "Hello"@echo " Makefile!"@echo "这⾥可以执⾏多条 Shell 命令!"endefall:$(run-hello-makefile)# bash 中运⾏make$ makeHello Makefile!这⾥可以执⾏多条 Shell 命令!3.3 条件判断条件判断的关键字主要有 ifeq ifneq ifdef ifndef语法:<conditional-directive><text-if-true>endif# 或者<conditional-directive><text-if-true>else<text-if-false>endif⽰例: ifeq的例⼦, ifneq和ifeq的使⽤⽅法类似, 就是取反# Makefile 内容all:ifeq ("aa", "bb")@echo "equal"else@echo "not equal"endif# bash 中执⾏make$ makenot equal⽰例: ifdef的例⼦, ifndef和ifdef的使⽤⽅法类似, 就是取反# Makefile 内容SRCS := program.call:ifdef SRCS@echo $(SRCS)else@echo "no SRCS"# bash 中执⾏make$ makeprogram.c3.4 Makefile 中的函数Makefile 中⾃带了⼀些函数, 利⽤这些函数可以简化 Makefile 的编写.函数调⽤语法如下:$(<function> <arguments>)# 或者${<function> <arguments>}<function> 是函数名<arguments> 是函数参数3.4.1 字符串函数字符串替换函数: $(subst <from>,<to>,<text>)功能: 把字符串<text> 中的 <from> 替换为 <to>返回: 替换过的字符串# Makefile 内容all:@echo $(subst t,e,maktfilt) <-- 将t替换为e# bash 中执⾏make$ makemakefile模式字符串替换函数: $(patsubst <pattern>,<replacement>,<text>)功能: 查找<text>中的单词(单词以"空格", "tab", "换⾏"来分割) 是否符合 <pattern>, 符合的话, ⽤ <replacement> 替代.返回: 替换过的字符串# Makefile 内容all:@echo $(patsubst %.c,%.o,programA.c programB.c)# bash 中执⾏make$ makeprogramA.o programB.o去空格函数: $(strip <string>)功能: 去掉 <string> 字符串中开头和结尾的空字符返回: 被去掉空格的字符串值# Makefile 内容VAL := " aa bb cc "all:@echo "去除空格前: " $(VAL)@echo "去除空格后: " $(strip $(VAL))# bash 中执⾏make去除空格前: aa bb cc去除空格后: aa bb cc查找字符串函数: $(findstring <find>,<in>)功能: 在字符串 <in> 中查找 <find> 字符串返回: 如果找到, 返回 <find> 字符串, 否则返回空字符串# Makefile 内容VAL := " aa bb cc "all:@echo $(findstring aa,$(VAL))@echo $(findstring ab,$(VAL))# bash 中执⾏make$ makeaa过滤函数: $(filter <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *保留* 符合模式 <pattern> 的单词, 可以有多个模式返回: 符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.o program.a反过滤函数: $(filter-out <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *去除* 符合模式 <pattern> 的单词, 可以有多个模式返回: 不符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter-out %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.c排序函数: $(sort <list>)功能: 给字符串 <list> 中的单词排序 (升序)返回: 排序后的字符串# Makefile 内容all:@echo $(sort bac abc acb cab)# bash 中执⾏make$ makeabc acb bac cab取单词函数: $(word <n>,<text>)功能: 取字符串 <text> 中的第<n>个单词 (n从1开始)返回: <text> 中的第<n>个单词, 如果<n> ⽐ <text> 中单词个数要⼤, 则返回空字符串# Makefile 内容all:@echo $(word 1,aa bb cc dd)@echo $(word 5,aa bb cc dd)@echo $(word 4,aa bb cc dd)# bash 中执⾏make$ makeaadd取单词串函数: $(wordlist <s>,<e>,<text>)功能: 从字符串<text>中取从<s>开始到<e>的单词串. <s>和<e>是⼀个数字.返回: 从<s>到<e>的字符串# Makefile 内容all:@echo $(wordlist 1,3,aa bb cc dd)@echo $(word 5,6,aa bb cc dd)@echo $(word 2,5,aa bb cc dd)# bash 中执⾏make$ makeaa bb ccbb单词个数统计函数: $(words <text>)功能: 统计字符串 <text> 中单词的个数返回: 单词个数# Makefile 内容all:@echo $(words aa bb cc dd)@echo $(words aabbccdd)@echo $(words )# bash 中执⾏make$ make41⾸单词函数: $(firstword <text>)功能: 取字符串 <text> 中的第⼀个单词返回: 字符串 <text> 中的第⼀个单词# Makefile 内容all:@echo $(firstword aa bb cc dd)@echo $(firstword aabbccdd)@echo $(firstword )# bash 中执⾏make$ makeaaaabbccdd3.4.2 ⽂件名函数取⽬录函数: $(dir <names...>)功能: 从⽂件名序列 <names> 中取出⽬录部分返回: ⽂件名序列 <names> 中的⽬录部分# Makefile 内容all:@echo $(dir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ make/home/ ./ ../ ./取⽂件函数: $(notdir <names...>)功能: 从⽂件名序列 <names> 中取出⾮⽬录部分返回: ⽂件名序列 <names> 中的⾮⽬录部分# Makefile 内容all:@echo $(notdir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ makea.c bb.cc.cd.c取后缀函数: $(suffix <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的后缀返回: ⽂件名序列 <names> 中各个⽂件名的后缀, 没有后缀则返回空字符串# Makefile 内容all:@echo $(suffix /home/a.c ./b.o ../c.a d)# bash 中执⾏make$ make.c .o .a取前缀函数: $(basename <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的前缀返回: ⽂件名序列 <names> 中各个⽂件名的前缀, 没有前缀则返回空字符串# Makefile 内容all:@echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)# bash 中执⾏make$ make/home/a ./b ../c /home/加后缀函数: $(addsuffix <suffix>,<names...>)功能: 把后缀 <suffix> 加到 <names> 中的每个单词后⾯返回: 加过后缀的⽂件名序列# Makefile 内容all:@echo $(addsuffix .c,/home/a b ./c.o ../d.c)# bash 中执⾏make$ make/home/a.c b.c ./c.o.c ../d.c.c加前缀函数: $(addprefix <prefix>,<names...>)功能: 把前缀 <prefix> 加到 <names> 中的每个单词前⾯返回: 加过前缀的⽂件名序列# Makefile 内容all:@echo $(addprefix test_,/home/a.c b.c ./d.c)# bash 中执⾏make$ maketest_/home/a.c test_b.c test_./d.c连接函数: $(join <list1>,<list2>)功能: <list2> 中对应的单词加到 <list1> 后⾯返回: 连接后的字符串# Makefile 内容all:@echo $(join a b c d,1234)@echo $(join a b c d,12345)@echo $(join a b c d e,1234)# bash 中执⾏make$ makea1 b2 c3 d4a1 b2 c3 d4 5a1 b2 c3 d4 e3.4.3 foreach语法:$(foreach <var>,<list>,<text>)⽰例:# Makefile 内容targets := a b c dobjects := $(foreach i,$(targets),$(i).o)all:@echo $(targets)@echo $(objects)# bash 中执⾏make$ makea b c da.ob.oc.od.o3.4.4 if这⾥的if是个函数, 和前⾯的条件判断不⼀样, 前⾯的条件判断属于Makefile的关键字语法:$(if <condition>,<then-part>)$(if <condition>,<then-part>,<else-part>)⽰例:# Makefile 内容val := aobjects := $(if $(val),$(val).o,nothing)no-objects := $(if $(no-val),$(val).o,nothing)all:@echo $(objects)@echo $(no-objects)# bash 中执⾏make$ makea.onothing3.4.5 call - 创建新的参数化函数语法:$(call <expression>,<parm1>,<parm2>,<parm3>...)⽰例:# Makefile 内容log = "====debug====" $(1) "====end===="all:@echo $(call log,"正在 Make")# bash 中执⾏make$ make====debug==== 正在 Make ====end====3.4.6 origin - 判断变量的来源语法:$(origin <variable>)返回值有如下类型:类型含义undefined<variable> 没有定义过default<variable> 是个默认的定义, ⽐如 CC 变量environment<variable> 是个环境变量, 并且 make时没有使⽤ -e 参数file<variable> 定义在Makefile中command line<variable> 定义在命令⾏中override<variable> 被 override 重新定义过automatic<variable> 是⾃动化变量⽰例:# Makefile 内容val-in-file := test-fileoverride val-override := test-overrideall:@echo $(origin not-define) # not-define 没有定义@echo $(origin CC) # CC 是Makefile默认定义的变量@echo $(origin PATH) # PATH 是 bash 环境变量@echo $(origin val-in-file) # 此Makefile中定义的变量@echo $(origin val-in-cmd) # 这个变量会加在make的参数中@echo $(origin val-override) # 此Makefile中定义的override变量@echo $(origin @) # ⾃动变量, 具体前⾯的介绍# bash 中执⾏make$ make val-in-cmd=val-cmdundefineddefaultenvironmentfilecommand lineoverrideautomatic3.4.7 shell语法:$(shell <shell command>)它的作⽤就是执⾏⼀个shell命令, 并将shell命令的结果作为函数的返回.作⽤和 `<shell command>` ⼀样, ` 是反引号3.4.8 make 控制函数产⽣⼀个致命错误: $(error <text ...>)功能: 输出错误信息, 停⽌Makefile的运⾏# Makefile 内容all:$(error there is an error!)@echo "这⾥不会执⾏!"# bash 中执⾏make$ makeMakefile:2: *** there is an error!. Stop.输出警告: $(warning <text ...>)功能: 输出警告信息, Makefile继续运⾏# Makefile 内容all:$(warning there is an warning!)@echo "这⾥会执⾏!"# bash 中执⾏make$ makeMakefile:2: there is an warning!这⾥会执⾏!3.5 Makefile中⼀些GNU约定俗成的伪⽬标如果有过在Linux上, 从源码安装软件的经历的话, 就会对 make clean, make install ⽐较熟悉.像 clean, install 这些伪⽬标, ⼴为⼈知, 不⽤解释就⼤家知道是什么意思了.下⾯列举⼀些常⽤的伪⽬标, 如果在⾃⼰项⽬的Makefile合理使⽤这些伪⽬标的话, 可以让我们⾃⼰的Makefile看起来更专业, 呵呵 :)伪⽬标含义all所有⽬标的⽬标,其功能⼀般是编译所有的⽬标clean删除所有被make创建的⽂件install安装已编译好的程序,其实就是把⽬标可执⾏⽂件拷贝到指定的⽬录中去print列出改变过的源⽂件tar把源程序打包备份. 也就是⼀个tar⽂件dist创建⼀个压缩⽂件, ⼀般是把tar⽂件压成Z⽂件. 或是gz⽂件TAGS更新所有的⽬标, 以备完整地重编译使⽤check 或 test⼀般⽤来测试makefile的流程。
makefile语法规则
makefile语法规则Makefile是一种文本文件,它用来定义一组规则来指明编译软件项目所需要完成的步骤。
它也是构建、编译以及安装一个软件项目必不可少的一部分。
Makefile可以帮助开发者,其中一项重要的原因是它可以在编译软件时降低开发者的工作量,使其能够更快更轻松地解决编译软件的问题。
Makefile语法规则可以分为两类:基本语法规则和特殊语法规则。
基本语法规则涉及Makefile文件中每行需要遵守的语法,而特殊语法规则涉及到Makefile中使用的自定义变量或函数。
下面将详细介绍这两类规则。
1.本语法规则基本语法规则是Makefile文件核心的部分,其定义了文件每一行的正确格式。
下面我们将介绍几条基本语法规则:a)Makefile文件中,每行以冒号开头的一行代表一条规则,并且冒号前面必须是一个有效的标识符,比如变量名或是函数名。
b) Makefile文件中,每行以Tab键开头的一行代表一个操作,这个操作会被执行以完成一个特定的任务c)有以#开头的行都会被忽略,因为它表示一行注释,用来解释Makefile语句的内容d)Makefile文件中,变量与函数的定义必须放在Makefile文件的开头,才能在 Makefile件内部使用它们e)一行末尾需要加上一个分号,这样才能表达出每条规则被终止的意思,以避免 Makefile现错误2.特殊语法规则特殊语法规则涉及到 Makefile件中使用的自定义变量或是函数。
该规则是用来控制 Makefile件中定义的任务如何被执行。
a)量:变量是一种使用字符来代表值的方法,变量使用美元符号($)来表示。
它可以被声明在 Makefile文件的开头,也可以在Makefile件的某一行中使用。
b)数:函数是一种在 Makefile件中独立运行的代码块,它可以接受参数,并且返回一个字符串或者一组字符串。
使用函数有助于提高 Makefile件的整体性和可维护性,并且可以多次使用,以减少重复的工作。
makefile编写规则 ifeq
makefile编写规则 ifeq【实用版】目录1.Makefile 简介2.Makefile 编写规则3.ifeq 函数的作用4.ifeq 函数的语法5.ifeq 函数的实例6.结论正文1.Makefile 简介Makefile 是一种用于自动化构建和编译软件的脚本文件。
它通常包含一系列的规则,用于指定如何构建和编译源代码。
Makefile 的主要目的是为了简化和自动化构建过程,以便开发者能够更专注于编写代码。
2.Makefile 编写规则在 Makefile 中,编写规则通常遵循以下格式:```目标:依赖文件t命令```其中,目标表示要构建的文件,依赖文件表示构建目标所需的输入文件,命令表示用于构建目标的命令。
例如,要编译一个名为“main.c”的源文件,可以编写如下规则:```main.o: main.ctgcc -c main.c```3.ifeq 函数的作用ifeq 函数是 Makefile 中的一种条件函数,用于根据某个条件决定是否执行相应的命令。
它可以帮助开发者根据不同的环境或配置选择性地执行代码。
4.ifeq 函数的语法ifeq 函数的语法如下:```ifeq (条件)ttrue-casetfalse-caseelsetelse-caseendif```其中,条件是一个逻辑表达式,true-case 和 false-case 分别表示条件为真和假时执行的命令。
else-case 是可选的,用于表示条件不满足时执行的命令。
5.ifeq 函数的实例假设我们希望根据不同的操作系统选择不同的编译器选项,可以编写如下 Makefile 规则:```%.o: %.ctifeq ($(OS), Linux)ttgcc -o $@ $< -std=gnu99telsettgcc -o $@ $< -std=ansitendif```在这个例子中,我们使用 ifeq 函数根据当前操作系统($(OS))选择不同的编译器选项。
makefile编写规则 ifeq
makefile编写规则 ifeqifeq是makefile中的一个条件判断语句,用于判断变量的值是否相等。
在makefile中,ifeq语句的基本语法如下:ifeq(条件1, 条件2)条件1和条件2相等时执行的命令else条件1和条件2不相等时执行的命令endififeq语句可以用在makefile中的任何地方,用于根据条件来执行相应的命令。
在本文中,我们将重点讨论ifeq语句的用法及其在makefile 中的应用。
一、ifeq语句的基本用法ifeq语句的基本用法是用来比较两个变量的值是否相等,如果相等则执行相应的命令,否则执行另外的命令。
在makefile中,ifeq语句通常用在条件判断中,如下所示:```makefileifeq ($(VAR1), $(VAR2))echo "VAR1和VAR2相等"elseecho "VAR1和VAR2不相等"endif```上面的示例中,我们使用ifeq语句来比较变量VAR1和VAR2的值是否相等,如果相等则执行echo "VAR1和VAR2相等",否则执行echo "VAR1和VAR2不相等"。
这样我们可以根据条件来执行不同的命令,以实现makefile的灵活控制。
二、ifeq语句的扩展用法除了用来比较变量的值是否相等外,ifeq语句还可以用来比较其他条件,如下所示:```makefileifeq ($(shell uname), Linux)echo "当前系统是Linux"else ifeq ($(shell uname), Darwin)echo "当前系统是MacOS"elseecho "当前系统不是Linux也不是MacOS"endif```上面的示例中,我们使用ifeq语句来判断当前系统类型,如果是Linux则执行echo "当前系统是Linux",如果是MacOS则执行echo "当前系统是MacOS",如果既不是Linux也不是MacOS则执行echo "当前系统不是Linux也不是MacOS"。
makefile语法格式详解
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我感觉要作一个好的和 professional的程序员,makefile仍是要懂。
这就仿佛此刻有这么多的HTML的编辑器,但若是你想成为一个专业人士,你仍是要了解 HTML的标识的含义。
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是不是具有完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell 脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来讲,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux 下GNU的make。
可见,makefile都成了一种在工程方面的编译方式。
现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。
当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux ,make的版本是。
必竟,这个make是应用最为普遍的,也是用得最多的。
而且其还是最遵循于IEEE 标准的()。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。
makefile 语法
makefile 语法Makefile是一种常用的构建工具,用于自动化构建和管理软件项目。
它是一种文本文件,包含一系列规则,用于指定如何编译、链接和构建源代码。
本文将介绍 Makefile 的语法和使用方法。
一、Makefile 的基本语法Makefile 文件由一系列规则组成,每个规则由一个目标和一个或多个依赖项组成。
目标是要生成的文件名,依赖项是生成目标所需要的文件或命令。
当目标文件不存在或依赖项的时间戳比目标文件的时间戳更晚时,Makefile 将自动执行规则中的命令,生成目标文件。
一个简单的 Makefile 示例:```hello: main.cgcc -o hello main.c```这个 Makefile 包含了一个规则,目标是 hello,依赖项是main.c。
当 main.c 文件的时间戳比 hello 文件的时间戳更晚时,Makefile 将执行 gcc 命令编译 main.c 文件,并生成可执行文件hello。
Makefile 的规则语法如下:```target: dependenciescommand1command2...```其中,target 是规则的目标,dependencies 是规则的依赖项,command1、command2 等是要执行的命令。
命令必须以一个制表符或多个空格开头,否则 Makefile 将无法识别。
二、Makefile 的变量Makefile 中可以定义变量,用于存储常用的值或命令。
变量以$ 符号开头,可以在规则中使用。
变量的定义语法如下:```VARNAME = value```或者```VARNAME := value```其中,等号和冒号加等号的区别在于,等号定义的变量是递归展开的,而冒号加等号定义的变量是简单展开的。
递归展开的变量可以包含其他变量的引用,而简单展开的变量只能包含直接的值。
示例:```CC = gccCFLAGS = -Wall -O2hello: main.c$(CC) $(CFLAGS) -o hello main.c```这个 Makefile 中定义了两个变量 CC 和 CFLAGS,用于存储编译器和编译选项。
make的用法总结
make的用法总结Make 是一款用于编译程序的工具,其主要功能是依据程序的依赖关系自动构建目标文件和可执行文件。
Make 文件格式简单,易于编辑和管理,被广泛应用于各种软件开发项目中。
Make 语法:Makefile 是 Make 的配置文件。
Makefile 由一系列规则组成,每一条规则由三部分组成:目标文件:执行命令生成的文件名;依赖文件:目标文件所依赖的文件名,如果依赖文件发生改变,就需要重新执行规则中的命令;命令:生成目标文件的命令,一般用 Shell 脚本实现。
规则语法如下:target: dependenciescommand1command2...其中,冒号左边是目标文件,冒号右边是依赖文件。
冒号右侧可以有多个文件名,以空格分隔。
命令必须以制表符或者“空格+制表符”开头,否则会出现语法错误。
Make 命令:make 命令用于执行 Makefile 中的规则,生成目标文件或可执行文件。
常用的命令有:make:根据 Makefile 生成目标文件或可执行文件;make target:只生成指定的目标文件;make clean:删除所有目标文件和可执行文件;make help:显示 Makefile 中定义的帮助信息。
Make 变量:Make 变量可以在 Makefile 中定义和使用,用于简化规则的编写和维护。
常用的 Make 变量有:SRC_FILES:源文件列表;OBJ_FILES:目标文件列表;CXX:编译器;CXXFLAGS:编译选项;LD:链接器;LDFLAGS:链接选项。
Make 高级用法:1. 条件语句Makefile 中可以使用条件语句,进行不同的处理。
条件语句格式如下:ifeq ($(variable), value)# do somethingelse# do something elseendif其中,$(variable) 表示变量名,value 表示变量的值。
cmake makefile使用
cmake makefile使用一、概述CMake和Makefile都是用于管理和构建C/C++项目的工具。
其中,Makefile是Unix/Linux系统下最常用的构建工具之一,而CMake则是一个跨平台的构建工具。
二、Makefile1. Makefile是什么?Makefile是一个文本文件,用于指定如何编译和链接程序。
它包含了编译器需要执行的指令,以及指定源代码文件和目标文件之间的依赖关系。
2. Makefile语法Makefile由一系列规则组成,每个规则包含了以下内容:- 目标文件:需要生成的文件名- 依赖文件:生成目标文件所需要的源代码或其他目标文件- 命令行:生成目标文件所需要执行的命令例如:```target: dependency1 dependency2command1command2```其中,“target”表示目标文件,“dependency1”和“dependency2”表示依赖文件,“command1”和“command2”表示生成目标文件所需执行的命令。
3. Makefile使用方法在Linux系统中,可以使用make命令来读取并执行Makefile中的规则。
make命令会自动检测源代码和目标代码之间的依赖关系,并根据规则自动编译程序。
例如,在当前目录下有一个名为“test.c”的源代码文件,并且在同一目录下有一个名为“Makefile”的文件,其中包含以下规则:test: test.cgcc -o test test.c```则可以使用以下命令来编译程序:```make```4. Makefile的优缺点优点:- Makefile可以自动检测源代码和目标代码之间的依赖关系,只需要编写简单的规则即可。
- Makefile可以在不同的平台上使用,具有很好的可移植性。
缺点:- Makefile语法比较繁琐,需要编写大量的规则。
- Makefile无法自动处理一些复杂的依赖关系,需要手动编写规则。
makefile 冒号的用法
Makefile 冒号的用法
在Makefile中,冒号(:)主要有两种用法:
规则中的冒号:在Makefile的规则中,冒号用于分隔目标文件和依赖项。
规则的格式为“目标文件:依赖项1 依赖项2 ... 命令”。
其中,目标文件是规则要生成的文件,依赖项是目标文件所依赖的其他文件,命令是用于生成目标文件的命令。
例如,下面的规则表示当目标文件“foo.o”发生变化时,执行命令“gcc -c foo.c”来重新生成它:
makefile
foo.o: foo.c
gcc -c foo.c
双冒号规则中的冒号:在Makefile中,双冒号规则是一种特殊的规则,用于指定当多个文件具有相同的依赖项时,如何执行不同的命令来生成目标文件。
双冒号规则的格式为“目标文件:: 依赖项1 依赖项2 ... 命令”。
例如,下面的规则表示当“foo.c”或“bar.c”发生变化时,分别执行不同的命令来重新生成“Newprog”目标文件:
makefile
Newprog :: foo.c $(CC) $(CFLAGS) $< -o $@
Newprog :: bar.c $(CC) $(CFLAGS) $< -o $@
在双冒号规则中,当同一个目标出现在多个规则中时,会按照规则的书写顺序执行。
因此,在上面的例子中,如果“foo.c”发生变化,将执行第一个规则重新生成“Newprog”,然后执行第二个规则重新生成“Newprog”,因为“bar.c”没有被修改。
总结起来,冒号在Makefile中有两种主要用法:一种是用于分隔目标文件
和依赖项的普通规则中的冒号,另一种是用于指定多个规则中如何执行不同命令的双冒号规则中的冒号。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
clean: @rm -vf main.o test
使 用:定义依赖关系;依赖的下行是要执行的编译或连接命令,必须以TAB开头;在 clean其冒号后什么也没有,那么,make 就不会自动去找文件的依赖性,也就不会自动 执行其后所定义的命令。要执行其后的命令,就要在 make 命令后明显得指出这个 lable 的名字。这样的方法非常有用,我们可以在一个 makefile 中定义不用的编译或 是和编译无关的命令,比如程序的打包,程序的备份,等等。 在默认的方式下,也就是我们只输入 make 命令。那么, 1、make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。 2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找 到“test”这个文件,并把这个文件作为最终的目标文件。 3、如果 test文件不存在,或是 test所依赖的后面的 .o 文件的文件修改时间要比 test这个文件新,那么,他就会执行后面所定义的命令来生成 test这个文件。 4、如果 test所依赖的.o 文件也存在,那么 make 会在当前文件中找目标为.o 文件的 依赖性,如果找到则再根据那一个规则生成.o 文件。(这有点像一个堆栈的过程) 5、当然,你的 C 文件和 H 文件是存在的啦,于是 make 会生成 .o 文件,然后再 用 .o 文件生命 make 的终极任务,也就是执行文件 edit 了。
makefile简介
2012年11月1日 16:08
一、Makefile 的规则 target ... : prerequisites ...
command ….. target 是目标文件,prerequisites 依赖文件,command 也就是 make 需要执行的命令
test:main.o gcc -o test main.o
这 就是整个 make 的依赖性,make 会一层又一层地去找文件的依赖关系,直到最终编 译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不 到,那么 make 就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成 功,make 根本不理。make 只管文件的依赖性,即,如果在我找了依赖关系之后,冒号 后面的文件还是不在,那么对不起,我就不工作啦。
分区 makefile 的第 3 页
路径的自动Leabharlann 索2012年11月1日 16:16
在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分 类,并存放在不同的目录中。所以,当 make 需要去找寻文件的依赖关系时,你 可以在文件前加上路径,但最好的方法是把一个路径告诉 make,让 make 在自动 去找。Makefile 文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指 明这个变量,make 只会在当前的目录中去找寻依赖文件和目标文件。如果定义了 这个变量,那么,make 就会在当当前目录找不到的情况下,到所指定的目录中去 找寻文件了。 VPATH = src:../headers 上面的的定义指定两个目录,“src”和“../headers”,make 会按照这个顺序 进行搜索。目录由“冒号”分隔。(当然,当前目录永远是最高优先搜索的地 方)
通配符代替了你一系列的文件,如“*.c”表示所以后缀为 c 的文件。一个需要我 们注意的是,如果我们的文件名中有通配符,如:“*”,那么可以用转义字符 “\”,如“\*”来表示真实的“*”字符,而不是任意长度的字符串。好吧,还是 先来看几个例子吧: clean: rm -f *.o 上面这个例子我不不多说了,这是操作系统 Shell 所支持的通配符。这是在命令中 的通配符。 print: *.c lpr -p $? touch print 上面这个例子说明了通配符也可以在我们的规则中,目标 print 依赖于所有的[.c] 文件。其中的“$?”是一个自动化变量,表示被修改的文件。 objects = *.o 上面这个例子,表示了,通符同样可以用在变量中。并不是说[*.o]会展开,不! objects的值就是“*.o”。Makefile 中的变量其实就是 C/C++中的宏。如果你要让 通配符在变量中展开,也就是让 objects 的值是所有[.o]的文件名的集合,那么, 你可以这样:objects := $(wildcard *.o),这种用法由关键字“wildcard”指 出。
“.PHONY”来显示地指明一个目标是“伪目标”,向 make 说明,不管是 否有这个文件,这个目标就是“伪目标”。只要有这个声明,不管是否有 “clean”文件,要运行“clean”这个目标,只有“makeclean”这样。于是整 个过程可以这样写:
.PHONY: clean clean: rm *.o temp
分区 makefile 的第 1 页
makefile详述
2012年11月1日 16:13
Makefile 里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。
1、显式规则。显式规则说明了,如何生成一个或多的个目标文件。这是由 Makefile 的书写 者明显指出,要生成的文件,文件的依赖文件,生成的命令。
分区 makefile 的第 6 页
使用函数
2012年11月1日 16:17
函数调用,很像变量的使用,也是以“$”来标识的,其语法如下: $(<function> <arguments> ) 或是 ${<function> <arguments>} 这 里,<function>就是函数名,make 支持的函数不多。<arguments>是函数的参数,参数间 以逗号“,”分隔,而函数名和参数之间以“空格”分隔。函数调用以“$”开头, 以圆括号 或花括号把函数名和参数括起。感觉很像一个变量,是不是?函数中的参数可以使用变量, 为了风格的统一,函数和变量的括号最好一样,如使用 “$(subst a,b,$(x))”这样的形 式,而不是“$(subst a,b,${x})”的形式。因为统一会更清楚,也会减少一些不必要的麻 烦。 还是来看一个示例: comma:= , empty:= space:= $(empty) foo:= a b c bar:= $(subst $(space),$(comma),$(foo)) 在 这个示例中,$(comma)的值是一个逗号。$(space)使用了$(empty)定义了一个空 格,$(foo)的值是“a b c”,$(bar)的定义用,调用了函数“subst”,这是一个替换函 数,这个函数有三个参数,第一个参数是被替换字串,第二个参数是替换字串,第三个 参数 是替换操作作用的字串。这个函数也就是把$(foo)中的空格替换成逗号,所以$(bar)的值是 “a,b,c”。 $(subst <from>,<to>,<text> ) 名称:字符串替换函数——subst。 功能:把字串<text>中的<from>字符串替换成<to>。 返回:函数返回被替换过后的字符串。
分区 makefile 的第 5 页
定义命令包
2012年11月1日 16:16
如果 Makefile 中出现一些相同命令序列,那么我们可以为这些相同的命令序 列定义一个变量。定义这种命令序列的语法以“define”开始,以“endef”结 束,如:
define run-yacc yacc $(firstword $^) mv y.tab.c $@ endef 这里,“run-yacc”是这个命令包的名字,其不要和 Makefile 中的变量重 名。在“define”和“endef”中的两行就是命令序列。这个命令包中的第一个 命令是运行 Yacc 程序,因为Yacc 程序总是生成“y.tab.c”的文件,所以第 二行的命令就是把这个文件改改名字。还是把这个命令包放到一个示例中来看 看吧。 foo.c : foo.y $(run-yacc) 我们可以看见,要使用这个命令包,我们就好像使用变量一样。在这个命令包 的使用中,命令包“run-yacc”中的“$^”就是“foo.y”,“$@”就 是 “foo.c”(有关这种以“$”开头的特殊变量,我们会在后面介绍),make 在 执行命令包时,命令包中的每个命令会被依次独立执行。
5、注释。Makefile 中只有行注释,和 UNIX 的 Shell 脚本一样,其注释是用“#”字符, 这个就像 C/C++中的“//”一样。如果你要在你的 Makefile 中使用“#”字符,可以用反斜 框进行转义,如:“\#”。
最后,还值得一提的是,在 Makefile 中的命令,必须要以[Tab]键开始。 这样,make的执行过程如下: 1、读入所有的 Makefile。 2、读入被 include 的其它 Makefile。 3、初始化文件中的变量。 4、推导隐晦规则,并分析所有规则。 5、为所有的目标文件创建依赖关系链。 6、根据依赖关系,决定哪些目标要重新生成。 7、执行生成命令。
分区 makefile 的第 4 页
伪目标
2012年11月1日 16:16
我们提到过一个“clean”的目标,这是一个“伪目标”,clean: 正像我们前面例子中的“clean”一样,即然我们生成了许多文件编译文件,我 们也应该提供一个清除它们的“目标”以备完整地重编译而用。 (以“make clean”来使用该目标) 因为,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一 个标签,由于“伪目标”不是文件,所以 make 无法生成它的依赖关系和决定 它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。当然, “伪目标”的取名不能和文件名重名,不然其就失去了 “伪目标”的意义了。 当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记