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文件语法
Makefile⽂件语法概述本⽂将介绍Makefile种注释、回显、通配符、变量、循环判断、函数注释Makefile中只有单⾏注释,没有多⾏注释,注释以 # 开头。
以下Makefile注释⽚段节选⾃的Makefile# Makefile for installing Lua# See doc/readme.html for installation and customization instructions.# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================# Your platform. See PLATS for possible values.PLAT= noneechoing(回显)通常,make在执⾏命令⾏之前会把要执⾏的命令⾏进⾏输出。
我们称之为“回显”,就好像我们输⼊命令执⾏⼀样。
@如果要执⾏的命令⾏以字符“@”开始,则make在执⾏时这个命令就不会被回显。
典型的⽤法是我们在使⽤“echo”命令输出⼀些信息时。
如:@echo 开始编译XXX模块......当make执⾏时,将输出“开始编译XXX模块......”这个信息。
如果在命令⾏之前没有字符“@”,那么,make的输出就是:echo编译XXX模块......编译XXX模块......“-n”或“--just-print”如果使⽤make的命令⾏参数“-n”或“--just-print”,那么make执⾏时只显⽰所要执⾏的命令,但不会真正的去执⾏这些命令。
只有在这种情况下make才会打印出所有make需要执⾏的命令,其中也包括了使⽤“@”字符开始的命令。
这个选项对于我们调试Makefile⾮常有⽤,使⽤这个选项我们可以按执⾏顺序打印出Makefile中所有需要执⾏的命令。
“-s”或“--slient”make参数“-s”或“--slient”则是禁⽌所有执⾏命令的显⽰,就好像所有的命令⾏均使⽤“@”开始⼀样。
vscode makefile语法
vscode makefile语法Visual Studio Code (VSCode) 支持多种编程语言的语法高亮和智能代码补全,包括 Makefile。
在 VSCode 中,你可以使用以下步骤来配置 Makefile 的语法高亮和智能代码补全:1. 打开 VSCode。
2. 在左侧的资源管理器中,找到并打开你的 Makefile 文件。
3. 点击顶部菜单栏中的 "查看",然后选择 "命令面板"。
4. 在命令面板中输入 "Color Theme",然后选择一个你喜欢的颜色主题。
5. 确保你的 Makefile 文件已经保存,然后按下 `F5` 键,VSCode 将自动检测 Makefile 的语法并启用语法高亮。
6. 在编写 Makefile 时,VSCode 会自动提供智能代码补全功能。
你可以按下 `Ctrl+Space` 键来触发代码补全提示。
如果你想要更深入地自定义 VSCode 的 Makefile 语法高亮和智能代码补全功能,你可以参考以下步骤:1. 打开 VSCode 的设置。
你可以按下 `Ctrl+,` 键来打开设置,或者在左侧的资源管理器中右键点击一个文件或文件夹,然后选择 "Open Settings"。
2. 在设置中,搜索 "Files: Language Mode"。
3. 在 "Files: Language Mode" 设置中,选择 "Editor Config" 或 "File Association"。
如果你选择了 "Editor Config",VSCode 将使用 Editor Config 文件来决定如何解析和显示 Makefile 文件。
如果你选择了 "File Association",VSCode 将使用文件关联来决定如何解析和显示 Makefile 文件。
Makefile 语法分析
Makefile 语法分析第一部分VERSION = 2# 给变量VERSION赋值PATCHLEVEL = 6# 给变量PATCHLEVEL赋值SUBLEVEL = 22# 给变量SUBLEVEL赋值EXTRAVERSION = .6# 给变量EXTRAVERSION赋值NAME = Holy Dancing Manatees, Batman!# 给变量NAME赋值# *DOCUMENTATION*# To see a list of typical targets execute "make help"# More info can be located in ./README# Comments in this file are targeted only to the developer, do not# expect to learn how to build the kernel reading this file.# Do not:# o use make's built-in rules and variables# (this increases performance and avoid hard-to-debug behavour);# o print "Entering directory ...";MAKEFLAGS += -rR --no-print-directory# 操作符“+=”的作用是给变量(“+=”前面的MAKEFLAGS)追加值。
# 如果变量(“+=”前面的MAKEFLAGS)之前没有定义过,那么,“+=”会自动变成“=”;# 如果前面有变量(“+=”前面的MAKEFLAGS)定义,那么“+=”会继承于前次操作的赋值符;# 如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符# 在执行make时的命令行选项参数被通过变量“MAKEFLAGS”传递给子目录下的make程序。
makefile的语法规则
Makefile的语法规则Makefile是GNU构建系统(GNU Build System,简称GNU Make),GNU Make是一个自动化构建工具,用于构建编译程序。
Makefile由一系列语法规则构成,这些规则定义了如何从源文件生成可执行文件或其他目标文件。
基本语法目标:目标是makefile要达到的最终目的,可以是一个可执行程序、一个库文件、一个文档文件等。
依赖:依赖是目标文件所依赖的其他文件,当依赖文件发生变化时,目标文件也需要重新生成。
命令:命令是生成目标文件所需的具体操作,可以是编译、链接、拷贝等。
示例:目标:hello依赖:hello.c命令:gcc -o hello hello.c这条规则定义了如何从源文件hello.c生成可执行文件hello。
当hello.c发生变化时,make会自动执行gcc -o hello hello.c命令重新生成hello可执行文件。
变量变量用于存储信息,变量名以开头,例如:CFLAGS = -Wall -O2这条代码定义了一个名为CFLAGS的变量,值为"-Wall -O2"。
变量可以在命令中使用,例如:目标:hello依赖:hello.c命令:gcc CFLAGS -o hello hello.c这条规则中,CFLAGS变量的值被用在了gcc命令中。
函数函数用于执行特定的任务,函数名以(开头,例如:(info 目标文件是 (TARGET))这条代码定义了一个名为info的函数,当make执行这条代码时,会输出“目标文件是(TARGET)”的信息。
目標:hello依賴:hello.c命令:(CC) (CFLAGS) -o hello hello.cCC = gccCFLAGS = -Wall -O2这条规则重写了上面两个规则。
CC和CFLAGS被定义为变量,并且在命令中使用了这些变量。
当make执行这条规则时,会使用gcc编译器和-Wall -O2编译标志来编译hello.c文件,并将输出的可执行文件命名为hello。
makefile语法格式
Makefile是一种简单的配置文件,用于描述如何编译和链接源代码文件,以及生成可执行文件的过程。
Makefile通常用于C、C++和其他编程语言的项目中。
Makefile的基本语法格式如下:
target: prerequisites
command
其中,target是要生成的目标文件或目录,prerequisites是生成目标文件所需的源文件或目录,command是执行的命令,用于编译和链接源文件生成目标文件。
例如,以下是一个简单的Makefile,它描述了如何将名为“main.c”的C源代码文件编译成可执行文件“main”:
main: main.o
gcc -o main main.o
main.o: main.c
gcc -o main.o main.c
在这个Makefile中,main是目标文件,main.o是其对应的源文件,gcc -o main main.o是执行的命令,用于将main.c编译成main.o文件,然后链接成可执行文件main。
需要注意的是,Makefile中的命令必须以tab键开头,而不是空格键。
同时,Makefile中还可以使用变量、函数、条件判断等高级语法,用于更灵活地描述编译和链接的过程。
Makefile笔记
Makefile笔记一作者:sun_bunny2006-03-09 10:18 星期四阴一、Makefile的规则target ... : prerequisites ...command......target也就是一个目标文件,可以是Object File,也可以是执行文件。
还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。
(任意的Shell命令)prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。
这就是Makefile的规则。
也就是Makefile中最核心的内容。
二、make中需要注意的地方反斜杠(\)是换行符的意思。
这样比较便于Makefile的易读。
我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成执行文件edit。
如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make clean”就可以了。
在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。
这里要说明一点的是,clean不是一个文件,它只不过是一个动作名字,有点像C语言中的label一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就不会自动执行其后所定义的命令。
要执行其后的命令,就要在make命令后明显得指出这个label的名字。
这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。
三、make是如何工作的整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
makefile笔记
makefile笔记Makefile是一个用来组织和管理程序编译和链接的工具。
通过定义一系列规则和命令,我们可以使用Makefile来自动化构建和管理大型项目的编译过程。
本文将介绍Makefile的基本语法和常用命令,以及如何编写一个简单的Makefile文件。
一、Makefile基本语法1. 标准格式Makefile由一系列规则组成,每个规则包含了一个目标(target)、我们想要生成的文件名,以及生成目标所需要的依赖关系(prerequisites)和命令(recipe)。
通常一个规则的基本格式如下:```makefiletarget: prerequisitesrecipes```其中,target是需要生成的文件名,prerequisites是依赖文件,recipes是生成目标所需要执行的命令。
2. 规则的执行原则- 如果target不存在或者target的依赖文件比target更新,那么执行recipes中的命令。
- 如果target的依赖文件有更新,那么也会执行recipes中的命令。
3. 空格和Tab键缩进在Makefile中,空格和Tab键具有不同的含义。
空格用来分隔目标、依赖和命令,而Tab键则用来标识命令行。
因此,在Makefile中,必须使用Tab键来缩进每条命令。
二、Makefile常用命令1. makemake命令是用来执行Makefile中的规则的。
通过运行make命令,可以自动编译和链接项目。
```shellmake target```2. make cleanclean是一个常用的命令,用于清除编译生成的文件。
在Makefile中,我们可以定义一个clean规则,然后通过运行make clean命令来执行清除操作。
```makefileclean:rm -f target```3. make allall是另一个常用的命令,在Makefile中可以定义一个all规则,用于执行整个项目的编译和生成。
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四则运算
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语法格式详解
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我感觉要作一个好的和 professional的程序员,makefile仍是要懂。
这就仿佛此刻有这么多的HTML的编辑器,但若是你想成为一个专业人士,你仍是要了解 HTML的标识的含义。
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是不是具有完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell 脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来讲,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux 下GNU的make。
可见,makefile都成了一种在工程方面的编译方式。
现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。
当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux ,make的版本是。
必竟,这个make是应用最为普遍的,也是用得最多的。
而且其还是最遵循于IEEE 标准的()。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。
makefile 语法
makefile 语法Makefile是一种常用的构建工具,用于自动化构建和管理软件项目。
它是一种文本文件,包含一系列规则,用于指定如何编译、链接和构建源代码。
本文将介绍 Makefile 的语法和使用方法。
一、Makefile 的基本语法Makefile 文件由一系列规则组成,每个规则由一个目标和一个或多个依赖项组成。
目标是要生成的文件名,依赖项是生成目标所需要的文件或命令。
当目标文件不存在或依赖项的时间戳比目标文件的时间戳更晚时,Makefile 将自动执行规则中的命令,生成目标文件。
一个简单的 Makefile 示例:```hello: main.cgcc -o hello main.c```这个 Makefile 包含了一个规则,目标是 hello,依赖项是main.c。
当 main.c 文件的时间戳比 hello 文件的时间戳更晚时,Makefile 将执行 gcc 命令编译 main.c 文件,并生成可执行文件hello。
Makefile 的规则语法如下:```target: dependenciescommand1command2...```其中,target 是规则的目标,dependencies 是规则的依赖项,command1、command2 等是要执行的命令。
命令必须以一个制表符或多个空格开头,否则 Makefile 将无法识别。
二、Makefile 的变量Makefile 中可以定义变量,用于存储常用的值或命令。
变量以$ 符号开头,可以在规则中使用。
变量的定义语法如下:```VARNAME = value```或者```VARNAME := value```其中,等号和冒号加等号的区别在于,等号定义的变量是递归展开的,而冒号加等号定义的变量是简单展开的。
递归展开的变量可以包含其他变量的引用,而简单展开的变量只能包含直接的值。
示例:```CC = gccCFLAGS = -Wall -O2hello: main.c$(CC) $(CFLAGS) -o hello main.c```这个 Makefile 中定义了两个变量 CC 和 CFLAGS,用于存储编译器和编译选项。
cmake makefile使用
cmake makefile使用一、概述CMake和Makefile都是用于管理和构建C/C++项目的工具。
其中,Makefile是Unix/Linux系统下最常用的构建工具之一,而CMake则是一个跨平台的构建工具。
二、Makefile1. Makefile是什么?Makefile是一个文本文件,用于指定如何编译和链接程序。
它包含了编译器需要执行的指令,以及指定源代码文件和目标文件之间的依赖关系。
2. Makefile语法Makefile由一系列规则组成,每个规则包含了以下内容:- 目标文件:需要生成的文件名- 依赖文件:生成目标文件所需要的源代码或其他目标文件- 命令行:生成目标文件所需要执行的命令例如:```target: dependency1 dependency2command1command2```其中,“target”表示目标文件,“dependency1”和“dependency2”表示依赖文件,“command1”和“command2”表示生成目标文件所需执行的命令。
3. Makefile使用方法在Linux系统中,可以使用make命令来读取并执行Makefile中的规则。
make命令会自动检测源代码和目标代码之间的依赖关系,并根据规则自动编译程序。
例如,在当前目录下有一个名为“test.c”的源代码文件,并且在同一目录下有一个名为“Makefile”的文件,其中包含以下规则:test: test.cgcc -o test test.c```则可以使用以下命令来编译程序:```make```4. Makefile的优缺点优点:- Makefile可以自动检测源代码和目标代码之间的依赖关系,只需要编写简单的规则即可。
- Makefile可以在不同的平台上使用,具有很好的可移植性。
缺点:- Makefile语法比较繁琐,需要编写大量的规则。
- Makefile无法自动处理一些复杂的依赖关系,需要手动编写规则。
跟我一起学makefile
Makefile学习教程: 跟我一起写Makefile o0 Makefile概述▪0.1 关于程序的编译和链接o 1 Makefile 介绍▪1.1 Makefile的规则▪1.2 一个示例▪1.3 make是如何工作的▪1.4 makefile中使用变量▪1.5 让make自动推导▪1.6 另类风格的makefile▪1.7 清空目标文件的规则o 2 Makefile 总述▪2.1 Makefile里有什么?▪2.2Makefile的文件名▪2.3 引用其它的Makefile▪2.4 环境变量MAKEFILES▪2.5 make的工作方式o 3 Makefile书写规则▪3.1 规则举例▪3.2 规则的语法▪3.3 在规则中使用通配符▪3.4 文件搜寻▪3.5 伪目标▪3.6 多目标▪3.7 静态模式▪3.8 自动生成依赖性o 4 Makefile 书写命令▪4.1 显示命令▪4.2 命令执行▪4.3 命令出错▪4.4 嵌套执行make▪4.5 定义命令包什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional 的程序员,makefile还是要懂。
这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
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功能
makefileforeach用法
makefileforeach用法Makefile中的foreach用法是用来遍历一个列表,并为每个元素执行一系列的操作。
它的语法如下:$(foreach <var>,<list>,<text>)其中,<var>是一个变量名,<list>是一个以空格分隔的字符串列表,<text>是要执行的一系列操作。
在执行foreach指令时,会将列表中的每个元素分别赋值给<var>,然后执行<text>中的操作。
下面我们来详细了解foreach的用法。
1.基本语法首先,让我们看一个简单的例子,假设我们有一个列表包含a、b和c三个元素,我们想要为每个元素打印一条消息:candidates := a b c$(foreach candidate,$(candidates),$(info Processing candidate: $(candidate)))在这个例子中,我们使用了两个内置函数:$(info ...)用于打印消息,$(foreach ...)用于遍历列表。
执行结果如下:Processing candidate: aProcessing candidate: bProcessing candidate: c2.执行命令除了打印消息,我们也可以使用foreach执行一系列的命令。
例如,假设我们有一个文件列表,我们想要将每个文件复制到一个目标目录中:files := file1.txt file2.txt file3.txtdestination := /path/to/destination/$(foreach file,$(files),cp $(file) $(destination))3.生成目标除了执行命令,我们还可以使用foreach生成目标。
假设我们有一个列表包含源文件的名称,我们想为每个源文件生成一个对应的目标文件:sources := source1.c source2.c source3.cobjects := $(foreach source,$(sources),$(source:.c=.o))在这个例子中,我们使用了一个替换函数$(source:.c=.o),它的作用是将源文件的后缀.c替换为.o。
详解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。
makefile经典教程(学会这些你就是高手了)
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++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Makefile 语法学习有稍稍在Linux 下碰过程序设计的开发者应该会知道,make 是用来将程序代码、函式库、头文件及其它资源文件build 成最终成果(即:最终的应用程序)的超强力辅助工具。
当然了,并不是非得动用到make 才能build 程序,或许有什么程序设计魔人喜欢什么都自己手动进行;但利用make 及其参考档(输入档案)Makefile 将会让整个编译工作轻松许多。
若您曾经打包过Debian Package,那么应该会发现debuan/rule 这个档案的语法和Makefile 几乎是一模一样,所以学习Makefile 的语法对于Debian Package Maintainer 而言也是一门必要的功课。
Makefile语法:以下为Makefile 的基本语法,批注:以# 开头的即为批注。
变量宣告:(有人称之为宏)语法:MACRO = value注意到,在=前后必须加上空白,而变量名称为大小写相异。
利用MACRO = 来取消该变数。
在惯例上,Makefile 内部使用的变量名称使用小写;而使用者很可能从命令行自行另外指定数值的变量,像是CFLAGS,则是使用大写。
在Makefile 中,可利用$(MACRO) 或${MACRO} 来存取已定义的变量。
例:tragets = foo$(targets): common.hgcc -o $(targets) foo.c效果等同:foo: common.hgcc -o foo foo.c:=语法注意到,make 会将整个Makefile 展开后,再决定变数的值。
也就是说,变量的值将会是整个Mackfile 中最后被指定的值。
例:x = fooy = $(x) barx = xyz# y 的值为xyz bar在上例中,y 的值将会是xyz bar,而不是foo bar。
您可以利用:= 来避开这个问题。
:= 表示变量的值决定于它在Makefile 中的位置,而不是整个Makefile 展开后最终的值。
x := fooy := $(x) barx := xyz# y 的值为foo bar在上例中,y 的值将会是foo bar,而不是xyz bar 了。
?=语法:?= 是一个简化的语法:若变量未定义,则替它指定新的值。
否则,采用原有的值。
例:FOO ?= bar若FOO 未定义,则FOO = bar;若FOO 已定义,则FOO 的值维持不变。
+=语法:例:CFLAGS = -Wall -gCFLAGS += -O2此时CFLAGS 的值就变成-Wall -g -O2 了。
define语法:使用define 语法的唯一优点是它可以让变量直接使用『断行』。
例:define foouname -aecho $$SHELLendefall:$(foo)上例可以视同于:foo = uname -a; echo $$SHELLall:$(foo)注意到在上例中使用了$$,让'$' 能传到Shell 中。
在target里另外指定变量的值可以在target 里另外指定变量的值。
例:foo = abcall: foo = xyzall:echo $(foo)# 此时,foo 的值为xyz以下的语法提供了和上例相同的功能:all: override foo = xyzall: export foo = xyzmake 也可以存取环境变量。
例:all:@echo $(CFLAGS)在上例中,虽然在Makefile 里虽然没有指定CFLAGS 的值,但make 会试图以环境变量来代出CFLAGS 的值。
可搭配wildcard 指令在变量里展开* ? [...] 等通配符。
例:objects=$(wildcard *.o)规则:(Rule)指示make 如何进行编译。
主要语法:target: dependencies<Tab>Commands或target: dependencies; Commands<Tab>CommandsRule 指示了make 如何建立target;及何时要重新建立target。
target:所要建立的档案dependencies:相依项目。
make 会据此决定是否要重新编译target。
Commands:建立target 的指令。
在Makefile 里并没有限定Rule 的先后顺序。
但默认上,make 会参考all 这个目标项目,并依据它的dependencies 来决定要建立哪些项目。
若没有all 项目,则会采用Makefile 里的第一个项目。
target:(目标项目)这个项目所要建立的档案,必须以:结尾。
例:foo.o: common.hgcc -c foo.c其中,foo.o 是这个项目要建立的档案;common.h 是相依性的项目/档案;而gcc -c foo.c 则为要产生这个项目所要执行的指令。
make 在编译时,若发现target 比较新,也就是dependencies 都比target 旧,那么将不会重新建立target,如此可以避免不必要的编译动作。
若该项目并非档案,则为fake 项目。
如此一来将不会建立target 档案。
但为了避免make 有时会无去判断target 是否为档案或fake 项目,建议利用 .PHONY 来指定该项目为fake 项目。
例:.PHONY: cleanclean:rm *.o在上例中,若不使用 .PHONY 来指定clean 为fake 项目的话,若目录中同时存在了一个名为clean 的档案,则clean 这个项目将被视为要建立clean这个档案,但clean 这个项目却又没有任何的dependencies,也因此,clean 项目将永远被视为up-to-date,永远不会被执行。
因为利用了 .PHONY 来指定clean 为fake 项目,所以make 不会去检查目录中是否存在了一个名为clean 的档案。
如此也可以提升make 的执行效率。
其它类以 .PHONY 的语法请参考:GNU `make': 4.9 Special Built-in Target Names另外,如果某个非fake 项目里的dependencies 包含了fake 项目的话,因为make 一定会执行fake 项目,这样一来,这个非fake 项目一定也会被执行。
这可能不是理想的做法。
dependencies:(相依性项目,以空白间隔)dependencies 是指定在建立target 之前,必须先检查的项目。
可以不指定。
例:foo.o: common.hgcc -c foo.c上例中是指:检查common.h。
如果它的建立日期比foo.o 新,就执行gcc -c foo.c 来重新产生foo.o。
也就是说,可以依需求建立dependencies,即使它和target 一点关系也没有。
相依性项目可以是Makefile 中其它的target。
也因此,在建立该target 之前,它会先检查在dependencies 里所指定的所有target。
Commands:(即为要执行的Shell 指令)必须以<Tab>开头。
使用Shell Script 语法。
在Makefile 里,只要以<Tab> 开头都将会被视为Shell Script 执行。
每条法则必须写在同一行。
每条Command 会启动一个新的Shell,预设为/bin/sh。
若执行完某条Command 但传回了错误值,make 就会中断执行。
因为每条Command 会启动一个新的Shell,所以有时执行的指令必须写在同一行,像是使用if 来进行条件判断,此时可以用; 来分隔指令。
例:all:if [ -f foo ];then rm foo;fi而以下是错误示范:all:cd subdir; $(MAKE)这时因为make 只会检查最后一个指令的传回值,所以在以上指令中,即使subdir 不存在,但make 并不会因而中断执行,并会继续执行$(MAKE) 指令,而产生了不可预期的结果。
为了避免这个问题,可以利用&& 来检查其中某个指令是否成功执行,再决定是否执行下个指令。
例:all:cd subdir && $(MAKE)特别字符:@:不要显示执行的指令。
-:表示即使该行指令出错,也不会中断执行。
例:.PHONY: cleanclean:@echo "Clean..."-rm *.o因为make 会一行一行将正在执行的Commands 显示在屏幕上,但您可以利用@ 来暂时关闭这个功能。
而make 只要遇到任何错误就会中断执行。
但像是在进行clean 时,也许根本没有任何档案可以clean,因而rm 会传回错误值,因而导致make 中断执行。
我们可以利用- 来关闭错误中断功能,让make 不会因而中断。
隐性法则:在上例中的:foo.o: common.hgcc -c foo.c由于产生foo.o 的指令就是gcc -c foo.c,因此在Makefile 里可以将其简化为:foo.o: common.h此时make 会依据target 的扩展名来猜测该如何编译target。
如此可以让Makefile 更为简洁。
您可以利用【空白指令】来避免make 依据隐性法则而进行编译。
例:foo.o: common.h<Tab>内部变数:$?:代表已被更新的dependencies 的值。
也就是dependencies 中,比tragets 还新的值。
$@:代表tragets 的值。
$<:代表第一个dependencies 的值。
$* : 代表tragets 所指定的档案,但不包含扩展名。
例:print: foo1.c foo2.c foo3.clpr -p $?touch print这样会将foo1.c foo2.c foo3.c 中已有更新的内容印至打印机。
内部函数:您可以在Makefile 使用make 所支持的一些内部函数。
详情请参考:GNU `make': 8 Functions for Transforming Text条件判断:可以在Makefile 中使用以下的条件判断语法。
但由于它们不是rule,所以不可以<Tab> 开头;但其后要执行的指令则必须以<Tab> 开头,make 才会视其为Shell 指令。
ifeq:(检查value1, value2 是否相等)ifeq (value1, value2)...else...endififneq:(提供和ifeq 相反的功能)ifneq (value1, value2)...else...endififdef:(检查variable 变量是否为空的)ifdef variable...else...endififndef:(提供和ifdef 相反的功能)ifdef variable...else....endif引入档案:将外部档案引入Makefile 中。