makefile讲解
make makefile 的参数
make makefile 的参数make是一个常用的构建工具,用于自动化编译和构建软件项目。
makefile是make工具的配置文件,用于描述项目的构建规则和依赖关系。
本文将介绍makefile的参数,包括常用的参数及其用法。
一、常用参数及其用法1. -f 文件名:指定makefile的文件名,默认为"makefile"或"Makefile"。
通过该参数,可以使用其他名称的makefile文件。
2. -C 目录:指定make命令的工作目录。
在执行make命令时,会切换到指定的目录,并在该目录下查找makefile文件进行构建。
3. -n:显示执行make命令时的操作,但不实际执行。
通过该参数,可以预览make命令的执行过程,检查构建规则是否正确。
4. -p:显示make命令的内置变量和规则。
通过该参数,可以查看make命令的内部工作机制,了解makefile文件的编写规则和使用方法。
5. -B:强制重新构建目标文件。
通过该参数,可以忽略文件的时间戳,强制重新执行构建规则,生成新的目标文件。
6. -j 并发数:指定make命令的并发执行数。
通过该参数,可以提高构建速度,同时执行多个任务。
7. -s:静默模式,不显示执行的命令。
通过该参数,可以减少输出信息,使构建过程更加清晰。
二、makefile的构建规则makefile由一系列构建规则组成,每个规则定义了目标文件、依赖文件和构建命令。
make命令根据构建规则,自动判断需要更新的文件,并执行相应的构建命令。
构建规则的基本格式如下:目标文件: 依赖文件构建命令其中,目标文件是要生成的文件,依赖文件是目标文件依赖的文件,构建命令是生成目标文件的命令。
构建规则中的目标文件和依赖文件可以是文件名,也可以是变量。
通过使用变量,可以提高makefile的可维护性和灵活性。
构建命令可以是任意的Shell命令,包括编译、链接、拷贝等操作。
makefile中make指令传入的参数
makefile中make指令传入的参数Makefile中make指令传入的参数是指在执行make命令时,可以通过命令行传入的参数。
这些参数可以用于控制程序的编译、运行等行为,使得程序更加灵活和可配置。
在Makefile中,我们可以通过在命令行中输入make和参数来执行相应的操作。
参数可以是任意的字符串,可以用于指定编译选项、目标文件、源文件等等。
下面我将结合一些实际的例子,来详细讲解一下如何使用make指令传入的参数。
我们需要在Makefile中定义一些变量,用于存储传入的参数。
可以通过在命令行中使用“变量名=参数值”的方式来传入参数。
例如,我们可以定义一个变量CC,用于存储编译器的路径:```CC = gcc```在命令行中执行make命令时,可以通过“make CC=/usr/local/bin/gcc”来传入参数,将编译器的路径设置为“/usr/local/bin/gcc”。
接下来,我们可以在Makefile中使用这些参数。
例如,我们可以使用$(CC)来表示编译器的路径:```$(CC) -o target source.c```在执行make命令时,make会将$(CC)替换为实际的参数值,然后执行相应的命令。
这样,我们就可以通过命令行传入不同的编译器路径,来编译源文件。
除了编译器的路径,还可以通过命令行传入其他的参数。
例如,我们可以定义一个变量CFLAGS,用于存储编译选项:```CFLAGS = -Wall -O2```在命令行中执行make命令时,可以通过“make CFLAGS=-g”来传入参数,将编译选项设置为“-g”。
然后,我们可以在Makefile中使用这些参数。
例如,我们可以在编译命令中加入$(CFLAGS):```$(CC) $(CFLAGS) -o target source.c```在执行make命令时,make会将$(CFLAGS)替换为实际的参数值,然后执行相应的命令。
makefile--参数传递、条件判断、include(五)
makefile--参数传递、条件判断、include(五)在多个Makefile嵌套调⽤时,有时我们需要传递⼀些参数给下⼀层Makefile。
⽐如我们在顶层Makefile⾥⾯定义的打开调试信息变量DEBUG_SYMBOLS,我们希望在进⼊⼦⽬录执⾏⼦Makefile时该变量仍然有效,这是需要将该变量传递给⼦Makefile,那怎么传递呢?这⾥有两种⽅法:1. 在上层Makefile中使⽤”export”关键字对需要传递的变量进⾏声明。
⽐如:1 2DEBUG_SYMBOLS = TRUE export DEBUG_SYMBOLS当不希望将⼀个变量传递给⼦ make 时,可以使⽤指⽰符 “unexport”来声明这个变量。
export⼀般⽤法是在定义变量的同时对它进⾏声明。
如下:1export DEBUG_SYMBOLS = TRUE2. 在命令⾏上指定变量。
⽐如:1$(MAKE) -C xxx DEBUG_SYMBOLS = TRUE这样在进⼊⼦⽬录xxx执⾏make时该变量也有效。
像编程语⾔⼀样,Makefile也有⾃⼰的条件语句。
条件语句可以根据⼀个变量值来控制make的执⾏逻辑。
⽐较常⽤的条件语句是ifeq –else-endif、ifneq-else-endif、ifdef-else-endif。
ifeq关键字⽤来判断参数是否相等。
⽐如判断是否⽣成调试信息可以这么⽤:1 2 3 4 5 6ifeq ($(DEBUG_SYMBOLS), TRUE) >---CFLAGS += -g -Wall -Werror -O0 else>---CFLAGS += -Wall -Werror -O2 endifIfneq和ifeq作⽤相反,此关键字是⽤来判断参数是否不相等。
ifdef关键字⽤来判断⼀个变量是否已经定义。
后两个关键字⽤法和ifeq类似。
现在我们继续改进我们上⼀节的Makefile,上⼀节的Makefile完成Makefile的嵌套调⽤,每⼀个模块都有⾃⼰的Makefile。
makefile编写规则 ifeq
makefile编写规则 ifeq什么是makefile?makefile是一种用于自动化构建程序的工具,它能够根据文件之间的依赖关系,自动决定哪些文件需要重新编译。
makefile由一系列规则组成,每个规则定义了如何生成一个或多个目标文件。
make命令会根据这些规则来执行相应的操作,从而实现自动化构建的功能。
ifeq规则的作用在makefile中,ifeq是一种条件语句,用于判断某个条件是否为真。
它的基本语法如下:ifeq (condition, value)# 条件为真时执行的操作else# 条件为假时执行的操作endifcondition是一个条件表达式,可以使用各种比较运算符来进行比较。
value是一个字符串,用于与condition进行比较。
如果condition和value相等,则条件为真,执行ifeq后面的操作;否则条件为假,执行else后面的操作。
ifeq规则的使用场景ifeq规则在makefile中的使用场景很多,下面列举了几个常见的用法:1. 根据不同的操作系统执行不同的操作在跨平台开发中,可能需要根据不同的操作系统执行不同的操作。
可以使用ifeq 规则来判断当前的操作系统,然后执行相应的操作。
ifeq ($(OS),Windows_NT)# Windows系统下的操作CC = clelse# 非Windows系统下的操作CC = gccendif上面的示例中,如果当前操作系统是Windows,则将CC变量设置为cl;否则,将CC变量设置为gcc。
2. 根据变量的值执行不同的操作有时候需要根据某个变量的值来执行不同的操作。
可以使用ifeq规则来判断变量的值,然后执行相应的操作。
ifeq ($(DEBUG),1)# 调试模式下的操作CFLAGS = -gelse# 非调试模式下的操作CFLAGS =endif上面的示例中,如果DEBUG变量的值为1,则将CFLAGS变量设置为-g;否则,将CFLAGS变量设置为空。
makefile中make指令传入的参数
makefile中make指令传入的参数(实用版)目录1.Makefile 简介2.Make 指令的作用3.Make 指令传入的参数4.示例与实践正文1.Makefile 简介Makefile 是一种构建脚本,用于自动化构建和编译软件项目。
它通常包含一系列的规则和指令,可以自动地执行编译、链接和安装等任务。
Makefile 最早用于 Unix 系统,现在已广泛应用于各种操作系统和编程语言。
2.Make 指令的作用在 Makefile 中,Make 指令是最核心的命令。
它可以自动地执行一系列的编译、链接和安装等任务,以构建软件项目。
Make 指令的工作原理是基于依赖关系,它可以自动地发现源文件和目标文件之间的依赖关系,并按照一定的顺序执行相应的操作。
3.Make 指令传入的参数Make 指令传入的参数主要有以下几种:(1)目标:指定要构建的目标文件,通常是可执行文件或库文件。
(2)源文件:指定构成目标文件的源文件,可以是 C、C++等源代码文件。
(3)编译器:指定用于编译源文件的编译器,例如 gcc、g++等。
(4)链接器:指定用于链接目标文件和库文件的链接器,例如 ld、ld.so 等。
(5)其他选项:还可以指定其他选项,例如优化级别、输出文件名等。
4.示例与实践下面是一个简单的 Makefile 示例,用于编译一个 C 语言程序:```CC = gccCFLAGS = -Wall -o2SOURCES = main.cOBJECTS = main.oTARGET = mainall: $(TARGET)$(TARGET): $(OBJECTS)t$(CC) $(CFLAGS) $^ -o $@$(OBJECTS): $(SOURCES)t$(CC) $(CFLAGS) -c $< -o $@```在这个示例中,我们指定了编译器(CC)、优化选项(CFLAGS)、源文件(SOURCES)、目标文件(TARGET)和依赖关系(all: $(TARGET))。
makefile编译流程
makefile编译流程Makefile是一种用于自动化编译的工具,它可以根据源代码文件的依赖关系自动编译出目标文件。
Makefile的编写需要遵循一定的规则和语法,下面将介绍Makefile的编译流程。
1. 编写Makefile文件Makefile文件是一个文本文件,其中包含了编译的规则和依赖关系。
在编写Makefile文件时,需要遵循一定的语法规则,如使用TAB键缩进、使用变量和函数等。
2. 执行make命令在Makefile文件所在的目录下执行make命令,make会自动读取Makefile文件,并根据其中的规则和依赖关系进行编译。
如果Makefile文件中没有指定目标,则默认编译第一个目标。
3. 分析依赖关系在执行make命令时,make会先分析Makefile文件中的依赖关系,确定哪些文件需要重新编译。
如果某个源文件被修改了,那么与之相关的目标文件也需要重新编译。
4. 编译源文件在确定需要重新编译的文件后,make会依次编译每个源文件,生成对应的目标文件。
编译过程中,make会根据Makefile文件中的规则和命令进行编译。
5. 链接目标文件在所有的源文件都编译完成后,make会将所有的目标文件链接起来,生成最终的可执行文件。
链接过程中,make会根据Makefile文件中的规则和命令进行链接。
6. 完成编译当所有的源文件都编译完成并链接成功后,make会输出编译成功的信息,并生成最终的可执行文件。
如果编译过程中出现错误,make会输出错误信息并停止编译。
总之,Makefile编译流程是一个自动化的过程,它可以大大提高编译的效率和准确性。
在编写Makefile文件时,需要注意语法规则和依赖关系,以确保编译过程的正确性。
mk文件语法
mk文件语法
“MK文件语法”通常指的是Makefile文件的语法。
Makefile是一种用于自动化构建程序的工具,它描述了如何从源代码生成可执行文件或库文件。
Makefile文件使用特定的语法规则来定义构建规则、依赖关系和编译选项等。
Makefile的语法包括以下部分:
1.变量定义:使用VAR = value的形式定义变量,可以使用${VAR}引用变量
的值。
2.规则定义:使用target: dependencies的形式定义规则,其中target是要
生成的目标文件,dependencies是生成目标文件所需的依赖文件。
例如:hello: main.o utility.ogcc -o hello main.o utility.o
3.命令:定义规则之后可以跟一系列命令,用于生成目标文件。
命令会在执
行Makefile时顺序执行。
例如:%.o: %.cgcc -c $< -o $@
4.条件判断和循环:Makefile支持条件判断和循环结构,可以根据条件执行
不同的命令或重复执行一组命令。
例如:
ifeq ($(CC), gcc)CFLAGS += -O2elseCFLAGS += -O0endif
5.函数:Makefile还提供了一些内置函数,可以在变量、规则和命令中使用。
例如:$(warning "This is a warning message")
以上是Makefile语法的一些基本组成部分。
具体的语法规则和用法可能会根据不同的Makefile版本和工具而有所不同。
makefile obj用法
文章标题:深入探讨Makefile中的Obj用法在软件开发中,Makefile是一个非常重要的工具,它帮助程序员管理项目的编译和信息过程。
而Makefile中的Obj用法则是Makefile中非常重要的一部分,它用来指定项目中的目标文件。
在本篇文章中,我们将深入探讨Makefile中的Obj用法,从简单到复杂,由浅入深,帮助读者更好地理解和运用Obj用法。
1. 什么是Makefile在开始深入探讨Makefile中的Obj用法之前,我们先来了解一下什么是Makefile。
Makefile是一种文件,其中包含了一系列规则和命令,用于指导编译器如何编译和信息项目中的源文件,最终生成可执行文件。
Makefile通过维护文件之间的依赖关系,可以使得在修改源文件后,只重新编译需要重新编译的文件,而不是整个项目。
这样可以提高编译的效率,特别是在大型项目中非常重要。
2. Obj用法的基础概念Obj用法是Makefile中用来指定目标文件的一个重要部分。
在Makefile中,通常通过指定目标文件来定义一个编译单元,Obj用法就是用来指定这些目标文件的。
在Makefile中,Obj用法通常是在规则中使用的,用来指定编译的目标文件是哪些。
我们可以这样定义一个规则:```main.o : main.cgcc -c main.c -o main.o```在这个例子中,main.o就是通过Obj用法指定的目标文件,它告诉Makefile需要生成名为main.o的目标文件,并且它是由main.c编译而来的。
3. Makefile中的Obj用法进阶除了简单地指定目标文件外,Obj用法还可以进一步扩展。
在实际开发中,一个目标文件可能由多个源文件编译而来,这时候就需要用到Obj用法的进阶用法了。
在Makefile中,我们可以使用通配符来指定一组目标文件,例如:```%.o : %.cgcc -c $< -o $@```这个规则中,%表示任意的文件名,$<表示依赖文件,$@表示目标文件。
makefile基本使用方法
makefile基本使用方法makefile是一种用来管理和自动化构建程序的工具。
它可以根据源代码文件的依赖关系和编译规则来自动构建目标文件和可执行文件。
makefile的基本使用方法如下:1. 创建makefile文件:在项目的根目录下创建一个名为makefile 的文件。
2. 定义变量:在makefile中,可以使用变量来存储一些常用的参数和路径,以便于后续的使用。
例如,可以定义一个名为CC的变量来指定编译器的名称,如:CC=gcc。
3. 编写规则:在makefile中,可以使用规则来指定如何编译源代码文件和生成目标文件。
一个规则由两部分组成:目标和依赖。
目标是要生成的文件,依赖是生成目标文件所需要的源代码文件。
例如,可以编写以下规则:```target: dependency1 dependency2command1command2```其中,target是目标文件,dependency1和dependency2是依赖的源代码文件,command1和command2是生成目标文件所需要执行的命令。
4. 编写默认规则:在makefile中,可以使用一个默认规则来指定如何生成最终的可执行文件。
默认规则的目标通常是可执行文件,依赖是所有的源代码文件。
例如,可以编写以下默认规则:```all: target1 target2```其中,target1和target2是生成的目标文件。
5. 编写clean规则:在makefile中,可以使用clean规则来清理生成的目标文件和可执行文件。
例如,可以编写以下clean规则: ```clean:rm -f target1 target2```其中,target1和target2是要清理的目标文件。
6. 运行make命令:在命令行中,使用make命令来执行makefile 文件。
make命令会自动根据规则和依赖关系来编译源代码文件和生成目标文件。
例如,可以运行以下命令:``````make命令会根据makefile文件中的规则和依赖关系来编译源代码文件并生成目标文件和可执行文件。
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文件的格式Makefile文件是一种常见的文本文件,用于描述一个项目中各个文件之间的依赖关系和编译规则。
Makefile文件通常由一系列规则组成,每个规则由一个目标、依赖关系和命令组成。
Makefile文件的格式如下:1. 目标(Target)目标是指需要生成的文件或者执行的操作。
在Makefile中,目标通常是一个可执行程序或者一个库文件。
目标的格式为:target: dependenciescommand其中,target表示目标名称,dependencies表示该目标所依赖的其他文件或者操作,command表示生成该目标所需要执行的命令。
2. 依赖关系(Dependencies)依赖关系指该目标所依赖的其他文件或者操作。
在Makefile中,可以通过在目标后面加上冒号(:)来定义该目标所依赖的其他文件或者操作。
多个依赖关系之间可以使用空格或者Tab键来进行分隔。
3. 命令(Command)命令是指生成该目标所需要执行的具体操作。
在Makefile中,可以通过在每个规则后面添加一行以Tab键开头的命令来定义具体操作。
4. 变量(Variables)变量是指用于存储各种编译参数和路径等信息的变量。
在Makefile中,可以通过使用$()符号来引用变量,并使用=符号来进行赋值操作。
例如:CFLAGS = -Wall -O2CC = gcctarget: dependencies$(CC) $(CFLAGS) -o target dependencies5. 注释(Comments)注释是指用于对Makefile中各个规则进行解释说明的文本。
在Makefile中,可以使用#符号来进行注释,#符号后面的内容将被忽略。
总之,Makefile文件是一个非常重要的工具,在项目开发过程中起到了至关重要的作用。
掌握Makefile文件的格式和编写方法,可以帮助我们更加高效地管理和组织项目代码,并提高项目开发效率。
Makefile经典教程(最掌握这部分足够---因为汇集全部精华)!!!!!!!!!!
Makefile经典教程0 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 8.0,make的版本是3.80。
必竟,这个make是应用最为广泛的,也是用得最多的。
而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。
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学习笔记
1,以#开头的行为注释行,相当于C语言的// ,在makefile中是区分大小写的,make和MAKE是不一样的。
如果需要在makefile中使用#的符号,就要用反斜杠\#转义成#本身的意义2,makefile格式目标:依赖文件1,依赖文件2命令–依赖文件后缀依赖文件1,依赖文件2,目标注意:命令行必须以单个的TAB字符进行缩进,不能是空格当然也可以跟目标和依赖文件在一行,不过要以;隔开3,宏定义在linux中其实就是变量定义,在引用宏时必须在宏前加上$符号,而且如果变量名的长度超过一个字符,在引用时必须加圆括号()。
注意:$Z=$(Z),$(2),$(CFLAGS)都是有效的变量4,$*,$@,$?,$<四个特殊的宏的值在执行命令的过程中会发生相应的变化(自动化变量)5,宏的定义很简单,格式为:变量=变量值6,反斜杠(\)有时在makefile中是换行符的意思。
7,隐晦规则指的就是.o文件自己推导出同名的依赖文件.c.8,伪目标的格式可以为:.PHONY: cleanclean:rm edit $(obiect)―.PHONY‖表示,clean是个伪目标文件。
9,有些是在命令的前面加上减号如:如上句的:-rm edit $(obiect)也许某些文件出现问题,但不要管,继续做后面的事,这个减号的作用就是加强保障,还有一个全局的办法就是给make加上“-I‖或是“ignore-errors‖参数,那么makefile中所有的命令都会忽略错误。
还有一个就是make的参数是”-k‖或是“-keep-going‖,这个参数的意思是如果规则中的命令出错了,那么就终止该规则的执行,但继续执行其它规则。
10,makefile 工作执行的步骤:1)、读入所有的Makefile。
2)、读入被include的其它Makefile。
3)、初始化文件中的变量。
4)、推导隐晦规则,并分析所有规则。
5)、为所有的目标文件创建依赖关系链。
makefile 命令行参数
-C选项可以指定Makefile所在的路径。如果我们在当前路径下执行make命令,但是Makefile文件不在当前路径下,那么就需要使用-C选项来指定Makefile所在的路径。例如:
make -C /path/to/Makefile
3. -f选项
-f选项可以指定要使用的Makefile文件名。如果我们有多个Makefile文件,那么就可以使用-f选项来指定要使用哪个Makefile文件。例如:
makefile 命令行参数
Makefile是一种用来管理代码编译的工具,它可以自动化执行编译任务,帮助程序员更高效地管理代码。在Makefile中,可以定义一系列规则来指定如何编译代码。在使用Makefile时,我们可以通过命令行参数来控制编译过程的行为。本文将详细介绍makefile命令行参数的使用方法。项
-j选项可以指定并行编译时所使用的线程数。如果我们有多个CPU核心,并且要编译大型项目,那么就可以使用-j选项来加速编译过程。例如:
make -j4
5. --dry-run选项
--dry-run选项可以模拟执行make命令,并输出将要执行的命令列表,但是并不会真正地执行这些命令。这个功能非常实用,因为我们可以预先查看将要执行的命令,确保它们是正确的。例如:
这样做的好处是,我们可以在不修改Makefile的情况下,通过命令行参数来控制编译过程的行为。
四、总结
本文介绍了Makefile命令行参数的用法,包括make命令、-C选项、-f选项、-j选项、--dry-run选项和--print-data-base选项。同时,本文还介绍了一些Makefile常用技巧,包括使用变量来存储编译选项、使用通配符来自动生成目标文件列表和使用命令行参数来控制编译过程。希望本文能够对大家理解和学习Makefile有所帮助。
makefile 生成依赖关系
一、概述在软件开发过程中,源文件之间的依赖关系是非常重要的。
当一个文件发生变化时,其依赖文件可能也会受到影响,因此需要一个工具来管理这些依赖关系,确保在编译过程中能够正确地处理依赖关系。
makefile就是一个非常强大的工具,能够自动生成依赖关系,本文将详细介绍makefile生成依赖关系的方法。
二、什么是makefilemakefile是一个包含规则和命令的文本文件,用来描述软件项目的编译过程。
它告诉make工具,如何去利用源文件生成目标文件。
makefile通常包含了以下内容:1. 目标(target):表示要生成的文件,可以是可执行文件、中间文件或其他类型的文件。
2. 依赖(dependencies):表示目标文件所依赖的源文件或其他文件。
3. 命令mands):表示生成目标文件的具体操作,通常是编译、信息等。
三、makefile生成依赖关系的原理在编译过程中,一个源文件可能会依赖于其他源文件或头文件,当这些依赖关系发生变化时,我们需要重新编译相关的文件。
makefile 生成依赖关系的原理就是通过分析源文件中的#include语句,自动识别出文件之间的依赖关系,并生成相应的规则。
1. 使用gcc的-M选项gcc是一个非常流行的编译器,在编译过程中,它提供了-M选项来生成依赖关系。
例如:```make.o: .cgcc -c $< -o $ -MMD -MF $*.d```这里,-MMD选项表示生成依赖关系文件,-MF选项指定了依赖关系文件的名称。
通过这样的makefile规则,gcc能够自动生成每个源文件的依赖关系。
2. 使用自定义脚本除了使用gcc的-M选项外,我们也可以编写一个自定义的脚本来生成依赖关系。
这样能够更加灵活地控制依赖关系的生成过程。
五、makefile生成依赖关系的优势1. 自动化:makefile能够自动分析源文件之间的依赖关系,不需要手动维护依赖关系。
2. 灵活性:makefile生成依赖关系的方法非常灵活,可以根据实际需要选择不同的生成方式。
makefile四则运算
makefile四则运算标题:深入理解Makefile中的四则运算在软件开发过程中,Makefile是一个非常重要的工具,它主要用于自动化编译和链接程序。
而在Makefile中,我们可以使用一些特殊的语法进行数学运算,包括四则运算(加、减、乘、除)。
本文将详细解析Makefile 中的四则运算,帮助你更好地理解和使用这一功能。
一、Makefile中的变量与赋值在开始四则运算之前,我们首先需要了解Makefile中的变量和赋值。
在Makefile中,我们可以使用"="或者":="来为变量赋值。
其中"="表示延迟赋值,会在需要时才进行计算;而":="表示立即赋值,会在定义时就进行计算。
例如:VAR1 = 10VAR2 := 20在这段代码中,VAR1被赋值为10,VAR2被赋值为20。
二、Makefile中的四则运算在Makefile中,我们可以使用"(shell expr ...)"命令来进行四则运算。
这个命令会执行shell命令expr,并将结果返回。
以下是一些基本的四则运算示例:1. 加法:makefileSUM := (shell expr (VAR1) + (VAR2))在这个例子中,SUM会被赋值为VAR1和VAR2的和,即30。
2. 减法:makefileDIFF := (shell expr (VAR1) - (VAR2))在这个例子中,DIFF会被赋值为VAR1和VAR2的差,即-10。
3. 乘法:makefilePRODUCT := (shell expr (VAR1) \* (VAR2))注意,由于"*"在Makefile中有特殊含义,所以我们需要使用"\*"来表示乘法。
在这个例子中,PRODUCT会被赋值为VAR1和VAR2的乘积,即200。
Makefile
定义
概述
Linux环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序 员,至少不能称得上是 Unix程序员。在 Linux(unix )环境下使用GNU的make工具能够比较容易的构建一个属 于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投 入一些时间去完成一个或者多个称之为Makefile文件的编写。
在 UNIX系统中,习惯使用 Makefile作为 makefile文件。如果要使用其他文件作为 makefile,则可利用 类似下面的 make命令选项指定 makefile文件:
make命令
$ make -f Makefile.debug
Makefile文件工程样例例如,一个名为prog的程序由三个C源文件filea.c、fileb.c和filec.c以及库文件 LS编译生成,这三个文件还分别包含自己的头文件a.h、b.h和c.h。通常情况下,C编译器将会输出三个目标文件 filea.o、fileb.o和filec.o。假设filea.c和fileb.c都要声明用到一个名为defs的文件,但filec.c不用。即 在filea.c和fileb.
所要完成的Makefile文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以 及如何编译、需要创建哪些库文件以及如何创建这些库文件、如何最后产生我们想要的可执行文件。尽管看起来 可能是很复杂的事情,但是为工程编写Makefile的好处是能够使用一行命令来完成“自动化编译”,一旦提供一 个(通常对于一个工程来说会是多个)正确的 Makefile。编译整个工程你所要做的事就是在shell提示符下输入 make命令。整个工程完全自动编译,极大提高了效率。
海思makefile结构解析
海思makefile结构解析全文共四篇示例,供读者参考第一篇示例:海思芯片是一家领先的半导体公司,在国际市场上拥有广泛的市场份额。
海思芯片的产品广泛应用在手机、网络通信、物联网、智能家居等领域,其芯片性能卓越,在同行业内享有很高的声誉。
在海思芯片的开发中,makefile是一个非常重要的工具,它负责管理整个项目的编译、链接和部署过程,帮助开发人员更高效地完成工作。
makefile是一个用于自动化编译的脚本文件,通过编写makefile 文件,可以告诉计算机如何编译源代码,生成可执行文件。
海思makefile结构解析主要包括以下几个部分:1. 定义变量:在makefile中定义变量是非常重要的,可以方便地管理项目的路径、编译参数等信息。
海思makefile中通常会定义一些常用的变量,比如CC表示编译器的路径,CXX表示C++编译器的路径,CFLAGS表示编译参数等。
通过定义这些变量,可以在整个makefile中直接引用,减少了代码的冗余,提高了代码的可维护性。
2. 设置编译规则:在makefile中,通常会定义一些编译规则,告诉make工具如何编译源文件和生成可执行文件。
海思makefile中的编译规则通常使用模式匹配的方式,比如"%.c:%.o"表示将所有的.c文件编译为.o文件,而"%.o:%.c"则表示将所有的.o文件根据对应的.c文件进行重新编译。
通过这些编译规则,make工具可以根据需要自动化地完成整个项目的编译过程。
3. 定义目标:在makefile中通常会定义一些目标,这些目标可以是编译生成可执行文件的命令,也可以是清理生成的临时文件的命令。
海思makefile中的目标通常包括all、clean、install等,通过定义这些目标,可以方便地管理整个项目的编译和部署过程。
4. 调用外部工具:在海思makefile中,通常会调用一些外部工具来完成一些特定的任务,比如编译器、链接器、打包工具等。
makefile打印函数
makefile打印函数使用makefile打印函数是一种常见的编程技巧,可以帮助程序员更好地组织和管理代码。
在本文中,我们将探讨如何使用makefile打印函数,并介绍一些与之相关的概念和用法。
让我们来了解一下makefile是什么。
makefile是一种文本文件,其中包含了一系列规则和指令,用于告诉计算机如何编译和构建代码。
它通常用于大型项目的管理,可以自动化编译过程,提高开发效率。
在makefile中,可以使用函数来执行一些特定的操作。
函数是一种预定义的指令,可以接受参数并返回结果。
使用函数可以将一些常见的操作封装起来,提高代码的可读性和可维护性。
在makefile中,打印函数是一种常用的函数,用于在控制台上输出一些信息。
它可以用来调试代码、输出变量的值等。
在makefile中,有几个常用的打印函数,包括echo、warning和error。
让我们来看一下echo函数。
echo函数可以用来在控制台上输出一些文字。
在makefile中,可以使用echo函数来输出一些提示信息,或者打印变量的值。
例如,我们可以使用以下的语法来使用echo函数:```$(echo Hello, world!)```这条规则会在控制台上输出"Hello, world!"。
除了echo函数,makefile中还有warning和error函数。
warning 函数用于输出警告信息,而error函数用于输出错误信息。
这两个函数可以用于在编译过程中检测到一些问题时,及时地给出提示。
例如,我们可以使用warning函数来输出一个警告信息:```$(warning This is a warning message)```这条规则会在控制台上输出一个警告信息。
类似地,我们可以使用error函数来输出一个错误信息:```$(error This is an error message)```这条规则会在控制台上输出一个错误信息,并停止继续执行makefile。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
• 链接Object文件的隐含规则
“<n>‖目标依赖于“<n>.o‖,通过运行C的编译器来运行链接程序生 成,其生成命令是: $(CC) $(LDFLAGS) <n>.o $(LOADLIBES) $(LDLIBS)
• 老式风格的"后缀规则"
双后缀 定义一对后缀:目标文件的后缀和依赖目标的后缀。例如“.c.o‖相 当于“%o : %c‖ 单后缀 定义一个后缀,也就是依赖目标的后缀。例如".c"相当于"% : %.c―
• 自定义后缀
伪目标.SUFFIXES: .pco .cob .pc
自动化变量列表
• • • • • $@表示规则中的目标文件集。 $%仅当目标是函数库文件中,表示规则中的目标成员名。 $<依赖目标中的第一个目标名字。 $?所有比目标新的依赖目标的集合,以空格分隔。 $^所有的依赖目标的集合,以空格分隔。如果在依赖目标 中有多个重复的,那个这个变量会去除重复的依赖目标, 只保留一份。 • $+这个变量很像"$^",也是所有依赖目标的集合。只是它 不去除重复的依赖目标。 • $* 这个变量表示目标模式中"%"及其之前的部分。
隐含规则
• 特点
是Makefile默认运行的规则 可使用系统变量 可自定义隐含规则 显式规则优于隐含规则
隐含规则
• 隐含规则实例
foo : foo.o cc –o foo foo.o 等价于 foo.o : foo.c cc –c foo.c
隐含规则一览
• 编译C程序的隐含规则
“<n>.o‖的目标的依赖目标会自动推导为“<n>.c‖,并且其生成命令 是 $(CC) –c $(CPPFLAGS) $(CFLAGS)
Makefile的条件语法
• 条件表达式的语法为: <conditional-directive> <text-if-true> endif
以及:
<conditional-directive> <text-if-true> else <text-if-false> endif 其中<conditional-directive>表示条件关键字 ,这个关键字有四个ifeq , ifneq ,ifdef,ifndef • <conditional-directive>允许多余的空格, • else,endif, <conditional-directive>不能以[Tab]键做为开始
Makefile的引用函数
• 调用举例
$(subst <from>,<to>,<text> )
名称:字符串替换函数——subst。 功能: <from>--被替换前的字符串 <to>------ 被替换后的字符串 <text>-----被替换的字串 $(subst ee,EE,feet on the street) 原为feet on the street 调用函数后为fEEt on the street
如果目标文件的依赖文件不存在或者更新,会重新编译目标文 件 如果没有依赖文件,make不会自动执行command命令
• 在过程中出现错误,make会直接退出并报错
简单的Makefile实例
• objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : defs.h kbd.o : defs.h command.h command.o : defs.h command.h display.o : defs.h buffer.h insert.o : defs.h buffer.h search.o : defs.h buffer.h files.o : defs.h buffer.h command.h utils.o : defs.h
Makefile的引用函数
• 调用语法
$(<function> <arguments> ) ${<function> <arguments>}
<function>函数名
<arguments>函数的参数
• 语法要求
参数间以逗号“,‖分隔 函数名和参数之间以“空格”分隔 函数调用以“$‖开头, 以圆括号或花括号把函数名和参数括起
make的工作方式
1、读入Makefile。 2、读入引用Makefile等文件。 3、初始化文件中的变量。 4、推导隐晦规则,并分析所有规则。 5、为所有的目标文件创建依赖关系链。 6、根据依赖关系,决定哪些目标要重新生成。 7、执行生成命令。
Makefile的默认工作原理
• 找到第一个目标文件,并把该文件作为最终文件 • 根据依赖关系进行工作
targets : prerequisites ; command command
targets-- -- 文件名,以空格分开 prerequisites--目标所依赖的文件,以空格分开多个文件 command-- -命令行, [Tab键]开头,用分号做为分隔
Makefile的引用文件
• include <filename1> <filename2>
Makefile的规则
• target ... : prerequisites ... command
target 目标文件 prerequisites 源文件 command源文件生成目标文件的规则,shell命令
Makefile内容
• Makefile里主要包含了五项内容
显式规则 隐晦规则 变量 引用文件 注释
filename—文件名称+路径
• 特点
符合shell的任意文件模式
多个文件以空格分开 include不能以[Tab]键开始 ,可以存在空格
Makefile的引用变量
• 变量命名语法 包含字符、数字,下划线(可以是数字开头) 不能使用“:‖、“#‖、“=‖或是空字符(空格、回车等) 大小写敏感 • 定义 变量在声明时需要赋初值 • 使用 在变量名前加上“$‖符号,建议使用小括号“()”或是大括号“{}‖ • 变量引用变量 • $(var:a=b)‖或是“${var:a=b} • 操作符“=‖和”:=‖的区别 • 操作符 “?=‖
Makefile讲解
• • • •
Makefile概述 Makefile编写 Makefile运行 Makefile应用实例
课前培训
• 什么是Unix shell脚本 • 什么是Makefile • 什么是程序的编译链接
Makefile概述
• • • • • • Makefile的规则 Makefile的内容 Makefile的文件名 Makefile的工作原理 Makefile的工作方式 Makefile的简单实例
Makefile的条件语法
• ifeq (<arg1>, <arg2> )
比较两个参数的值是否相同,相同为真
• ifneq (<arg1>, <arg2> )
比较两个参数的值是否相同,不同为真
• ifdef <variable-name>
变量的值非空,则表达式为真
• Ifndef
变量的值为空,则表达式为真
Makefile的字符含义
• 命令间的“;” 上条命令结果应用到下条命令 • 命令行前的字符“@‖ 不显示执行命令 • 命令行前的字符“-‖ 忽略执行该命令的错误 • 命令行前的字符“#‖ 用于注释,Makefile中只有行注释 • 命令中的波浪号“~‖ ―~/test‖,这就表示当前用户的$HOME目录下的test目录 “~hchen/test‖则表示用户hchen的宿主目录下的test目录 • 命令中的波浪号“\ ‖
Makefile的文件名
• 默认的三种文件名
GNUMakefile、Makefile、makefile 执行时直接使用make命令 make = make -f Makefile
• 自定义文件名
可使用自定义文件名,makelib 执行时使用make的“-f‖和“--file‖参数 make –f makelib
Makefile的编写
• • • • • • Makefile的书写规则 Makefile的引用文件 Makefile的引用变量 Makefile的条件语法 Makefile的引用函数 Makefile的字符含义
Makefile的书写规则
• 规则语法
target ... : prerequisites ... command
Makefile 的运行
• Makefile的运行参数 “—debug[=<options>]‖ 输出make的调试信息。它有几种不同的级别可供选择,如果没有参 数,那就是输出最简单的调试信息。下面是<options>的取值: a —— 也就是all,输出所有的调试信息。(会非常的多) b —— 也就是basic,只输出简单的调试信息。即输出不需要重编译 的目标。 v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个 Makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。 i —— 也就是implicit,输出所以的隐含规则。 j —— 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、 返回码等。 m —— 也就是Makefile,输出make读取Makefile,更新Makefile,执 行Makefile的信息。 -d--默认等同于 –d文件和依赖文件的规则列表 测试是否所有的依赖文件都存在或是理当存在 如果存在或是理当存在,形成规则 执行规则其相当的命令,并加载自定义变量