在 Makefile 中,变量是一个名字(像是 C 语言中的宏),代表一个文本字符串(变量的值)。在 Makefile 的目标、依赖、命令中引用变量的地方,变量会被它的值所取代(与 C 语言中宏引用的方式相同,因此其他版本的 make 也把变量称之为“宏”)。在Makefile 中变量有以下几个特征:

  1. Makefile 中变量和函数的展开 (除规则命令行中的变量和函数以外),是在 make读取 makefile 文件时进行的,这里的变量包括了使用“ =”定义和使用指示符“ define”定义的。

  2. 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。

  3. 变量名是不包括“ :”、“ #”、“ =”、前置空白和尾空白的任何字符串。需要注意的是,尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的其它字符可能会在make的后续版本中被赋予特殊含义,并且这样命名的变量对于一些shell来说是不能被作为环境变量来使用的。

  4. 变量名是大小写敏感的。变量“ foo”、“ Foo”和“ FOO”指的是三个不同的变量。 Makefile 传统做法是变量名是全采用大写的方式。推荐的做法是在对于内部定义定义的一般变量(例如:目标文件列表 objects)使用小写方式,而对于一些参数列表(例如:编译选项 CFLAGS)采用大写方式,但这并不是要求的。但需要强调一点:对于一个工程,所有 Makefile 中的变量命名应保持一种风格,否则会显得你是一个蹩脚的程序员(就像代码的变量命名风格一样)。

  5. 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自动化变量。像“ $<”、“ $@”、“ $?”、“ $*”等。

  当我们定义了一个变量之后,就可以在 Makefile 的很多地方使用这个变量。变量的引用方式是:“ $( VARIABLE_NAME)”或者“ ${ VARIABLE_NAME }”来引用一个变量的定义。例如:“ $(foo) ”或者“ ${foo}”就是取变量“ foo”的值。

  美元符号“ $”在 Makefile 中有特殊的含义,所有在命令或者文件名中使用“ $”时需要用两个美元符号“ $$”来表示。

  注意: Makefile 中在对一些简单变量的引用,我们也可以不使用“()”和“ {}”来标记变量名,而直接使用“ $x”的格式来实现,此种用法仅限于变量名为单字符的情况。另外自动化变量也使用这种格式。对于一般多字符变量的引用必须使用括号了标记,否则 make 将把变量名的首字母作为作为变量而不是整个字符串 (“ $PATH”在 Makefile中实际上是“ $(P)ATH”)。这一点和 shell 中变量的引用方式不同。 shell 中变量的引用可以是 “ ${xx}”或者“ $xx”格式。但在 Makefile 中多字符变量名的引用只能是 “ $(xx)”或者“ ${xx}”格式。

  第一种风格的变量是递归方式扩展的变量。这一类型变量的定义是通过“ =”或者使用指示符“ define”定义的。这种变量的引用,在引用的地方是严格的文本替换过程,此变量值的字符串原模原样的出现在引用它的地方。如果此变量定义中存在对其他变量的引用,这些被引用的变量会在它被展开的同时被展开。就是说在变量定义时,变量值中对其他变量的引用不会被替换展开;而是变量在引用它的地方替换展开的同时,它所引用的其它变量才会被一同替换展开。

  为了避免“递归展开式”变量存在的问题和不方便。 GNU make 支持另外一种风格的变量,称为“直接展开”式。这种风格的变量使用“ :=”定义。在使用“ :=”定义变量时,变量值中对其他量或者函数的引用在定义变量时被展开(对变量进行替换)。所以变量被定义后就是一个实际需要的文本串,其中不再包含任何变量的引用。

  GNU make 中,还有一个被称为条件赋值的赋值操作符“ ?=”。被称为条件赋值是因为:只有此变量在之前没有赋值的情况下才会对这个变量进行赋值。

  

  通常,一个通用变量在定义之后的其他一个地方,可以对其值进行追加。这是非常有用的。我们可以在定义时(也可以不定义而直接追加)给它赋一个基本值,后续根据需要可随时对它的值进行追加(增加它的值)。在 Makefile 中使用“ +=”(追加方式)来实现对一个变量值的追加操作。

  通常在执行 make 时,如果通过命令行定义了一个变量,那么它将替代在 Makefile中出现的同名变量的定义。就是说,对于一个在 Makefile 中使用常规方式(使用“ =”、“ :=”或者“ define”)定义的变量,我们可以在执行 make 时通过命令行方式重新指定这个变量的值,命令行指定的值将替代出现在 Makefile 中此变量的值。如果不希望命令行指定的变量值替代在 Makefile 中的变量定义,那么我们需要在 Makefile 中使用指示符“ override”来对这个变量进行声明,变量在定义时使用了“ override”,则后续对它值进行追加时,也需要使用带有“ override”指示符的追加方式。否则对此变量值的追加不会生效。

定义变量的另外一种方式是使用“ define”指示符。它定义一个包含多行字符串的变量,我们就是利用它的这个特点实现了一个完整命令包的定义。

   define”定义变量的语法格式:以指示符“ define”开始,“ endif”结束,之间的所有内容就是所定义变量的值。所要定义的变量名字和指示符“ define”在同一行,使用空格分开;指示符所在行的下一行开始一直到“ endif”所在行的上一行之间的若干行,是变量值。        define two-lines

       echo foo

       echo $(bar)

       endef

  如果将变量“ two-lines”作为命令包执行时,其相当于:

     two-lines = echo foo; echo $(bar)

  使用“ define”定义的变量和使用“ =”定义的变量一样,属于“递归展开”式的变量,两者只是在语法上不同。因此“ define”所定义的变量值中,对其它变量或者函数引用不会在定义变量时进行替换展开,其展开是在“ define”定义的变量被展开的同时完成的。

