makefile 打印变量_[Makefile] 缩进与空格--记录踩过的坑

今天折腾了好久,就为了debug两个makefile的bug。虽然最后找到原因了,但是,怎么说呢,用现在流行的话来说,实在是意难平啊!必须写一篇记录一下!

第一个问题,是个语法高亮问题。今天观察到makefile里一些有缩进的语句,没有被正确的语法高亮,比如下面这样:

d3e81792b60d3dc18d33d7d6ea78e72d.png
看起来没什么毛病……就是变量B怎么不给我高亮?

而正常来说,B应该被识别成变量:

464f1809907722d19780beb276b4ae98.png
正常来说B应该被识别成变量

问题的原因是在写非recipe的时候,缩进应该使用空格而非TAB。在写makefile中的recipe时,因为实际上我们写的是希望shell执行的语句,所以使用的是shell syntax。而make识别recipe的方式就是缩进使用TAB。而其他时候,比如上面的例子中,我们并非在写recipe,这时候syntax应该按照makefile风格来写,所以应当使用空格来缩进。这也正是编辑器对语法高亮识别的方式。

虽然看起来只是语法高亮的问题,但归根结底是make如何识别makefile中语句的问题。错误的缩进可能导致其他问题,比如在下面的例子中:

A

我们的本意是打印B的值,但是执行结果却是打印了一个空行,同时接着一行B=B。这背后的原因,就是B=B这一行使用了TAB来缩进,因此make把这一行也当做recipe的一部分,于是将其交给Shell执行。而除此之外,makefile中没有定义B的值,因此echo打印了一个空行,并且B=B也被打印出来。

d4b1f3d6501b67e851f94c0d2bebdb55.png
Wrong !

可以参考GNU Make 5.1节深入学习recipe syntax问题。

第二个问题看起来就更奇怪一些。出错的代码类似下面这样:

A

看起来打印的结果应该是B,但实际上执行的结果却打印了C:

a962ae41fd93745ad6f2c6673d59ff55.png

3c4dde13a063728ec003e03c7491362b.png

这个问题表面上看非常不可思议。而真正发现问题之后,也让人不禁摇头感叹。这个问题其实上仅仅因为A=A这一行的结尾多了一个空格。所以变量A实际上值是"A "。故而ifeq语句走了else分支。

这种问题知道之后觉得是个非常郁闷,但makefile似乎很难避免这样的问题。因为在makefile中,语句之间没有分隔符号,同时对字符串变量也不需要加引号。在我们日常使用的很多语言中,空格是可以自由添加的,本身不代表任何含义。所以习惯了其他语言语法的我们,面对这种"ghost white space"真的很难发现。我们只能要求维护makefile的同事多留心了。

另外,对于变量来说,实际上=前后是允许有空格的,并且会被忽略掉,不会当做值的一部分。但行尾的空格则相反。

希望以后都不要再debug makefile问题了……愿这篇文章没有更新……

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

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

相关文章

算法设计与分析——贪心算法——背包问题

0-1背包问题: 前提:给定n种物品和一个背包。物品i的重量是Wi,其价值为Vi,背包的容量为C。 问题:应如何选择装入背包的物品,使得装入背包中物品的总价值最大? 背包问题: 与0-1背包问题类似&…

python函数模块化教程_【软件测试教程】Python模块化以及内置模块的使用

一:什么是模块模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py。模块可以被别的程序引入,以使用该模块中的函数等功能。二:模块类型1:自定义模块由编程人员自己写的模块。自定义模块时要注意命名&#xff0…

企业级精致 Blazor 套件 BootstrapBlazor 介绍

BootstrapBlazor1、前言 Blazor 作为一种 Web 开发的新技术已经发展有一段时间了,有些人标称 无 JS 无 TS,我觉得有点误导新人的意味,也有人文章大肆宣传 Blazor 是 JavaScript 的终结者,是为了替代 JavaScript 而生的&#xff0c…

算法设计与分析——贪心算法——最优装载问题

有一批集装箱要装上一艘载重量为c的轮船。其中集装箱i的重量为Wi。最优装载问题要求确定在装载体积不受限制的情况下&#xff0c;将尽可能多的集装箱装上轮船。 #include<iostream> #include<algorithm> #include<cstring> using namespace std;typedef str…

AgileConfig-轻量级配置中心 1.1.0 发布,支持应用间配置继承

AgileConfig轻量级配置中心自第一个版本发布不知不觉已经半年了。在并未进行什么推广的情况下收到了250个star&#xff0c;对我有很大的鼓舞&#xff0c;并且也有不少同学试用&#xff0c;并且给出了宝贵的意见&#xff0c;非常感谢他们。其中有一些意见非常好&#xff0c;但是…

python getopt模块_python之getopt模块使用

实用方向&#xff1a;处理命令行参数的一个方法&#xff0c;简单好用。方法&#xff1a;getopt模块总共有2个函数&#xff0c;分别为&#xff1a;getopt.getoptgetopt.gnu_getopt简单使用&#xff1a;getopt这个函数常用&#xff0c;简单看一下这个函数的使用&#xff1a;getop…

算法设计与分析——贪心算法——多机调度问题

