10分钟教你学会Makefile
makefile中使用cp命令
makefile中使用cp命令介绍在编写软件项目时,为了方便管理和构建代码,我们通常会使用makefile来自动化构建过程。
makefile是一种用于描述代码构建规则的文件,其中可以包含各种命令和指令。
其中,cp命令是makefile中常用的一个命令,用于复制文件或目录。
cp命令的基本用法cp命令的基本语法如下:cp [选项] 源文件目标文件其中,选项可以用来指定一些复制的行为,例如是否覆盖目标文件、是否保留源文件的属性等。
源文件是要复制的文件或目录,目标文件是复制后的文件或目录的名称。
cp命令的常见选项cp命令有许多选项可以用来控制复制的行为,下面是一些常见的选项: - -r:递归地复制目录及其内容。
- -f:强制复制,即使目标文件已经存在也进行复制。
- -i:交互式复制,如果目标文件已经存在,会询问是否覆盖。
- -p:保留源文件的属性,包括权限、时间戳等。
- -u:只复制更新的文件,即只复制源文件比目标文件新的文件。
- -v:显示详细的复制过程。
使用cp命令复制文件在makefile中使用cp命令复制文件可以方便地将源文件复制到目标文件中。
下面是一个简单的示例:all:cp source_file.txt target_file.txt上述示例中,我们使用了makefile的规则,其中all是规则的目标,cpsource_file.txt target_file.txt是规则的命令。
当我们运行make命令时,makefile会根据规则执行相应的命令,从而完成文件的复制。
使用cp命令复制目录除了复制文件,cp命令还可以复制目录及其内容。
在makefile中,我们可以使用cp命令的-r选项来递归地复制目录。
下面是一个示例:all:cp -r source_directory target_directory上述示例中,我们使用了-r选项来递归地复制source_directory目录及其内容到target_directory目录中。
makefile all用法
makefile all用法Makefile是一种类似于脚本的文件,可以用来自动化构建、编译和整合代码。
Makefile中常常会用到all指令,可以一次性执行多个任务。
本篇文章将详细说明Makefile中all指令的用法。
一、all指令的用途在Makefile中使用all指令的语法非常简单,只需要在文件中添加如下代码即可:all:<command1><command2><command3>...<command_n>其中,<command>表示需要执行的命令,可以是编译、构建、安装等一系列操作。
在语法中,all指令后面紧跟着“:”,表示all指令执行的是“伪目标”,而不是一个真正的文件。
也就是说,all指令并不会生成任何东西,它只是用来方便执行多个任务的一个指令。
1. all指令必须放在Makefile文件的开头。
这是因为,Makefile文件中的第一个目标就是Makefile默认的目标,也就是all指令。
2. all指令的语句必须以制表符(Tab)开头,否则会出现错误。
这是因为Makefile中使用了缩进,而不是空格,来标识命令与目标之间的关系。
因此,必须使用制表符来开头。
3. 如果在执行all指令的时候,其中的某个命令失败了,则后续的命令将不再执行。
这是因为Makefile中使用的是顺序执行的方式,即一个任务执行完成后才会进行下一个任务的执行。
下面是一个简单的Makefile文件,其中包含了几个常用的构建命令:说明:4. 使用make命令时,可以通过传递参数来指定执行的目标。
比如make clean,就只会执行clean目标下的所有命令。
总结:Makefile中使用all指令能够一次性执行多个命令,方便快捷。
在Makefile文件中添加all指令时,需要注意语法和文件位置等问题,避免出现错误。
在实际开发过程中,建议在Makefile文件中添加clean等指令,用于清理生成的目标文件和可执行文件。
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 if用法
makefile if用法Makefile 是一种常用的构建工具,用于自动化构建软件项目。
在Makefile 中,if 语句能够根据条件来选择不同的命令或变量赋值。
本文将逐步介绍Makefile 中if 语句的用法,包括条件判断、变量赋值、嵌套使用等方面的内容。
首先,我们需要了解Makefile 中if 语句的基本语法。
if 语句可以写在任何位置,但通常我们将其放在文件的顶部,用于设置全局变量或选择不同的命令。
if 语句的基本结构如下:ifeq (条件,值)# 条件成立时执行的命令或变量赋值else# 条件不成立时执行的命令或变量赋值endif在这个基本结构中,ifeq 为条件判断语句,它用于判断条件是否等于某个值。
若条件成立,则执行if 代码块内的命令或进行变量赋值,否则执行else 代码块内的命令或变量赋值。
endif 表示if 语句的结束。
接下来,我们来看一些具体的示例,以帮助理解if 语句的用法。
1. 条件判断:在Makefile 中,我们可以使用各种条件进行判断。
以下是一些常用的判断方式:- 变量是否为空:ifeq ((VAR),)# VAR 为空时执行的命令或变量赋值else# VAR 不为空时执行的命令或变量赋值endif- 变量是否等于某个值:ifeq ((VAR),某个值)# VAR 等于某个值时执行的命令或变量赋值else# VAR 不等于某个值时执行的命令或变量赋值endif- 多个条件判断:ifeq ((VAR),某个值)# VAR 等于某个值时执行的命令或变量赋值else ifeq ((VAR),另一个值)# VAR 等于另一个值时执行的命令或变量赋值else# VAR 既不等于某个值,也不等于另一个值时执行的命令或变量赋值endif2. 变量赋值:在if 语句中,我们可以根据条件选择不同的变量赋值,使得程序更具有灵活性。
以下示例展示了如何根据条件选择不同的变量赋值:ifeq ((OS),Linux)# OS 等于Linux 时,执行以下变量赋值CC = gccelse# OS 不等于Linux 时,执行以下变量赋值CC = clangendif根据上述示例,当操作系统为Linux 时,CC 的值将被赋为gcc,否则为clang。
makefile make install 用法举例
makefile make install 用法举例Makefile是一种用于自动化编译和构建软件的工具,它可以根据不同的构建目标(如编译、安装等)自动生成相应的构建指令。
在Makefile中,可以使用make命令来执行构建任务,其中make install是一种常用的构建指令,用于安装软件包。
一、Makefile的创建在创建Makefile之前,需要了解项目的基本结构和依赖关系,并根据需求定义不同的构建目标。
Makefile通常包含多个规则,每个规则定义了一个特定的构建目标及其对应的构建指令。
以下是一个简单的Makefile示例,用于编译一个C语言程序:```makefileCC=gccCFLAGS=-Wall -gSRC=main.c utils.cOBJ=$(SRC:.c=.o)all: $(SRC) Makefile $(OBJ)$(CC) $(CFLAGS) $(OBJ) -o program%.o: %.c$(CC) $(CFLAGS) -c $< -o $@clean:rm -f $(OBJ) $(EXE) *.o core* *~ .depend```在这个示例中,我们定义了两个规则:all规则和%.o规则。
all规则用于定义编译和链接指令,而%.o规则用于定义编译指令。
在执行make命令时,Makefile会根据当前目录下的Makefile和源文件自动生成相应的构建指令。
二、make install的使用make install是Makefile中常用的一种构建指令,用于将软件包安装到目标系统中。
使用make install命令时,需要指定安装的目标目录和安装选项。
下面是一个简单的示例:假设我们有一个名为myapp的软件包,将其安装到/usr/local/目录下:```bashmake install prefix=/usr/local/```在这个示例中,我们使用make install命令将myapp软件包安装到/usr/local/目录下。
makefile引用标准c函数
一、概述在软件开发过程中,为了提高代码的可维护性和可移植性,通常会使用Makefile来管理代码的编译和信息过程。
而在C语言的开发中,经常会用到标准C库中的各种函数。
本文将讨论如何在Makefile中引用标准C函数,以及一些注意事项和最佳实践。
二、Makefile中的规则Makefile是用来描述软件项目中文件之间的依赖关系的文件。
它包含了一系列规则,每个规则包含了一个目标文件、依赖文件和生成目标文件的命令。
当执行make命令时,Makefile会根据规则自动执行对应的命令,从而生成目标文件。
三、引用标准C函数1. 在Makefile中引用标准C函数需要首先确保C标准库的头文件被正确包含。
在C语言中,通过#include指令可以将标准C库的头文件包含到源文件中。
2. 在Makefile中,我们可以使用变量来定义编译器、编译选项和信息选项。
我们可以定义CC变量来指定C语言的编译器,CFLAGS变量来指定编译选项,LDFLAGS变量来指定信息选项。
3. 当我们需要在Makefile中引用标准C函数时,我们只需要在对应的规则中使用变量来指定编译选项和信息选项。
如果我们需要使用标准C函数printf,我们只需要在对应的规则中将需要用到的标准库信息到目标文件中。
四、注意事项和最佳实践1. 在Makefile中引用标准C函数时,我们需要确保编译时能找到对应的标准C库文件。
通常情况下,标准C库文件会在系统的标准库目录下,我们需要将这些目录添加到信息选项中。
2. 在Makefile中引用标准C函数时,我们需要确保编译器能找到对应的标准C库头文件,通常情况下,标准C库头文件会在系统的标准头文件目录下,我们需要将这些目录添加到编译选项中。
3. 在Makefile中引用标准C函数时,我们需要确保编译器能正确识别和处理对应的标准C函数的参数和返回值类型。
通常情况下,标准C函数的参数和返回值类型会在对应的头文件中定义,我们需要确保这些定义被正确包含到源文件中。
make的主要用法
make的主要用法Make是一个常用的构建工具,它可以自动化地编译程序、生成文档、打包发布等操作。
Make最初是Unix系统下的一个工具,现在已经被广泛地应用于各种平台和语言中。
一、Make的基本概念1.1 MakefileMakefile是Make的配置文件,它描述了如何构建目标文件。
Make会根据Makefile中的规则来判断哪些文件需要重新编译,以及如何编译它们。
1.2 目标文件目标文件是指要生成的文件,可以是可执行程序、静态库、动态库等。
在Makefile中,每个目标都有一个对应的规则来描述如何生成它。
1.3 依赖关系依赖关系指的是目标文件与源文件之间的关系。
如果一个目标文件依赖于另外一个文件,那么在生成这个目标文件之前必须先生成它所依赖的那个文件。
1.4 规则规则描述了如何从源代码生成目标代码。
规则由三部分组成:目标、依赖和命令。
其中,目标表示要生成的文件,依赖表示该目标所依赖的其他文件,命令表示如何从依赖中生成目标。
二、Makefile语法2.1 变量定义变量可以用来存储一些常用的值,比如编译器、编译选项等。
变量的定义格式为:变量名=变量值。
2.2 目标规则目标规则描述了如何生成一个目标文件。
目标规则的格式为:目标: 依赖命令其中,目标表示要生成的文件,依赖表示该目标所依赖的其他文件,命令表示如何从依赖中生成目标。
2.3 伪目标伪目标是指不对应任何实际文件的目标,它们通常用来描述一些特殊的操作,比如清空临时文件、打包发布等。
伪目标的名称前面要加上一个“.”号。
2.4 函数Make提供了一些内置函数来方便我们编写Makefile。
常用的函数有:$(wildcard pattern)、$(patsubst pattern,replacement,text)、$(subst from,to,text)等。
三、Makefile实例下面是一个简单的Makefile示例:CC=gccCFLAGS=-Wall -gLDFLAGS=-lmall: hello_world.exehello_world.exe: hello_world.o$(CC) $(LDFLAGS) $< -o $@hello_world.o: hello_world.c$(CC) $(CFLAGS) -c $< -o $@clean:rm -f *.o *.exe这个Makefile定义了三个变量:CC表示编译器,CFLAGS表示编译选项,LDFLAGS表示链接选项。
python makefile 用法
python makefile 用法在使用Python编写程序时,我们通常需要编译和运行代码,这就需要用到makefile。
makefile是一种可以自动化地构建程序的工具,它可以根据代码修改的情况自动判断哪些文件需要重新编译,从而提高程序的编译效率。
使用makefile的基本步骤如下:1. 创建一个名为makefile的文件,通常放在程序的根目录下。
2. 在makefile中定义一些变量,如编译器、编译选项等。
3. 定义一些规则,如编译规则、目标规则等。
4. 运行make命令,根据makefile的规则进行编译和链接。
下面是一个简单的makefile示例:```# 定义编译器和编译选项CC=gccCFLAGS=-Wall -g# 定义编译规则%.o: %.c$(CC) $(CFLAGS) -c $< -o $@# 定义目标规则main: main.o sub.o$(CC) $(CFLAGS) main.o sub.o -o main# 清除中间文件clean:rm -f *.o main```在这个示例中,我们定义了两个变量CC和CFLAGS,分别表示编译器和编译选项。
接着定义了一个编译规则,表示将.c文件编译成.o文件的过程。
其中,$<表示依赖文件(即输入文件),$@表示目标文件(即输出文件)。
最后定义了一个目标规则,表示将main.o和sub.o链接成可执行文件main。
最后,我们定义了一个清除中间文件的规则,可以通过运行make clean来清除中间文件。
可以通过运行make命令来编译和链接程序。
例如,如果你有一个名为main.c和sub.c的源文件,并想将它们编译成可执行文件main,可以在终端中输入以下命令:```$ make main```这将根据makefile中定义的规则自动编译和链接程序,并生成可执行文件main。
总之,makefile是一个非常有用的编译工具,可以帮助我们自动化地构建程序,提高编译效率。
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文件时,需要注意语法规则和依赖关系,以确保编译过程的正确性。
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的一个重要内容,规则。
熟悉规则对于书写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?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。
这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,VisualC++的nmake,Linux下GNU的make。
可见,makefile都成为了一种在工程方面的编译方法。
现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。
当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux8.0,make的版本是3.80。
必竟,这个make是应用最为广泛的,也是用得最多的。
而且其还是最遵循于IEEE 1003.2-1992标准的(POSIX.2)。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。
makefile gcc编译
makefile gcc编译
Makefile 是一个用来组织代码编译的工具,而 GCC 是一个常用的 C 和 C++ 编译器。
在 Makefile 中使用 GCC 进行编译可以通过以下步骤完成:
1. 创建一个名为 "Makefile" 的文本文件,并确保它位于你的项目根目录下。
2. 在 Makefile 中定义你的编译规则。
例如,假设你有一个名为 "main.c" 的源文件需要编译成可执行文件 "app",你可以这样编写 Makefile:
make.
app: main.c.
gcc -o app main.c.
在这个例子中,我们定义了一个名为 "app" 的目标,它依赖于"main.c" 这个源文件。
当你运行 "make" 命令时,Make 工具会根
据这个规则来执行编译。
3. 打开终端,进入到包含 Makefile 的项目目录下。
4. 运行命令 "make"。
Make 工具会读取 Makefile 文件,并执行其中定义的编译规则。
在这个例子中,它会使用 GCC 编译器来编译 "main.c" 并生成可执行文件 "app"。
需要注意的是,Makefile 可以包含更复杂的规则和变量定义,以及支持多个源文件的编译。
你可以根据你的项目需求来进一步扩展和定制 Makefile 文件。
总之,通过合理编写 Makefile 并结合使用 GCC 编译器,你可以高效地组织和管理你的代码编译过程。
关于make的用法
关于make的用法一、make的概述及基本用法在计算机编程中,make是一个非常重要的工具,被广泛用于软件项目的自动化构建。
Make可以根据用户定义的规则和依赖关系,有效地管理项目中各个文件之间的编译关系,从而实现高效地构建出可执行文件或库。
Make通常使用Makefile文件来描述项目中各个源文件之间的依赖关系和编译规则。
在Makefile中,我们可以定义一系列的目标(target),每个目标表示一个需要构建的文件或者一项任务。
接下来,让我们详细了解make的基本用法。
二、Makefile的语法及规则1. 目标与依赖关系在一个Makefile中,目标(target)是构建任务的最终产物或者需要执行的某种操作。
可以将目标理解为一个文件名,但不限于此,还可以是用户指令等其他形式。
依赖关系(dependencies)是指完成某个目标所必需的其他文件或目标。
当一个目标所依赖的其中任何一个依赖发生变化时,该目标就会被重新构建。
2. 规则和命令规则(rules)是指定了如何生成特定目标以及其相应依赖之间关系的语句。
每条规则通常包含两部分:目标和命令。
目标一般是一个文件名,表示所要生成的文件或者任务。
命令则是构建该目标所需的具体操作步骤。
3. 变量和函数Makefile中还可以定义变量和函数,用于简化构建过程中的重复代码和参数配置。
变量可以存储各种常用值(如编译器选项、文件路径等),而函数可以根据给定参数执行一系列操作。
三、make指令及常用选项1. make指令make命令是调用make工具来执行Makefile中定义的任务。
在终端中输入"make"命令会默认执行Makefile文件中第一个目标的构建操作。
如果我们想指定其他目标,可以使用以下方式:```$ make 目标名```2. 常用选项- "-f filename" 或 "--file=filename":指定要使用的Makefile文件。
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的流程。
sv 中的makefile 写法
SV(SystemVerilog)是一种硬件描述语言,用于设计和验证数字电路。
在进行SV代码编写的过程中,makefile是一种非常有用的工具,可以帮助组织和管理SV项目中的代码文件。
本文将介绍SV中makefile的写法,希望能为SV开发者提供一些参考和帮助。
1. 为什么需要makefile在SV项目中,通常会涉及到多个源文件、库文件、测试文件等。
使用makefile可以帮助我们轻松地组织和管理这些文件,实现自动化编译、信息和运行测试的功能。
makefile还可以帮助我们避免重复编译文件,提高开发效率。
2. makefile的基本结构makefile由一系列规则组成,每个规则由一个目标、依赖列表和命令组成。
一个基本的makefile看起来像这样:```makefiletarget: dependenciesmand```其中,target表示规则的目标文件,dependencies表示该目标文件的依赖文件mand表示需要执行的命令。
3. 使用变量在makefile中,我们可以使用变量来定义一些常量,方便我们在后续的规则中使用。
例如:```makefileSV_SRC = file1.sv file2.sv file3.sv```这样,我们就可以在后续的规则中使用$(SV_SRC)来表示这些文件,而不需要重复地写出它们的文件名。
4. 基本规则在SV项目中,常见的makefile规则包括编译规则、信息规则和运行测试规则。
以下是一个简单的例子:```makefileall: $(SV_SRC)vlog $(SV_SRC)sim: allvsim top_module```在这个例子中,我们定义了两个规则,分别是all和sim。
all规则依赖于$(SV_SRC)中的文件,使用vlog命令对这些文件进行编译。
sim规则依赖于all规则,使用vsim命令来运行测试。
5. 使用通配符在makefile中,我们还可以使用通配符来表示一类文件。
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 表示变量的值。
使用makefile编译多个文件(.c,.cpp,.h等)
使⽤makefile编译多个⽂件(.c,.cpp,.h等)有时候我们要⼀次运⾏多个⽂件,这时候我们可以使⽤Makefile◊make是什么? make是⼀个命令⼯具,是⼀个解释makefile中指令的命令⼯具。
它可以简化编译过程⾥⾯所下达的指令,当执⾏make 时,make 会在当前的⽬录下搜寻 Makefile (or makefile) 这个⽂本⽂件,执⾏对应的操作。
make 会⾃动的判别原始码是否经过变动了,⽽⾃动更新执⾏档。
◊为什么要使⽤make? 假设,现在⼀个项⽬⾥⾯包含了100个程序⽂件,如果要对这个项⽬进⾏编译,那么光是编译指令就有100条。
如果要重新进⾏编译,那么就⼜得像之前⼀样重新来⼀遍。
这样重复且繁琐的⼯作实在是让我们很不爽啊。
所以,⽤make来进⾏操作,间接调⽤gcc岂不是很⽅便?如果我们更动过某些原始码档案,则 make 也可以主动的判断哪⼀个原始码与相关的⽬标⽂件档案有更新过,并仅更新该档案。
这样可以减少重新编译所需要的时间,也会更加⽅便。
◊makefile⼜是⼲什么的? makefile其实就是⼀个⽂档,⾥⾯定义了⼀系列的规则指定哪些⽂件需要先编译,哪些⽂件需要后编译,哪些⽂件需要重新编译,它记录了原始码如何编译的详细信息! makefile⼀旦写好,只需要⼀个make命令,整个⼯程完全⾃动编译,极⼤的提⾼了软件开发的效率。
先看⼀下makefile的规则: ⽬标(target):⽬标⽂件1 ⽬标⽂件2 <Tab>gcc -o 欲建⽴的执⾏⽂件⽬标⽂件1 ⽬标⽂件2先举⼀个运⾏多个c语⾔⽂件。
⾸先下⾯是⼀个完整的 c语⾔⽂件,实现了统计⽤户输⼊的字符串中⼤⼩写字母的个数#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>void test(){char str[50]={0};scanf("%s",str);int m=0;int n=0;pid_t p=fork();if(p<0){printf("fork failed");}if(p == 0){for(int i=0;i<sizeof(str);i++){if( str[i]<='Z'&& str[i]>='A'){m++;}}printf("⼤写字母⼀共有");printf("%d",m);printf("个");}if(p>0){for(int i=0;i<sizeof(str);i++){if(str[i]>='a' && str[i]<='z'){n++;}}printf("⼩写字母⼀共有");printf("%d",n);printf("个");}}int main(){test();return 0;}此时我们可以把该⽂件拆成三份,⼀份是.h⽂件,⽤来放头⽂件等信息,另外两个是.c⽂件,⼀个⽤来放main⽅法,⼀个放声明的函数,如下三图则在终端进⾏⼀下操作成功运⾏多个⽂件下⾯介绍运⾏cpp⽂件,⼤致步骤相同。
makefile拷贝语句
makefile拷贝语句Makefile是一种用于自动化构建和管理项目的工具,它通过描述目标文件与依赖文件之间的关系,以及如何生成目标文件的规则来完成任务。
在Makefile中,拷贝文件是一个常见的操作,可以通过使用cp命令来实现。
下面是一些常用的Makefile拷贝语句,用于在构建过程中拷贝文件。
1. 拷贝单个文件:```target_file: source_filecp source_file target_file```这个拷贝语句将源文件source_file拷贝到目标文件target_file。
2. 拷贝多个文件到同一目录:```target_files: source_filescp source_files target_directory```这个拷贝语句将源文件source_files拷贝到目标目录target_directory下。
3. 拷贝多个文件到不同目录:```target_files: source_filescp source_files target_directory1cp source_files target_directory2...```这个拷贝语句将源文件source_files拷贝到多个不同的目录target_directory1、target_directory2等。
4. 拷贝目录:```target_directory: source_directorycp -r source_directory target_directory```这个拷贝语句将源目录source_directory及其所有子目录和文件拷贝到目标目录target_directory。
5. 拷贝文件并重命名:```target_file: source_filecp source_file target_directory/target_file```这个拷贝语句将源文件source_file拷贝到目标目录target_directory,并重命名为target_file。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux基础 – Makfile
梅方靖
编译流程
编译流程: 预处理->编译->汇编->链接
Linux
每个编译的环节都会产生不同类型的文件,对于C程序: 预处理 -> .i文件 编译 -> .s文件 汇编 -> .o文件 => .a文件 .so文件 链接 -> 可执行文件 每个环节都有自己的依赖,即若想生成.o文件,那么需 要.s、.i、.c文件。
Makefile简单的练习
有三个源程序 程序fun:
程序main.c:
使用gcc编译出应用程序test: #gcc fun1.c fun2.c main.c -o test
接下来,我们使用Makefile来写一个 脚本。
Makefile简单的练习
#sample makefile script CC=gcc SRCS=fun1.c fun2.c main.c EXEC=test all: $(CC) $(SRCS) -o $(EXEC) clean: rm -rf $(EXEC)
Makefile自动检测更新
#sample makefile script CC=gcc OBJS=fun1.o fun2.o main.o EXEC=test
Makefile隐式规则
Linux
由于make有自动推导的功能,所以隐式的规则可以让程序员比较简略 地书写Makefile。 make在解释Makefile时,若目标是.o文件,那么他会自动的去寻找相 应的.c文件, 并隐式的进行编译。
Makefile隐式规则 - 简化2
#sample makefile script CC=gcc OBJS=fun1.o fun2.o main.o EXEC=test
Makefile文件的命名可以为“Makefile"或"makefile"。
如果使用非标准命名的makefile,必须用命令开关"-f" 或 “-file”。 参数 “-f <name>” 或 “--file <mane>”告诉make 读入name 作 为makefile文件。
Makefile的好处
编译器类型 编译选项, 通常为-O2 -Wall -I -L 额外链接库 应用程序名 源代码 目标文件
Makefile通用版(基本版)
# makefile example CC=gcc CFLAGS = -Wall -O2 CFLAGS += -I./ -L./ LFLAGS = -lpthread -lm SRCS = fun1.c \ fun2.c \ main.c
Makefile的命名及执行方式
Linux
使用make命令执行Makefile文件。 在默认情况下,make会执行当前目录下的Makefile文件。若当 前目录下找不到相关的Makefile文件,则会出现错误: make: *** No targets specified and no makefile found. Stop.
Makefile的规则(命令)
Linux
规则解释如何编译文件,make根据依赖关系执行产生或更新目标;规 则也说明如何和何时执行动作。有的规则看起来很复杂,但都符合下 述模式。
<target>:<depend> command1 command2
……
target是一个目标文件,可以是可执行文件或.o文件,也可以是执行动作。
Makefile的规则练习
#makefile rule example A:B @echo "A" B:C @echo "B" C:D @echo "C" D: @echo "D" G:
Linux
@echo "G"
分别执行make、make B、make G。 查看结果,并分析结果。
Makefile自动检测更新
编译思考
Linux
对于庞大的工程项目,比如内核源码中存在成千上万个源文件, 那么编译的时候,如何实现自动化编译,即源头文件与头文件 或者静、动态库之间找到彼此的依赖关系进行编译,最终生成 目标文件。 大多数的Winodws的程序员不需要深入了解自动化编译流程,因 为Windows的IDE(Integrated Development Environment)已经做 了相关的工作,比如VC,VB等。而Linux下没有这样的IDE,通常 需要程序员做用脚本自行书写。 要做一个好的professional程序员,尤其是linux程序员,至少 需要懂得设计该脚本 - Makefile。
Linux
all:$(OBJS) $(CC) $(OBJS) -o $(EXEC) fun1.o: fun2.o: main.o:
clean: rm -rf $(EXEC)
简化2: 使用隐式规则,目标文件为.o文件,make自动推导搜索.c文件,并编译。
Makefile隐式声明 - 简化3
#sample makefile script CC=gcc OBJS=fun1.o fun2.o main.o EXEC=test
Linux
Makefile带来的好处——“自动化编译”,一旦写好,只需要 一个make命令,整个工程完全自动编译,极大的提高了软件开 发的效率。 另一个好处,某工程有10万个源文件,如果其中某一个源文件 发生改变,不需要重新编译整个工程,但是我们生成应用程序 前需要将所有的源文件生成.o文件。makefile会根据文件更新 时间而判断,是否需要重新编译源文件成.o文件,在生成应用 程序时,只需要将所有的.o文件做链接即可。
注释: Makefile注释使用"#",若Makefile需要用到“#”,则需要做 转义“\#”。
Makefile的组成
#sample makefile script include other.make
注释
Linux
文件指示,包含其他文件,其他文件中的变量会被包含进来
CC=gcc
SRCS=fun1.c fun2.c main.c EXEC=test
CC,SRCS,EXEC为变量,都是字符串,使用时会完全被替 换。
makefile命令部份,变量在被引用时需要加上$()或者${}
all: $(CC) $(SRCS) -o $(EXEC)
Makefile与程序或其它脚执行顺序一样,都是自上到下。 引用未定义的变量时,不会出错,但其值为空,即什么都没有。
Linux
all:$(OBJS) $(CC) $(OBJS) -o $(EXEC) clean: rm -rf $(EXEC)
简化3: 使用隐式规则,目标的依赖为三个.o文件,fun1.o, fun2.o,main.o, make自动推导,找到相应.c文件生成找到.o文件。
Makefile的变量替换
Makefile的介绍
认识Makefile和make。
Linux
Makfile是一种纯文本的编译脚本,在其中可以指定需要编译哪 些文件,哪些先编译,哪些后编译,哪些需要重新编译,最终 需要生成怎么样的应用程序。
make是一种命令,它用来解释Makefile脚本,并根据脚本中的 指定内容,进行操作。
Linux
EXEC=test
all:$(OBJS) $(CC) $(OBJS) -o $(EXEC) clean: rm -rf $(EXEC)
Makefile的变量追加
Linux
在定义一个变量之后,我们可以继续在变量后面加上新的值。 追加的语法与C语言中复合运算的“+=”类似。 如: CFLAGS = -Wall CFLAGS += -O2 那么最终CFLAGS的值为 -Wall -O2
Linux
all:$(OBJS) $(CC) $(OBJS) -o $(EXEC) fun1.o:fun1.c $(CC) -c fun1.c fun2.o:fun2.c $(CC) -c fun2.c main.o:main.c $(CC) -c main.c clean: rm -rf $(EXEC)
depend目标的依赖,目标若需要成立,必须有依赖。一个target可以拥有多
个depend 。 command是make执行动作,一个目标依赖关系中可以包含多个命令,但是 每个command不能是空格或者其它的字符,只可以一个制表符Tab键。 注:若target缺少depend ,那么command会直接被执行。
#sample makefile script CC=gcc SRCS=fun1.c fun2.c main.c
Linux
EXEC=test
all: $(CC) $(SRCS) -o $(EXEC) 编写完后,保存,在当前目录下执行make命令,生成可执行程序test
Makefile的组成
Makefile里主要包含了五种类型的语句:
例: SRCS = fun1.c fun2.c main.c OBJS = $(SRCS:.c=.o) 那么变量OBJS值为fun1.o fun2.o main.o
Makefile优化
#sample makefile script CC=gcc SRCS=fun1.c fun2.c main.c OBJS=(SRCS:.c=.o)
Linux
工程若干个源文件中,某一个文件发生了改变,我们希望只重新编译被修改 的那一个文件,其它的文件不重新编译。 make在执行时,会确认所有target是否都是最新的,若target的某一个 depend的时间比target新,那么make会重新根据依赖关系来执行相应的命令。 对于例子中的Makefile,all没有依赖所以命令总是会执行。 这里需要修改 Makefile