《GNU make项目管理》笔记--变量与宏(1)

make包含两种语言。第一种语言用来描述工作与必要条件所组成的依存图。第二种语言是宏语言,用来进行文字替换。像

C预处理器,m4以及宏汇编器。

一个变量名称几乎可以由任何字符自称。包括大部分的标点符号,即使空格也可以使用,但应该避免这么做。事实上只有:

、#和=等字符不允许使用在变量名称中。

变量名称是区分大小写的。要取得某个变量的值,请使用$()括住该变量的名称,有一个特例:变量名称若为单一字母(letter)

则可以省略圆括号,所以请直接使用$letter。

你还可以使用花括号来扩展变量,例如${CC}.现代化的makefile多半使用园括号。

当 变量用来表示用户在命令行上或环境中所定义的常数时,习惯上会全部以大写来编写其名称,单词之间以下划线符号_隔开。

至于只在makefile文件中出现的变量,则会全部以小写来编写其名称,单词之间以下划线符号隔开。最后,内含用户自定义

函数的变量以及宏都会以小写来编写其名称,单词之间以破折号-隔开。

#常数

CC := gcc

MKDIR := mkdir -p

#内部变量

sources = *.c

objects = $(subst .c,.o,$(sources))

#函数

maybe-make-dir = $(if $(wildcard $1),,$(MKDIR) $1)

1.变量的类型

make的变量有两种类型:经简单扩展的变量以及经递归扩展的变量

你可以使用:=赋值运算来定义一个经简单扩展的变量:

MAKE_DEPEND := $(CC) -M

之所以称此变量为经简单扩展时因为,一旦make从makefile读进该变量的定义语句,赋值运算符的右边部分会立即被扩展。

赋值运算符的右边部分只要出现make变量的引用就会被扩展,而扩展后所产生的文本则会被存储称该变量的值。此行为跟

大多数的程序和脚本语言相同。举例,此变量被扩展之后一般会成为下面这样:

gcc -M

然而,如果上面的CC变量尚未定义,则此变量被扩展后一般会变成这样:

<space> -M

第二种变量类型称为经递归扩展的变量。你可以用=赋值运算符来定义一个经递归扩展的变量:

MAKE_DEPEND = $(CC) -M

之所以称此变量为经递归扩展是因为,make只会读进赋值运算符右边的部分,并将之存储成该变量的值,但不会进行任何

扩展的动作,扩展动作会被延迟到该变量被使用的时候才进行,将此变量称为延后扩展的变量或许比较恰当。因为扩展动作

会延迟到该变量实际被使用的时候才进行。

MAKE_DEPEND = $(CC) -M

...

#稍后

CC = gcc

这样,当MAKE_DEPEND被使用的使用,即使CC并未定义,MAKE_DEPEND在脚本中的值也会被扩展成gcc -M。

2.其他的赋值类型

make还另外提供了两种赋值运算符:?= 和 +=。

?= 运算符称为附带条件的变量赋值运算符。此运算符只会在变量的值尚不存在的状况下进行变量要求赋值的动作。

#将所产生的每个文件放到$(PROJECT_DIR)/out目录中。

OUTPUT_DIR ?= $(PROJECT_DIR)/out

我们只会在输出目录变量OUTPUT_DIR的值尚不存在的状况下对它进行赋值的动作。

+=运算符通常被称为附件运算符,此运算符会将文本附加到变量中,对于简单变量进行附加的动作,+=运算符可以被实现

成这样:

simple := $(simple) new stuff

但是递归变量会导致一个问题,如果将+=运算符实现成下面这样,是不允许的。

recursive = $(recursive) new stuff

这时一个错误,因为make没有办法妥善地加以处理。如果make存储recursive当前的定义加上new stuff,则make就不能在

运行时再次扩展它。此时试图扩展一个自我引用的递归变量将会产生一个无限循环。

所以,+=被特别实现成可将文本附加到递归变量中并做正确的事。

3.宏

变量适合用来存储单行形式的值,对于多行形式的值,例如命令脚本,如果我们想在不同的地方执行它,该怎么办?例如

下面的命令序列:

ehco create [email protected]

$(RM) $(TMP_DIR)

$(MKDIR) $(TMP_DIR)

$(CC) main.c

$(RM) $(TMP_DIR)

在GNU make中,我们可以通过define指令以创建宏,在make中,宏只是用来定义变量的另一种方式,此变量还可以包含

内置换行符号。

define create-obj

@echo create [email protected]

$(RM) $(TMP_DIR)

$(MKDIR) $(TMP_DIR)

$(CC) main.c

$(RM) $(TMP_DIR)

endef

define指令后面跟着变量名称以及一个换行符号。变量的主体包含了所有的命令序列直到endef关键字出现为止,endef关键字

必须自成一行。一个由define创建的变量,就像任何其他的边来个你一样,会被扩展许多次,除非它被使用在命令脚本的语境

中,下面是宏的使用范例:

$(UI-OBJ):$(UI-CLASSES)

$(create-obj)

请注意,我们为echo命令前置了一个@字符,当执行命令脚本时,前置@字符的命令行不会被make输出,因此,当我们运行

