第七部分 使用变量 (上)

目录

一、变量的基础

二、变量中的变量


  

 在 Makefile 中的定义的变量,就像是 C/C++语言中的宏一样,他代表了一个文本字串, 在 Makefile 中执行的时候其会自动原模原样地展开在所使用的地方。其与 C/C++所不同的 是,你可以在 Makefile 中改变其值。在 Makefile 中,变量可以使用在“目标”,“依赖目 标”,“命令”或是 Makefile 的其它部分中。

        变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有“:”、“#”、“=”或是空字符(空格、回车等)。变量是大小写敏感的,“foo”、“Foo”和“FOO” 是三个不同的变量名。传统的 Makefile 的变量名是全大写的命名方式,但我推荐使用大小 写搭配的变量名,如:MakeFlags。这样可以避免和系统的变量冲突,而发生意外的事情。 有一些变量是很奇怪字串,如“$

一、变量的基础

        变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好 用小括号“()”或是大括号“{}”把变量给包括起来。如果你要使用真实的“$”字符, 那么你需要用“$$”来表示。

        变量可以使用在许多地方,如规则中的“目标”、“依赖”、“命令”以及新的变量中。先

看一个例子:

objects = program.o foo.o utils.o

program : $(objects)

cc -o program $(objects)

$(objects) : defs.h

变量会在使用它的地方精确地展开,就像 C/C++中的宏一样,例如:

foo = c

prog.o : prog.$(foo)

$(foo)$(foo) -$(foo) prog.$(foo)

展开后得到:

prog.o : prog.c

cc -c prog.c

        当然,千万不要在你的 Makefile 中这样干,这里只是举个例子来表明 Makefile 中的变 量在使用处展开的真实样子。可见其就是一个“替代”的原理。

         另外,给变量加上括号完全是为了更加安全地使用这个变量,在上面的例子中,如果你 不想给变量加上括号,那也可以,但我还是强烈建议你给变量加上括号。

二、变量中的变量

        在定义变量的值时,我们可以使用其它变量来构造变量的值,在 Makefile 中有两种方 式来在用变量定义变量的值。

先看第一种方式,也就是简单的使用“=”号,在“=”左侧是变量,右侧是变量的值,右侧 变量的值可以定义在文件的任何一处,也就是说,右侧中的变量不一定非要是已定义好的值, 其也可以使用后面定义的值。如:

foo = $(bar)

bar = $(ugh)

ugh = Huh?

all:

echo $(foo)

        我们执行“make all”将会打出变量$(foo)的值是“Huh?”( $(foo)的值是$(bar), $(bar)的值是$(ugh),$(ugh)的值是“Huh?”)可见,变量是可以使用后面的变量来定义的。

        这个功能有好的地方,也有不好的地方,好的地方是,我们可以把变量的真实值推到后 面来定义,如:

CFLAGS = $(include_dirs) -O

include_dirs = -Ifoo -Ibar

        当“CFLAGS”在命令中被展开时,会是“-Ifoo -Ibar -O”。但这种形式也有不好的地 方,那就是递归定义,如:

CFLAGS = $(CFLAGS) -O

或:

A = $(B) B = $(A)

        这会让 make 陷入无限的变量展开过程中去,当然,我们的 make 是有能力检测这样的定 义,并会报错。还有就是如果在变量中使用函数,那么,这种方式会让我们的 make 运行时 非常慢,更糟糕的是,他会使用得两个 make 的函数“wildcard”和“shell”发生不可预知 的错误。因为你不会知道这两个函数会被调用多少次。

        为了避免上面的这种方法,我们可以使用 make 中的另一种用变量来定义变量的方法。 这种方法使用的是“:=”操作符,如:

x := foo

y := $(x) bar

x := later

其等价于:

y := foo bar

x := later

值得一提的是,这种方法,前面的变量不能使用后面的变量,只能使用前面已定义好了的变 量。如果是这样:

y := $(x) bar

x := foo

那么,y 的值是“bar”,而不是“foo bar”。

        上面都是一些比较简单的变量使用了,让我们来看一个复杂的例子,其中包括了 make 的函数、条件表达式和一个系统变量“MAKELEVEL”的使用: ifeq (0,${MAKELEVEL})

cur-dir := $(shell pwd)

whoami := $(shell whoami)

host-type := $(shell arch)

MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}

