Makefile 使用总结 - wang_yb - 博客园
makefile的用法
makefile的用法Makefile是一种用于自动化编译程序的工具,它可以根据源代码文件的依赖关系,自动编译出最终的可执行文件。
Makefile的使用可以大大提高程序的开发效率和可维护性,下面我们来详细了解一下Makefile的用法。
一、Makefile的基本语法Makefile的基本语法由一系列规则组成,每个规则由以下几部分组成:1. 目标(Target):表示需要生成的文件名或者是一个伪目标,如clean。
2. 依赖(Prerequisites):表示生成目标所依赖的文件或者是其他目标。
3. 命令(Command):表示生成目标的具体命令。
例如,下面是一个简单的Makefile规则:```hello: main.o hello.ogcc -o hello main.o hello.omain.o: main.cgcc -c main.chello.o: hello.cgcc -c hello.c```这个Makefile规则表示需要生成一个名为hello的可执行文件,它依赖于main.o和hello.o两个目标文件。
生成hello文件的具体命令是gcc -o hello main.o hello.o。
同时,main.o和hello.o两个目标文件分别依赖于main.c和hello.c两个源代码文件,生成它们的具体命令是gcc -c main.c和gcc -c hello.c。
二、Makefile的常用命令1. make:执行Makefile文件,生成目标文件。
2. make clean:删除所有生成的目标文件。
3. make install:将生成的目标文件安装到指定的目录中。
4. make uninstall:卸载已经安装的目标文件。
5. make help:显示Makefile文件中定义的所有规则。
三、Makefile的高级用法1. 变量Makefile中可以定义变量,用于存储一些常用的参数或者路径。
makefile输出总结
makefile输出总结【原创版】目录1.Makefile 简介2.Makefile 的输出3.Makefile 输出的格式4.Makefile 输出的优点5.总结正文1.Makefile 简介Makefile 是一种构建脚本,用于自动化构建和编译软件项目。
它通常包含一系列的规则和指令,用于描述项目的构建过程。
Makefile 最早用于 Unix 系统,但现在已经广泛应用于各种操作系统和编程语言中。
2.Makefile 的输出Makefile 的输出是指在执行 Makefile 后,系统生成的文件或结果。
这些输出通常包括编译后的目标文件、可执行文件和库文件等。
Makefile 的输出可以帮助开发者快速了解项目的构建状态,以便进行调试和测试。
3.Makefile 输出的格式Makefile 的输出格式通常遵循一定的规范,例如在输出文件名前加上“@”符号,表示该文件是由 Makefile 生成的。
另外,Makefile 还可以通过设置输出变量,来控制输出的格式和内容。
4.Makefile 输出的优点Makefile 输出的优点主要体现在以下几个方面:(1)自动化:Makefile 可以自动化执行构建过程,提高开发效率。
(2)可维护性:Makefile 可以将项目的构建过程描述得非常清晰,便于维护和修改。
(3)可扩展性:Makefile 可以通过调用其他脚本和程序,来实现更复杂的构建逻辑。
(4)跨平台性:Makefile 可以在各种操作系统和编程语言中使用,具有一定的通用性。
5.总结总之,Makefile 是一种非常实用的构建脚本工具,可以帮助开发者自动化项目的构建过程,提高工作效率。
python makefile 用法
python makefile 用法Python Makefile可用于自动化编译,构建和测试Python项目。
它是一个命令脚本,帮助程序员在不同的操作系统上拥有相同的构建环境,减少了跨平台应用的开发难度。
本文将详细介绍Python Makefile的使用方法,包括如何创建,配置和使用Makefile,以及常见的Makefile命令和技巧。
创建Python Makefile要创建Python Makefile,您需要使用任何文本编辑器创建一个Makefile文件。
Makefile文件通常命名为Makefile或makefile,并位于项目根目录中。
在Makefile文件中,您需要定义一组规则,以指定每个目标的依赖关系,命令和操作。
以下是一个简单的Makefile示例,用于编译和执行名为myapp.py的Python 应用程序。
```make # Makefile for the myapp Python application# Define the application file APPNAME = myapp.py # Define the Python interpreter PYTHON = python3all: $(PYTHON) $(APPNAME)# Define the clean rule clean: rm -f *.pyc ```在上面的Makefile中,我们定义了两个规则,一个是`all`,另一个是`clean`。
`all`规则定义如何构建我们的应用程序,`clean`规则定义如何清理构建期间生成的文件。
配置Python Makefile在编写Python Makefile时,您需要配置Python解释器和其他环境变量。
以下是一些常见的Makefile变量和用法:- **PYTHON**:Python解释器的命令。
在大多数情况下,它需要设置为python3。
- **PYFLAGS**:Python解释器的选项和参数,例如“-O”(优化),“-m”(运行包的主模块)等。
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的语法及其用法,希望能够帮助读者更好地理解和使用 makefile。
一、makefile 的基本语法makefile 的基本语法包括目标、依赖、命令三个要素。
下面我们来逐一介绍。
1. 目标目标是指要生成的文件,也就是 makefile 的最终输出。
目标通常是一个可执行文件、一个库文件或者一个归档文件。
在 makefile 中,目标通常以文件名的形式出现。
例如:```app: main.c func.c```这里的“app”就是目标。
2. 依赖依赖是指生成目标所需要的文件或者其他目标。
在 makefile 中,依赖通常以文件名的形式出现。
例如:```app: main.c func.c```这里的“main.c”和“func.c”就是依赖。
3. 命令命令是指生成目标所需要执行的命令。
在 makefile 中,命令通常以“TAB”键开头,并且必须与目标或者依赖之间有一个空格。
例如:```app: main.c func.cgcc main.c func.c -o app```这里的命令是“gcc main.c func.c -o app”。
二、makefile 的实例了解了 makefile 的基本语法后,我们来看一个简单的makefile 实例:```app: main.c func.cgcc main.c func.c -o app```这个 makefile 的作用是将“main.c”和“func.c”编译成一个可执行文件“app”。
如果我们在命令行中执行“make”命令,make 就会自动根据 makefile 中的规则来生成目标文件“app”。
三、makefile 的高级语法除了基本语法之外,makefile 还有一些高级语法,如变量、函数、条件语句等。
makefile 用法及搭配
Makefile 是一个用于自动编译和链接的配置文件,它通常用于管理大型项目的编译过程。
Makefile 定义了一系列的规则和依赖关系,用于指定如何生成目标文件。
Makefile 的基本用法如下:1. 定义目标文件:在Makefile 中,每个规则都有一个目标文件,这个目标文件是规则中所有命令的输出文件。
目标文件使用空格分隔,每个目标文件之间用tab 键进行缩进。
2. 定义依赖文件:规则中的依赖文件是生成目标文件所需的文件。
如果没有找到这些依赖文件,规则中的命令将不会被执行。
3. 定义命令:规则中的命令是用来生成目标文件的。
在命令前必须有一个tab 键进行缩进。
在Makefile 中,还可以使用伪目标(phony target)来指定特定的动作或命令,而不需要生成任何文件。
例如,可以使用“clean”作为伪目标,执行清理操作的命令。
下面是一个简单的Makefile 的例子:```makefile# 目标文件:main.omain.o: main.cgcc -c main.c -o main.o# 目标文件:mainmain: main.ogcc main.o -o main```这个Makefile 定义了两个规则:一个是生成main.o 目标文件,另一个是生成main 目标文件。
生成main.o 目标文件需要main.c 文件作为依赖文件,并执行gcc -c main.c -o main.o 命令。
生成main 目标文件需要main.o 文件作为依赖文件,并执行gcc main.o -o main 命令。
使用Makefile 时,需要注意以下几点:1. Makefile 的语法非常简单,但要编写高效的Makefile 需要对项目的结构和依赖关系有深入的了解。
2. Makefile 中的规则必须遵循一定的格式,否则无法正确执行。
3. 在Makefile 中使用变量和条件语句可以提高Makefile 的可读性和灵活性。
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
1:在编译时,编译器只检测语法和函数、变量是否声明如果函数未被声明,编译器会给出一个警告,但可以生成object file2:makefile的规则:如果依赖文件比目标文件新的话或者目标文件不存在,就会执行后续定义的命令这里会比较它们的修改日期如果工程没有编译过,所有c文件都会被编译链接如果只是工程的某几个c文件被修改,那么只编译这几个如果头文件被修改,那么只编译包含头文件的c文件3:make是怎样工作的3.1:读入所有的Makefile读入被include的Makefile在当前目录下面找名字为”Makefile”或”makefile”的文件make 执行时-l后面参数指定的目录3.2初始化文件中的变量3.3:推导隐晦规则,并分析所有规则3.4:为所有的目标文件创建依赖关系链3.3:找第一个目标文件3.4:如果目标文件不存在或者依赖文件比目标文件新,就会执行下一行的命令否则就不会执行下一行的命令而是去寻找依赖文件的依赖3.5:得到新的依赖文件后,由于依赖文件比目标文件新,所以就会执行目标文件中的下一行的命令3.5:所有说目标文件的相关命令是最后被执行的4:清空目标文件的规则伪目标不是文件,无法生成它的依赖文件和决定它是否要执行我们只有显示的指明这个目标才能让其生效.PHONY表明是否有这个文件,这个目标就是一个伪目标.PHONY:cleanclean:-rm edit $(objects)#加上一个减号的含义是:某些文件会出问题但不影响后续操作5:通配符~和HOME$<:所有的依赖集$@:目标集6:文件搜寻:当前目录;也可以在文件前加上路径;VPATH执行的路径,多个路径间用冒号关键字vpath指定不同的文件在不同的目录<pattern>需要包含% 字符vpath <pattern> <dir>vpath <pattern>清除符合模式的文件的搜索目录vpath 清除已经设置好的文件搜索目录7:静态模式<targets...>:<target-pattern...>:<prerq-pattern...>objects = foo.o bar.o$(objects): %.o: %.c#target定义了一系列的目标文件,是目标的一个集合#prerq-pattern是目标的依赖的模式,它是对target-pattern形成的模式在进行一次依赖目标的定义#其计算方法是,取<target-parrtern>模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合自动生成依赖性:为每一个 name.c的文件生成一个 name.d的文件[.d]文件中存放着[.c]文件的依赖关系%.d:%.c@set -e;rm -f $@;\$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@;\rm -f $@.$$$$sed命令的显示:https:///edwardlost/archive/2010/09/17/1829145.html目的:在编译器生成的依赖关系中加入[.d]文件的依赖main.o : main.c defs.h替换为:main.o main.d: main.c defs.h把自动生成的Makefile加入到我们的Makefile中sources = foo.c bar.cinclude $(sources:.c=.d)8:显示命令:命令前加上@则不会显示make 参数-s 则会全面机制参数的显示make -n 或者--just-print 只是显示命令不会执行适合用来调试make -w 在进入每一个子makefile会显示工作目录,-C 参数默认加上-w9:命令的依赖:两条命令之间用分号,而不是单独的两行10:嵌套执行makeSubsys:cd sub && make等同于make -C sub总控的makefile的变量会传递到下面的makefile(如果显示声明)export variable但是不会覆盖下面的makefile,除非加上参数-e如果传递所有的变量export如果不想传递某个变量unexport varible11:变量的定义A=${b} #右侧中的变量并不一定是已经定义好的变量造成的问题是:死锁A:=$(B) #右侧的变量必须是已经定义好的FOO ?= bar #如果左侧的变量已经被定义,则什么都不做,如果没有被定义就会定义A += B 属于变量的追加12:变量替换的两种方法${var:a=b} 例如foo := a.o b.o c.obar := $(foo:.o=.c)${var:%.o:%.c}12:函数的调用语法:${<function> <arguments>}函数名和参数之间用空格隔开,参数之间用逗号13:字符串处理函数$(subst <from>,<to>,<text> )$(patsubst <pattern>,<replacement>,<text> )#$(patsubst %.c,%.o,x.c.c bar.c)$(strip <string> )功能:去掉<string>字串中开头和结尾的空字符$(findstring <find>,<in> )功能:在字串<in>中查找<find>字串$(filter <pattern...>,<text> )以<pattern>模式过滤<text>字符串中的单词,保留符合模式<pattern>的单词。
makefile的使用
makefile的使用一、什么是makefilemakefile是一种用来描述和指导如何编译和构建程序的文件。
它记录了源文件之间的依赖关系和编译规则,通过解析makefile文件,可以自动化地编译和构建程序。
二、为什么要使用makefile使用makefile有以下几个优点:1.自动化编译: makefile可以在编译过程中自动判断哪些文件需要重新编译,从而减少重复编译的时间和工作量。
2.简化构建流程: makefile可以将复杂的构建过程和编译命令封装成一个命令,简化构建流程,提高工作效率。
3.管理项目依赖: makefile可以记录文件之间的依赖关系,当某个文件发生变化时,只需要重新编译与之相关的文件,从而加快构建速度。
4.提高可维护性: makefile使得代码的组织结构更加清晰和可维护,便于团队协作和后续维护。
三、makefile的基本语法makefile的语法较为简单,包括以下几个基本元素:1.目标(target): 目标是构建过程中的一个步骤或者一个文件,并且有依赖关系。
在makefile中,目标通常是一个需要构建的文件,也可以是一个执行命令的动作。
2.依赖关系(prerequisites): 依赖关系是指目标所依赖的文件或者其他目标。
当一个目标的依赖发生变化时,该目标需要重新构建。
3.命令(command): 命令是指构建过程中的具体操作。
在makefile中,每个目标可以指定一个或多个命令,用于构建该目标。
4.变量(variable): 变量是makefile中定义的一个数据容器,用于存储常量或者计算结果。
可以通过引用变量来简化makefile的书写和维护。
5.规则(rule): 规则是指一个目标和其依赖关系的完整定义,包含了目标、依赖关系和命令。
下面是一个简单的makefile示例:# 定义变量CC = gccCFLAGS = -Wall -O2# 定义目标及其依赖关系和命令hello: main.o utils.o$(CC) $(CFLAGS) -o hello main.o utils.o# 定义目标的依赖关系和命令main.o: main.c utils.h$(CC) $(CFLAGS) -c main.cutils.o: utils.c utils.h$(CC) $(CFLAGS) -c utils.c四、makefile的工作流程makefile的工作流程包括以下几个步骤:1.读取makefile文件: make工具会首先读取当前目录下的makefile文件,如果没有找到,则会寻找默认的文件名(GNUmakefile、makefile或Makefile)。
makefile的使用问题总结 (3)
这篇文章将用来陆续整理makefile编写的时候出现的问题和网上找到的一些答案。
0. gcc的常用规则$ gcc -Wall -c hello_fn.c 产生一个 .o 文件(编译)$ gcc main.o hello_fn.o -o hello 产生可执行文件(链接)如果只有一个文件,可以把编译和链接用一个command完成gcc -Wall hello.c -o hello1. 如何在makefile中echoa) 必须在某一个段内,否则会有( commands commence before first target)b) 命令必须以tab开头,否则会有(missing separator)c) @符号不能丢在某个段内,如clearn里:clean:@echo "hello, baidu" ##这一行开头是个TAB符2. 如何让makefile同时支持32和64位ARCH := $(shell getconf LONG_BIT) # 很巧妙,获取long在不同系统上的位数来决定系统的位数CPP_FLAGS_32 := -D32_BIT ... Some 32 specific compiler flags ... CPP_FLAGS_64 := -D64_BITCPP_FLAGS := $(CPP_FLAGS_$(ARCH)) ... all the other flags ...3. 如何配置使用intel 编译器icc 往往会有20%左右的性能提升,当然要看具体的代码。
icc一个顺带的好处是比较不依赖较高版本的libstdc++,所以如果icc编译软件对intel cpu将会有更好的兼容性。
AS = asCC = iccCPP = icpcF77 = f77F9X = gfortranLD = icpcAR = arRANLIB = ranlibWINDRES = windres4. 关于伪目标 .PHONY 目标伪目标就是告诉makefile,并不需要生成真实的文件(真目标)的意思,只要把这个命令跑完就行了,这个可以预防一些因为本地真实存在一个真目标,而且依赖没有更新,而导致自己被忽略不去执行的问题,比如若本地存在一个clean的文件,那若不显式的说明这个clean 是伪目标,他就会被忽略,不被执行到。
makefile学习心得
Makefile学习心得1.Makefile在单一目录下的编译a)Makefile主要运用于工程的管理,使工程能自动按需求来编译,对于单目录来说,可以用非常简单的命令来:目录:依赖(所有的源文件):命令(需要什么就怎么编)b)例程:所有文件都在一个目录下i.all:mkfifo_server mkfifo_clientii..PHONY:alliii.mkfifo_server:mkfifo_server.civ.gcc -o $@ $^v.mkfifo_client:mkfifo_client.cvi.gcc -o $@ $^2.关键在于对多级目录下的各大程序的编译与库的编译与链接问题。
a)对于多级目录下各自编译问题:i.在各源文件目录下编写各源文件的编译Makefileii.在顶层目录下编写的Makefile需要指定各源文件的路径,可以用通配符来表示iii.用$(MAKE) -C进入到各目录分别编译,这里有一个非常重要的技巧那就是make 对目录的并行处理,也就是伪目标的一个重要运用iv.例程:在顶层目录下有socket mkfifo两个目录1.DIR := $(shell pwd)2.SUBDIR := socket mkfifo3..PHONY:all subdir $(SUBDIR)4.all:creat complie subdir $(SUBDIR)5.creat:6.@mkdir -p $(DIR)/socket27.@cp -rf $(DIR)/socket/* $(DIR)/socket2plie:9.@make -C $(DIR)/socket10.#subdir:$(SUBDIR)11.$(SUBDIR):12.$(MAKE) -C $@13.socket:mkfifo14.Socket mkfifo 目录下的Makefile可以参照单目录下的Makefile来写15.特别要注意的一点是一定要声明subdir与$(SUBDIR)为伪目标否则编译只能编译第一个目录b)在不同目录下编译生成库文件,并链接生成可执行文件i.在需要编译成库文件的目录下写源程序,头文件和编译成库的Makefileii.在顶层目录下写主函数用以链接库文件,调用库文件中的函数来执行iii.在顶层目录下编写Makefile,这一层的Makefile主要工作是,设置各目录的路径,可以按照上面的做法用伪目标先进入各目录编译库文件,然后再链接各库生成可执行文件iv.例程:在顶层目录下有一个helloworld子目录,用来编译生成静态库文件1.DIR:=$(shell pwd)2.SUBDIR:=$(DIR)/helloworld3..PHONY:all4.all:subdir main clean5.subdir:6.$(MAKE) -C $(SUBDIR)7.main:main.c8.gcc -o $@ $^ $(SUBDIR)/*.a9.clean:10.cd $(SUBDIR) && rm -rf *.o11.Helloworld目录下的Makefilea)libhello.a:hello.ob)ar rcs $@ $^c)#hello.o:hello.cd)# gcc -c $^ -o $@12.注意:库文件在生成后最用一个变量来表示,此处不再描述,helloworld文件中的Makefile最后两句可以注释掉,make可以利用其隐式规则自动进行推导,动态库的制作与编译链接与静态库差不多,可以照此推导3.Makefile生成动态库a)这个与上面生成静态库的方法有点类似,只是生成动态库的命令有点不同,并且也要指定库文件所在的目录b)例程:与上静态库中一样,只是改为编译成动态库,并在顶层Makefile中将其拷贝到/usr/bin目录下i.DIR:=$(shell pwd)ii.SUBDIR:=$(DIR)/helloworldiii.LIB:=/usr/biniv..PHONY:allv.all:subdir mov main cleanvi.subdir:vii.$(MAKE) -C $(SUBDIR)viii.mov:ix.@cp -rf $(SUBDIR)/*.so $(LIB)x.main:main.cxi.gcc -o $@ $^ $(LIB)/libhello.soxii.clean:xiii.cd $(SUBDIR) && rm -rf *.oxiv.Helloworld目录中的Makefile编写1.libhello.so:hello.o2.gcc -shared -fPIC $^ -o $@3.# ar rcs $@ $^4.#hello.o:hello.c5.# gcc -c $^ -o $@总结: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的流程。
Makefile使用总结
1 概述1.1什么是Makefilemakefile关系到了整个工程的编译规则。
一个工程中的源文件不计其数,并且按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。
可见,makefile成为了一种在工程方面的编译方法。
2 makefile介绍make命令执行时,需要一个makefile 文件,以告诉make命令如何去编译和链接程序。
首先,我们用一个示例来说明makefile的书写规则。
这个示例来源于gnu的make使用手册,在这个示例中,我们的工程有8个c文件,和3个头文件,我们要写一个makefile来告诉make命令如何编译和链接这几个文件。
我们的规则是:1)如果这个工程没有编译过,那么我们的所有c文件都要编译并被链接。
2)如果这个工程的某几个c文件被修改,那么我们只编译被修改的c文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的c文件,并链接目标程序。
只要我们的makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。
2.1 makefile的规则在讲述makefile之前,还是让我们先来粗略地看一看makefile的规则。
gcc与makefile的个人体会
gcc与makefile的使用前段时间学习了vim,现在师兄让我用gcc与makefile文件,很多概论都比较模糊,例如gcc干什么用的?makefile干什么用的?gcc与makefile有什么关系?于是查阅了一些资料,在此做一个小结:gcc与makefile的关系涉及到make,下面是几条1.gcc是编译一个文件,make是编译多个源文件的工程文件的工具。
2.gcc不具有IDE,而是IDE 的后台的编译器,make是一个命令工具,是一个解释makefile 中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的make,Linux下GNU的make。
(在这里我只用过visualC++),可见,makefile都成为了一种在工程方面的编译方法。
3.make就是按照makefile脚本对整个项目的各个文件进行分别编译和链接,makefile基本上就是"目标"(target),"关连"(dependencies) 和"动作"三者所组成的脚本。
makefile 文件是许多编译器--包括Windows NT 下的编译器--维护编译信息的常用方法,只是在集成开发环境中,用户通过友好的界面修改makefile 文件而已。
make除了可以做到编译和连结,也可以把如何产生文档(如manual page, info档及dvi 档) ,以及打包压缩都完成。
4.make 可以说是一个批处理程序,它可以自动编译多个文件。
当然写好的脚本是前提。
MAKE是运用GCC去编译文件的。
5.Makefile文件作为一种描述文档一般需要包含以下内容:◆目标:依赖◆命令他人的总结:gcc就是一个纯编译器而make更牛逼些包括了gcc只有把makefile解决一切ok1、绕路了一开始用gcc时,就会有之前用VC++6.0习惯性的思维(打开vc++6.0,会有个窗口,再在窗口里进行C语言编写);我就试着在终端里把gcc的窗口打开(我输入命令$ gcc <回车>,显示错误),我就开始在网上查,怎么在终端里打开gcc窗口,网上很少有我想要的答案,可能太简单了,没人不会。
makefile 的简单使用方法
makefile 的简单使用方法【最新版3篇】《makefile 的简单使用方法》篇1Makefile 是一个工程文件的编译规则,用于描述整个工程的自动编译和链接的规则。
它可以简单的认为是一个批处理文件,可以自动执行编译、链接等命令。
以下是一个简单的Makefile 的使用方法:1. 创建一个Makefile 文件,通常以.make 为扩展名。
2. 在Makefile 中指定需要编译的源文件和目标文件,以及编译命令和链接命令。
3. 在Makefile 中定义变量,用于存储编译和链接过程中的相关信息,例如编译器路径、目标文件路径等。
4. 在Makefile 中使用条件语句,根据不同的条件来指定不同的编译和链接规则。
5. 在Makefile 中使用include 语句,将多个Makefile 文件包含在一起,以便更好地组织和管理编译规则。
6. 在Makefile 中使用注释,用于说明编译规则的详细信息和用途。
7. 执行Makefile 命令,使Makefile 中的编译和链接规则生效,生成所需的目标文件。
以上是Makefile 的一个简单使用方法,具体的使用方法还需要根据具体的需求进行调整和修改。
《makefile 的简单使用方法》篇2Makefile 是一个工程文件的编译规则,用于描述整个工程的自动编译和链接的规则。
它可以简单的认为是一个批处理文件,可以自动化编译和链接过程,避免手动执行编译和链接命令。
以下是Makefile 的简单使用方法:1. 创建Makefile 文件:在工程目录中创建一个名为“Makefile”的文件,该文件包含工程的编译规则。
2. 编写Makefile 文件:在Makefile 文件中,编写工程的编译规则,包括显式规则、隐晦规则、变量定义、文件指示和注释等。
3. 编译工程:在命令行中进入工程目录,执行“make”命令,Makefile 会自动执行编译和链接命令,生成可执行文件。
makefile的基本用法以及yolov3的makefile解析
makefile的基本用法以及yolov3的makefile解析Makefile的基本用法以及YOLOv3的Makefile解析Makefile是一种用于自动化构建的文件,它定义了一系列规则和依赖关系,用于编译、链接和生成可执行文件等操作。
Makefile通常用于C/C++项目中,但它也可以用于其他编程语言。
一、Makefile的基本用法1. 规则(Rule)Makefile中的规则定义了如何生成目标文件和如何根据依赖关系重新生成目标文件。
一个规则通常由以下几部分组成:target: prerequisites[tab] command- target:目标文件,即要生成的文件。
- prerequisites:目标文件的依赖文件。
- command:生成目标文件的命令。
2. 变量(Variable)Makefile中的变量用于存储值,可以在规则中引用。
常见的变量有以下几种:- CC:C/C++编译器。
- CFLAGS:编译选项。
- LDFLAGS:链接选项。
- RM:删除文件的命令。
可以通过在Makefile中定义变量来方便地修改编译和链接参数,使构建过程更加灵活。
3. 默认规则(Default Rule)Makefile中可以定义一个默认规则,当使用make命令时,会自动执行默认规则中定义的命令。
默认规则的语法如下:.PHONY: allall: target- .PHONY:伪目标,表示该规则是一个伪目标。
- all:默认规则的名字。
- target:默认规则要生成的目标文件。
4. 命令行变量在执行make命令时,可以通过命令行参数传递变量的值。
例如,make CC=gcc可以将CC变量的值设置为gcc。
5. clean规则clean规则用于删除生成的目标文件和其他中间文件,以便重新构建项目。
通常的写法是:clean:[tab] (RM) target这里的(RM)是一个预定义变量,表示删除文件的命令(通常为rm -f)。
详解Makefile函数的语法与使用
详解Makefile函数的语法与使⽤使⽤函数:在Makefile中可以使⽤函数来处理变量,从⽽让我们的命令或是规则更为的灵活和具有智能。
make所⽀持的函数也不算很多,不过已经⾜够我们的操作了。
函数调⽤后,函数的返回值可以当做变量来使⽤。
⼀、函数的调⽤语法函数调⽤,很像变量的使⽤,也是以“$”来标识的,其语法如下:$(<function> <arguments> )或是${<function> <arguments>}这⾥,<function>就是函数名,make⽀持的函数不多。
<arguments>是函数的参数,参数间以逗号“,”分隔,⽽函数名和参数之间以“空格”分隔。
函数调⽤以“”开头,以圆括号或花括号把函数名和参数括起。
感觉很像⼀个变量,是不是?函数中的参数可以使⽤变量,为了风格的统⼀,函数和变量的括号最好⼀样,如使⽤“(subst a,b,(x))”这样的形式,⽽不是“(subst a,b,${x})”的形式。
因为统⼀会更清楚,也会减少⼀些不必要的⿇烦。
还是来看⼀个⽰例:comma:= ,empty:=space:= (empty) (empty)foo:= a b cbar:= (subst (space),(comma),(foo))在这个⽰例中,(comma)的值是⼀个逗号。
(space)使⽤了(empty)定义了⼀个空格,(foo)的值是“a b c”,(bar)的定义⽤,调⽤了函数“subst”,这是⼀个替换函数,这个函数有三个参数,第⼀个参数是被替换字串,第⼆个参数是替换字串,第三个参数是替换操作作⽤的字串。
这个函数也就是把(foo)中的空格替换成逗号,所以$(bar)的值是“a,b,c”。
⼆、字符串处理函数$(subst <from>,<to>,<text> )名称:字符串替换函数——subst。
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无法自动处理一些复杂的依赖关系,需要手动编写规则。
C++学习进阶之Makefile基础用法详解
$(TARGET):$(TESTOBJ) $(LIB) $(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
$(LIB):$(OBJS) $(CXX) -shared $^ -o $@
$(TESTOBJ) $(OBJS):%.o:%.cpp $(CXX) $(CXXFLAGS) $< -o $@
makefile 文件可改为:
TARGET = simpletest OBJS = simple.o simpletest.o
$(TARGET):$(OBJS) g++ $(OBJS) -o $(TARGET)
simple.o:simple.cpp simpletest.o:simpletest.cpp clean:
绝大多数的 IDE 开发环境都会为用户自动编写 Makefile。
Make 是怎么工作的?
Make 工作的原则就是:
一个目标文件当且仅当在其依赖文件(dependencies)的更改时间戳比该目标文件的创建时间戳新时,这个目标文件才需要 被重新编译。
Make 工具会遍历所有的依赖文件,并且把它们对应的目标文件进行更新。编译的命令和这些目标文件及它们对应的依赖文件 的关系则全部储存在 Makefile 中。
Makefile 中也指定了应该如何创建,创建出怎么样的目标文件和可执行文件等信息。
除此之外,你甚至还可以在 Makefile 中储存一些你想调用的系统终端的命令,像一个 Shell 脚本一样使用它。
作用:
Makefile 文件告诉 Make 怎样编译和连接成一个程序
可用命令 dnf install make 安装make功能
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
# Makefile内容 OBJS2 = $(OBJS1) programC.o OBJS1 = programA.o programB.o all: @echo $(OBJS2) # bash中执行 make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使用 $ make programA.o programB.o programC.o
我的标签
linux (63) linux-kernel (30) CLR via C#笔记 (24) C#学习 (9) puppet (8) C#疑难杂症 (7)
prerequisites - 生成 target 所需要的文件或者目标
1. 显示规则 :: 说明如何生成一个或多个目标文件 (包括 生成的文件 , 文件的依赖文件 , 生成的 命令 ) 2. 隐晦规则 :: make的自动推导功能所执行的规则 3. 变量定义 :: Makefile中定义的变量 4. 文件指示 :: Makefile中引用其他 Makefile; 指定 Makefile中有效部分 ; 定义一个多行命 令 5. 注释 :: Makefile只有行注释 "#", 如果要使用或者输出 "#"字符 , 需要进行转义 , "\#"
vpath <pattern> <directories> :: 符合<pattern>格式的文件, 就从<directories>中搜索
3. Re:《Linux内核设计与实…
楼主好,书上说内核中内存不分 页,那么又有主内核页全局目录中的 内核页表,我不太理解 --找尾巴的猫m
4. Re:Django使用心得(一)
Makefile 使用总结 - wang_yb - 博客园
2013年6月 (1) 2013年5月 (3) 2013年4月 (6) 2012年9月 (2) 2012年8月 (4) 2012年7月 (3) 2012年6月 (1) 2012年1月 (1) 2011年12月 (2) 2011年11月 (4) 2011年10月 (2) 2011年9月 (1) 2011年8月 (2) 2011年7月 (9) 2011年6月 (5) 2011年5月 (3) 2011年4月 (9)
测试 :=
# Makefile内容 OBJS2 := $(OBJS1) programC.o OBJS1 := programA.o programB.o all: @echo $(OBJS2) # bash中执行 make, 可以看出 OBJS2 中的 $(OBJS1) 为空 $ make programC.o
[...] :: ex. [abcd] 表示a,b,c,d中任意一个字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表 示 0~9中任意一个数字 ~ :: 表示用户的home目录
积分与排名
积分 - 88238 排名 - 1831
2.1.3 路径搜索
当一个Makefile中涉及到大量源文件时(这些源文件和Makefile极有可能不在同一个目录中), 这时, 最好将源文件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量 VPATH 就 是完成这个功能的. 指定了 VPATH 之后, 如果当前目录中没有找到相应文件或依赖的文件, Makefile 回到 VPATH 指定的 路径中再去查找.. VPATH 使用方法: vpath <directories> vpath <pattern> vpath :: 当前目录中找不到文件时, 就从<directories>中搜索 :: 清除符合<pattern>格式的文件搜索路径 :: 清除所有已经设置好的文件路径
5. Re:Django使用心得(一)
@wang_yb你是工作中用到这 些框架的,还是自己感兴趣自学的? 我是最近在看python的东西看到 的。还不清楚django的应用场 景。... --呆雁
2.2 Makefile 中的变量
2.2.1 变量定义 ( = or := )
OBJS = programA.o programB.o OBJS-ADD = $(OBJS) programC.o # 或者 OBJS := programA.o programB.o OBJS-ADD := $(OBJS) progride
作用是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量
/wang_yb/p/3990952.html
3/19
2015年3月12日
语法: override <variable> = <value> override <variable> := <value> override <variable> += <value>
最新评论
1. Re:C#操作Excel总结
@蜡笔小青不好意思, 我有5, 6 年没搞过windows和excel, 现在有 没有这套环境可以实验了...... --wang_yb
2. Re:C#操作Excel总结
你好,请问下Excel单元格里面 加下拉选项,怎样设置下拉选项的字 体大小,非常感谢,请回复我邮件 吧:379314367@ --蜡笔小青
阅读排行榜
1. C#操作Excel总结(18556) 2. IIS 403错误详细原因(15… 3. C# 连接Oracle(利用OD… 4. Django使用心得(一)(… 5. 深刻理解C#的传值调用和…
评论排行榜
1. C# 连接Oracle(利用OD… 2. Petapoco 连接oracle11…
或者
target ... : prerequisites ; command command ...
*注 * command太长, 可以用 "\" 作为换行符
2.1.2 规则中的通配符
* ? :: 表示任意一个或多个字符 :: 表示任意一个字符
2010年6月 (7) 2010年5月 (9) 2010年4月 (3)
2.2.3 变量追加值 +=
# Makefile内容 SRCS := programA.c programB.c programC.c SRCS += programD.c all: @echo "SRCS: " $(SRCS) # bash中运行make $ make SRCS: programA.c programB.c programC.c programD.c
# 示例1 - 当前目录中找不到文件时, 按顺序从 src目录 ../parent-dir目录中查找文件 VPATH src:../parent-dir # 示例2 - .h结尾的文件都从 ./header 目录中查找 VPATH %.h ./header # 示例3 - 清除示例2中设置的规则 VPATH %.h # 示例4 - 清除所有VPATH的设置 VPATH @呆雁我是工作用uliweb, 这个 也是我粗略比较了django和uliweb 之后选择的.django就是web框架, 和 ROR, MVC等等是一类 的.... --wang_yb
< 日 1 8 一 2 9
2015年3月 二 3 三 4 四 26 5 12 19 26 2 五 27 6 13 20 27 3
> 六 28 7 14 21 28 4
22 23 24 25 10 11
15 16 17 18 22 23 24 25 29 30 31 1
搜索
本篇博客是基于 {精华} 跟我一起写 Makefile 而整理的, 有些删减, 追加了一些示例. 非常感谢 gunguymadman_cu 提供如此详尽的Makefile介绍, 这正是我一直寻找的Makefile中文文档.
javascript学习 (6) C学习 (4) django框架 (4) mono (2) 更多
随笔档案(166)
2015年3月 (1) 2015年2月 (2) 2015年1月 (7) 2014年11月 (1) 2014年10月 (1) 2014年9月 (4) 2014年8月 (3) 2014年7月 (11) 2014年6月 (40) 2014年5月 (7) 2014年4月 (1) 2014年3月 (1) 2014年1月 (6) 2013年12月 (1) 2013年11月 (1) 2013年10月 (1) 2013年9月 (1)
Makefile 使用总结 - wang_yb - 博客园
下面通过一个例子体会 override 的作用:
# Makefile内容 (没有用override) SRCS := programA.c programB.c programC.c all: @echo "SRCS: " $(SRCS) # bash中运行make $ make SRCS=nothing SRCS: nothing ################################################# # Makefile内容 (用override) override SRCS := programA.c programB.c programC.c all: @echo "SRCS: " $(SRCS) # bash中运行make $ make SRCS=nothing SRCS: programA.c programB.c programC.c
2.2.2 变量替换
# Makefile内容 SRCS := programA.c programB.c programC.c OBJS := $(SRCS:%.c=%.o) all: @echo "SRCS: " $(SRCS) @echo "OBJS: " $(OBJS) # bash中运行make $ make SRCS: programA.c programB.c programC.c OBJS: programA.o programB.o programC.o