sds

GNU make使用变量⑤变量的引用、定义等的更多相关文章

  1. 【转】变量的声明和定义,从C到编译原理到C++,再到Java

    基础学了太久,时间一长有些东西就可能记得不太清楚,俗话说得好,"好记性不如烂笔头",所以把基础中的基础-变量的声明和定义,从C到编译原理到C++,再到Java用烂笔头记录下来 最早 ...

  2. PHP 7: PHP 变量和常量的定义

    原文:PHP 7: PHP 变量和常量的定义 本章说说变量的定义.如果对于变量和常量的定义,你会注意几个方面呢?你可能会想到: 如何定义变量,它和C# 等语言有什么不同呢? 变量区分大小写吗? PHP ...

  3. 变量的声明和定义以及extern的用法

    变量的声明和定义以及extern的用法                                          变量的声明不同于变量的定义,这一点往往容易让人混淆. l         变量 ...

  4. 继承的基本概念: (1)Java不支持多继承,也就是说子类至多只能有一个父类。 (2)子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法。 (3)子类中定义的成员变量和父类中定义的成员变量相同时,则父类中的成员变量不能被继承。 (4)子类中定义的成员方法,并且这个方法的名字返回类型,以及参数个数和类型与父类的某个成员方法完全相同,则父类的成员方法不能被继承。 分析以上程

    继承的基本概念: (1)Java不支持多继承,也就是说子类至多只能有一个父类. (2)子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法.(3)子类中定义的成员变量和父类中定义的 ...

  5. 面试题:使用finalkeyword修饰一个变量时,是引用不能变,还是引用的对象不能变?

    /* * 问题:使用finalkeyword修饰一个变量时,是引用不能变,还是引用的对象不能变 * 答: * 使用finalkeyword修饰一个变量时,是指引用变量不能变,引用变量所指向的对象中的内 ...

  6. php面试专题---1、php中变量存储及引用的原理

    php面试专题---1.php中变量存储及引用的原理 一.总结 一句话总结: 查看变量的存储结构可以安装xdebug扩展,用xdebug_debug_zval()方法,不推荐使用memory_get_ ...

  7. Java并发之原子变量和原子引用与volatile

    我们知道在并发编程中,多个线程共享某个变量或者对象时,必须要进行同步.同步的包含两层作用:1)互斥访问(原子性):2)可见性:也就是多个线程对共享的变量互斥地访问,同时线程对共享变量的修改必须对其他线 ...

  8. c#变量缺少using引用,如何快速加上using,加Using的快捷键[bubuko.com]

    在vs的“工具”->“选项”中,左侧树形菜单,“环境”下的“键盘”中设置快捷键. 在“显示命令包含”输入框内输入“显示智能标记”,找到“视图.显示智能标记”,可以看到该命令的快捷键已经分配了2个 ...

  9. php入门变量之变量的间接引用、连接字符串和连接赋值运算符

    [1]变量的间接引用: <?php $a = 'b'; $$a = '123'; echo $b; ?> 上面的输出结果是123 我们可以看到在第二行代码中多了一个$,并通过指定的名称访问 ...

随机推荐

  1. 【工匠大道】svn使用总结

    原文地址 SVN(Subversion)是一个自由.开源的项目源代码版本控制工具.目前,绝大多数开源软件和企业代码管理,都使用SVN作为代码版本管理软件. Subversion将文件存放在中心版本库里 ...

  2. Lind.DDD.Manage项目核心技术分享

    回到目录 关于Lind.DDD.Manager的培训与学习 讲解:张占岭 花名:仓储大叔 主要框架:Lind.DDD,Lind.DDD.Manager 关于Lind.DDD.Manager 由于数据模 ...

  3. 26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做准备,由于许久没有练习双截棍了,难免生疏,所以现在临时抱 ...

  4. linux top命令查看内存及多核CPU的使用讲述

    查看多核CPU命令 mpstat -P ALL  和  sar -P ALL 说明:sar -P ALL > aaa.txt   重定向输出内容到文件 aaa.txt top命令 经常用来监控l ...

  5. 配置文件(App.config文件)

    1. 配置文件概述: 应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的.它是可以按需要更改的,开发人员可以使用配置文件来更改设置,而不必重编译应用程序.配置文件的根节点是 co ...

  6. Entity Framework 中的Code First 中引入数据库函数

    1,在项目中添加CodeFirstStoreFunctions包: Install-Package EntityFramework.CodeFirstStoreFunctions 2,注册注册函数,F ...

  7. keleyi菜单0.1.5版本发布了

    keleyi菜单是一个让你轻松创建向上弹出菜单的jquery插件. 最新版本0.1.5增加了显示三角形的功能,当一级菜单包含有子菜单时,会在一级菜单的右侧显示一个小三角形.如图所示: 查看例子:htt ...

  8. CSS3的自定义动画帧

    CSS3新增的动画帧非常绚丽,可以简单实现一些动画效果,目前除IE外各大主流浏览器都支持 本文演示三个:transform: scale3d(x, y, z)-缩放;.transform: trans ...

  9. 简单介绍JSON

    如下图:

  10. ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave由于鼠标移动速度过快导致问题解决办法

    记录两个项目开发中遇到的问题,一个是ECharts外部调用保存为图片操作,一个是workflow工作流连接曲线onmouseenter和onmouseleave事件由于鼠标移动过快触发问题. 一.外部 ...