该类问题可以使用贪心策略可以设计出较好的近似算法&#xff08;并不是最优解&#xff09; #include<stdio.h> #include<stdlib.h> #include<iostream> #include<algorithm> using namespace std;typedef struct Node {int hour;//记录该作业的所需要…

如何在 C# 中使用 Dapper ORM

译文链接&#xff1a;https://www.infoworld.com/article/3025784/how-to-use-the-dapper-orm-in-c.html?nsdrtrue对象关系映射&#xff08;ORM&#xff09;这个概念已经存在很长时间了&#xff0c;ORM的作用就是用来解决 编程领域的 object model 和关系数据库中的 data mode…

从像素坐标到相机坐标_鱼眼相机模型EUCM(一)

前言相较于普通的针孔相机&#xff0c;鱼眼相机的能够观测到的范围更广&#xff0c;在一定程度上其实是可以增强视觉的鲁棒性的。针对于鱼眼相机的模型其实有挺多的&#xff0c;也有论文对这些模型进行了评测&#xff0c;但对于本人来说&#xff0c;最熟知的还是针孔模型&#…

GraphQL:简单开开始一个查询

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述&#xff0c;使得客户端能够准确地获得它需要的数据&#xff0c;而且没有任何冗余&#xff0c;也让 API 更容易地随着时间推移而演进&#xff0c…

算法设计与分析——回溯法——批处理作业调度

问题描述&#xff1a;给定n个作业的集合{J1,J2,…,Jn}。每个作业必须先由机器1处理&#xff0c;然后由机器2处理。作业Ji需要机器j的处理时间为tji。对于一个确定的作业调度&#xff0c;设Fji是作业i在机器j上完成处理的时间。所有作业在机器2上完成处理的时间和称为该作业调度…

python输入日期计算天数_用python计算日期(1、返回指定日期所在的一周,2,计算一个日期的月份和天数加减)...

放两个小轮子吧&#xff0c;欢迎测试bug&#xff0c;然后告诉我&#xff1a;1、返回指定日期所在的一周2&#xff0c;计算一个日期的月份和天数加减# -*- coding: utf-8 -*-"""Created on Tue May 17 17:11:28 2016author: pcloth关于日期的计算轮子""…

探索.NET平台中的SIMD内在函数Vector

概述Vector&#xff08;向量&#xff09;是一种序列式容器&#xff0c;事实上和数组差不多&#xff0c;但它比数组更优越。一般来说数组不能动态拓展&#xff0c;因此在程序运行的时候不是浪费内存&#xff0c;就是造成越界。而Vector刚好弥补了这个缺陷&#xff0c;它的特征是…

算法设计与分析——回溯法——装载问题

0027算法笔记——【回溯法】回溯法与装载问题 自己写的代码&#xff1a; #include <iostream> using namespace std; template <class Type> class Loading {//friend Type MaxLoading(Type[],Type,int,int []);//private:public:void Backtrack(int i);int n, …

python功能函数_Python-功能函数的使用

Python中的函数提供了有组织的&#xff0c;可重用的代码来执行一组操作。函数简化了编码过程&#xff0c;防止冗余逻辑&#xff0c;并使代码更容易遵循。定义和调用简单函数使用def语句来定义Python中的函数最常见的方式。这种说法是所谓的单条复合语句的语法如下&#xff1a;d…

深入解析 C# 的 String.Create 方法

作者&#xff1a;Casey McQuillan译者&#xff1a;精致码农原文&#xff1a;http://dwz.win/YVW说明&#xff1a;原文比较长&#xff0c;翻译时精简了很多内容&#xff0c;对于不重要的细枝末节只用了一句话概括&#xff0c;但不并影响阅读。你还记得上一次一个无足轻重的细节点…

算法设计与分析——回溯法——n皇后问题

一、什么是N皇后问题&#xff1f; 在nn格的棋盘上放置彼此不受攻击的n个皇后。按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。n后问题等价于再nn的棋盘上放置n个皇后&#xff0c;任何2个皇后不妨在同一行或同一列或同一斜线上。 问题…

全局程序集缓存gac中安装程序集_我就不信2W字把源码拆的这么碎,你还不明白mybatis缓存...

前言不知道大家看到这张图感觉怎么样&#xff0c;不是难&#xff0c;一共也没有几个组件&#xff0c;但是真的让我想当头疼&#xff0c;因为在面试的时候&#xff0c;就这张图&#xff0c;对&#xff0c;你没看错&#xff0c;就这几个组件&#xff0c;那是让我相当难受啊MyBati…

GraphQL:和EntityFramework更配哦

GraphQL 既是一种用于 API 的查询语言也是一个满足你数据查询的运行时。GraphQL 对你的 API 中的数据提供了一套易于理解的完整描述&#xff0c;使得客户端能够准确地获得它需要的数据&#xff0c;而且没有任何冗余&#xff0c;也让 API 更容易地随着时间推移而演进&#xff0c…

算法设计与分析——回溯法——符号三角形问题

#include<iostream> using namespace std;class Triangle{public:void Backtrack(int t);int n;//第一行的符号个数 int half;//n*(n1)/4 int count;//当前—的个数 int **p;//符号三角形矩阵 long sum; //已找到的符号三角形数 };void Triangle::Backtrack(int t) {if(…