endif

        关于条件表达式和函数,我们在后面再说,对于系统变量“MAKELEVEL”,其意思是, 如果我们的 make 有一个嵌套执行的动作(参见前面的“嵌套使用 make”),那么,这个变 量会记录了我们的当前 Makefile 的调用层数。

        下面再介绍两个定义变量时我们需要知道的,请先看一个例子,如果我们要定义一个变 量,其值是一个空格,那么我们可以这样来:

nullstring :=

space := $(nullstring) # end of the line

nullstring 是一个 Empty 变量,其中什么也没有,而我们的 space 的值是一个空格。因为 在 操作符的右边是很难描述一个空格的,这里采用的技术很管用,先用一个 Empty 变量来 标明变量的值开始了,而后面采用“#”注释符来表示变量定义的终止,这样,我们可以定 义出其值是一个空格的变量。请注意这里关于“#”的使用,注释符“#”的这种特性值得我们注意,如果我们这样定义一个变量:

dir := /foo/bar # directory to put the frobs in

dir 这个变量的值是“/foo/bar”,后面还跟了 4 个空格,如果我们这样使用这样变量来指 定别的目录——“$(dir)/file”那么就完蛋了。

还有一个比较有用的操作符是“?=”,先看示例:

FOO ?= bar

其含义是,如果 FOO 没有被定义过,那么变量 FOO 的值就是“bar”,如果 FOO 先前被定义 过,那么这条语将什么也不做,其等价于:

ifeq ($(origin FOO), undefined)

FOO = bar

endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/601431.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DDoS攻击的多种方式

DDOS攻击指分布式拒绝服务攻击,即处于不同位置的多个攻击者同时向一个或数个目标发动攻击,或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者同时实施攻击。由于攻击的发出点是分布在不同地方的,这类攻击称为分布式拒绝服务…

leetcode:2451. 差值数组不同的字符串(python3解法)

难度&#xff1a;简单 给你一个字符串数组 words &#xff0c;每一个字符串长度都相同&#xff0c;令所有字符串的长度都为 n 。 每个字符串 words[i] 可以被转化为一个长度为 n - 1 的 差值整数数组 difference[i] &#xff0c;其中对于 0 < j < n - 2 有 difference[i]…

C# 路径搜索算法 A* 算法 和 Dijkstra 算法

A*算法和Dijkstra算法是两种常用的路径搜索算法&#xff0c;用于在图形结构中寻找最短路径。它们都属于单源最短路径算法&#xff0c;可以用于解决各种寻路问题。 A算法是一种启发式搜索算法&#xff0c;同时考虑了实际移动代价和估计距离代价&#xff0c;通过估计代价来指导搜…

【unity小技巧】FPS游戏实现相机的偏移震动、武器射击后退和后坐力效果

最终效果 文章目录 最终效果前言相机偏移震动相机震动脚本换弹节点震动 武器射击后退效果武器后坐力效果完结 前言 关于后坐力之前其实已经分享了一个&#xff1a;FPS游戏后坐力制作思路 但是实现起来比较复杂&#xff0c;如果你只是想要简单的实现&#xff0c;可以看看这个&…

JAVA计算组合数