make时,它不会输出echo命令本身,只会输出该命令的输出,如果在宏内部使用@前缀,这个前缀字符只会影响使用到它的

命令行。然而,如果将这个前缀用在宏引用上,则整个宏主体都会被隐藏起来:

$(UI-OBJ):$(UI-CLASSES)

@$(create-obj)

当make运行时只会显示:

$make

create ui-obj...

时间: 2024-10-20 07:12:19

《GNU make项目管理》笔记--变量与宏(1)的相关文章

变量与宏1

转自 http://blog.csdn.net/todd911/article/details/43493847 make包含两种语言.第一种语言用来描述工作与必要条件所组成的依存图.第二种语言是宏语言,用来进行文字替换.像 C预处理器,m4以及宏汇编器. 一个变量名称几乎可以由任何字符自称.包括大部分的标点符号,即使空格也可以使用,但应该避免这么做.事实上只有: .#和=等字符不允许使用在变量名称中. 变量名称是区分大小写的.要取得某个变量的值,请使用$()括住该变量的名称,有一个特例:变量名

关于字符驱动中的变量,宏,头文件等的简介

ssize_t second_drv_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { } 这是一个文件读函数 ssize_t是signed size_t,size_t是标准C库中定义的,应为unsigned int.我们很容易看出输入参数中 file 是文件 buf 是文件要读到什么地方去,用户buf count是要读多少东西 那么ppos是什么东东,是当前文件的偏移量嘛?? 但是当前文件的偏移量在fi

《GNU make项目管理》笔记--规则(2)

1.模式规则 有如下的源代码树: 根目录 |---makefile |----|include| |           |___myutil.h |___|src| |----myutil.c |__main.c 各文件内容如下: main.c: #include <stdio.h> #include "myutil.h" int main(void) { myprint(); return 0; } myutil.h: void myprint(); myutil.c:

《GNU make项目管理》笔记--规则(3)

1.管理程序库 程序库(archive library)是一个特殊的文件,该文件内含其他被称为成员的文件.程序库可用来将相关的目标文件聚集成 较容易操作的单元,例如,C的标准程序库lib.a就包含了许多低级的C函数.因为程序库如此常见,所以make对它们的创建. 维护以及引用提供了特别的支持.程序库的建立及修改可通过ar程序来进行. 下面我们看一个例子,程序包结构如下: 根目录 |---makefile |----|include| |           |___myutil.h |     

变量与宏2

转自 http://blog.csdn.net/todd911/article/details/44237959 1.何时扩展变量 当make在处理递归变量或define指令的时候,会将变量里的每一行或宏的主体存储起来,包括换行符号,但不会予以扩展. 宏定义里的最后一个换行符号并不会被存储称宏的一部分,否则,宏被扩展时make会读进一个额外的换行符号. 当宏被扩展时,make会立即扫描被扩展的文本中是否存在宏或变量的引用,如果存在就予以扩展,如此递归进行下去.如果 宏是在命令脚本的语境中被扩展的

GNU/Linux复习笔记(1)

第一次接触GNU/Linux还是大四上学期实习的那两个月在window里装了 个虚拟机玩红帽的系统,那段时间稍微学了一点命令就不玩了.后来大四下学期认识了王总,装了双系统,那段时间又对linux有了进一步认识并产生了很大的 兴趣.直到上学期突然发疯把笔记本装debian8以后才完全进入linux的世界.学习真的是一个螺旋式上升的过程.下面进入正题: ---Linux的基本原则: 1.由目的单一的小程序组成,组合小程序完成复杂任务(KISS:keep it simple,stupid)2.一切皆文

Gnu make学习笔记

# 单行注释# 多行注释:脚本语言大多是行注释:若想多行注释,建议每行首用#号.可替代方法是行尾续行符,但这样不太好 # Makefile规则结构# target:[prerequisites]# command# 或者# target:[prerequisites]; command# 其中每条command需要以Tab开始,遵从shell语法.如果用";"隔开的话,就不用Tab了# 注意不要轻易以Tab开头,以Tab开头的命令都被交给系统shell去接手了# make后执行的默认是

Sass学习笔记 -- 变量及变量作用域历史遗留问题

sass有两种后缀名文件: 一种后缀名为sass,写选择器时不能使用大括号和分号 一种后缀名为scss,使用大括号和分号 //后缀名为sass的语法,不能出现大括号和分号 $highlight-color: #abcdef .selected   border: 1px $highlight-color solid    //后缀名为scss的语法,跟css一样,需要大括号和分号 $highlight-color: #abcdef; .selected{   border:1px solid $

PMP项目管理笔记 项目定义

项目的定义 项目是为创造独特的产品,服务或成果而进行临时性的工作. 项目是组织的经营需要与战略目标服务的. PMBOK 指南描述的项目管理知识,从本质上讲,是用来管理中等或以上规模,跨部门,跨专业的目的.PMP考试中的项目,通常也是这类项目. 项目的三个特新 1.临时性 2.独特性 3.渐进明细性     项目许多地方需要渐进明细,例如    1.项目的范围    2.项目的计划    3.项目的目标    项目管理特别强调项目的特性和项目的计划都是逐渐细化出来的,因为:     项目的各种情况