JAVA计算组合数 /*** 计算组合数&#xff0c;即C(n, m) n!/((n-m)! * m!)* param n* param m* return*/public static long combination(int n, int m) {return (n > m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;}

ROS OpenCV 级联分类器

Haar级联分类器、HOG级联分类器和LBP级联分类器都是计算机视觉中用于目标检测的特征提取与分类方法&#xff0c;它们各自利用不同的图像特征进行训练&#xff0c;并且通常结合级联结构来提升实时性。 一、Haar级联分类器 1. 特征描述&#xff1a; Haar特征由Paul Viola和Michae…

使用printJS使网页打印成PDF、网页html结合printJS导出为pdf

先放几个参考链接 感谢&#xff01; Vue使用PrintJS实现页面打印功能_vue print.js 设置打印pdf的大小-CSDN博客 前台导出pdf经验汇总 &#xff08;html2canvas.js和浏览器自带的打印功能-print.js&#xff09;以及后台一些导出pdf的方法_iqc后台管理系统怎么做到导出pdf-CSD…

大创项目推荐 深度学习图像分类算法研究与实现 - 卷积神经网络图像分类

文章目录 0 前言1 常用的分类网络介绍1.1 CNN1.2 VGG1.3 GoogleNet 2 图像分类部分代码实现2.1 环境依赖2.2 需要导入的包2.3 参数设置(路径&#xff0c;图像尺寸&#xff0c;数据集分割比例)2.4 从preprocessedFolder读取图片并返回numpy格式(便于在神经网络中训练)2.5 数据预…

ssm基于JSP的网络游戏交易系统的设计与实现+jsp论文

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;商品管理信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足…

面试题理解深层次的数组名

目录 引言 一&#xff1a;一维数组 举例如下 1.铺垫知识 数组名是数组首元素的地址&#xff0c;但是有两个特殊情况 &#xff08;1&#xff09;sizeof(数组名) &#xff08;2&#xff09;&数组名 2.分析讲解上述代码结果 2.字符数组 举例一如下 1.知识铺垫 …

(三)其他的输入输出

文章目录 getchar();单个字符输入使用&#xff1a; putchar();单个字符输出(自带换行)使用 puts();字符串输出与printf区别使用 gets();后面补充 代码现象 getchar(); 单个字符输入 使用&#xff1a; 变量 getchar(); 例&#xff1a;char a&#xff1b; a getchar(); put…

软件测试之单元测试、系统测试、集成测试知识总结

一、单元测试的概念 单元测试是对软件基本组成单元进行的测试&#xff0c;如函数或一个类的方法。当然这里的基本单元不仅仅指的是一个函数或者方法&#xff0c;有可能对应多个程序文件中的一组函数。 单元也具有一些基本的属性。比如&#xff1a;明确的功能、规格定义&#…

PHP进阶-实现网站的QQ授权登录

授权登录是站点开发常见的应用场景&#xff0c;通过社交媒体一键授权可以跳过注册站点账户的繁琐操作。本文将讲解如何用PHP实现QQ授权登录。首先&#xff0c;我们需要申请QQ互联开发者账号获得APPID和密钥&#xff1b;接着&#xff0c;我们下载QQ官方SDK&#xff1a;PHP SDK v…

【Docker】 Docker 开发注意事项

在使用 Docker 进行开发时,需要注意以确保开发过程顺利和高效: 1. 了解 Docker 基础:在开始之前,了解 Docker 的基本概念,如镜像(Images)、容器(Containers)、仓库(Repositories)和 Dockerfile 的基本语法。 2. 编写清晰的 Dockerfile:Dockerfile 应该清晰、简洁,…

IP地址定位技术的应用及其重要性

随着网络技术的快速发展&#xff0c;网络安全问题日益凸显&#xff0c;IP地址定位技术在网络安全领域的应用也越来越广泛。本文将介绍IP地址定位技术在网络安全领域的应用及其重要性。 一、IP地址定位技术概述 IP地址定位技术是指通过一定的技术手段&#xff0c;将虚拟网络中的…

关于《码农翻身》一书的读后感以及自己的一些拙见汇总

书籍名称 《码农翻身》 | 刘欣&#xff08;码农翻身&#xff09; 著 | 文章将以问答的形式进行叙述 1.是从什么渠道接触到《码农翻身》的 一个工作日的下午&#xff0c;手上的任务基本结束&#xff0c;翻了翻桌上的书和笔记之类的&#xff0c;同事见我在看书&#xff0c;于是向…

Java 标准注解和元注解

Java 标准注解 Java 1.5开始自带的标准注解&#xff0c;包括Override、Deprecated和SuppressWarnings&#xff1a; Override&#xff1a;表示当前的方法定义将覆盖父类中的方法Deprecated&#xff1a;表示代码被弃用&#xff0c;如果使用了被Deprecated注解的代码则编译器将发…

华为云服务介绍(二)

在 华为云服务介绍(一) 中我们看到华为云提供了一系列的云服务,包括计算、存储、网络、数据库、安全等方面的解决方案。通过灵活的系统架构设计,可以充分利用这些云服务技术,从而更好地满足用户的需求。 本文从系统架构的角度出发,通过充分利用华为云提供的各种云服务技…

阿里后端实习一面面经

阿里后端实习一面面经 项目中使用到了es&#xff0c;es的作用&#xff1f; elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 es中的重要概念&#xff1f; 群集&#xff1a;一个或多个节点…

PostgreSQL的常见错误和解决方法

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 在学习新的东西时&#xff0c;会犯很多的错误&#xff0c;会遇到很多坑。我们在填坑与犯错中不断进步成长。 以下是在学习pgsql中…