怎么样调试make$(VARIABLE)。再次是使用 $$ 向 shell 传递一个 $ 符号。就是这样,这实际上都非常简单。
默认情况下,make 会打印出它所运行的每个命令,如果有任何命令失败,make 就会停止执行。在某些情况中,可能会出现某个命令看起来失败了,但是我们却希望整个编译过程继续进行。如果一个命令的第一个字符是连字符(-),那么该行中剩余的命令都会执行,不过其退出状态会被忽略。 如果并不希望回显命令,可以在前面加上 @ 符号作为前缀。这是显示消息最常用的方法: 清单 10. 禁止回显
如果没有 @ 符号,这就会产生下面的输出: 清单 11. 没有 @ 的命令
尽管 @ 符号不会真正改变 make 所做的事情,但是这却是一种非常受欢迎的特性。 有些人们非常希望实现的事情却不可移植。但是这些问题也有一些解决办法。 历史上最难解决的一个兼容性问题是在 makefile 中对包含的处理。早先的 make 实现通常都没有提供方法来实现这种功能,但是现代的一些 make 变种似乎看起来都对这个问题进行了妥善处理。GNU make 语法非常简单,即 有些程序可能会简单地要求使用 GNU make,有些则可能要求使用 Berkeley make,还有些可能要求使用 smake。如果需要包含的文件非常多,可以尝试简单指定一个 make 工具,用这个工具编译一个树(在这 3 种以源代码形式发布的可移植 make 工具中,我最喜欢的是 Berkeley make)。 实际上并没有什么好方法来做这件事情。如果使用了一个包含文件,就可能会遇到此文件是否被干净地包含这样的移植性问题。如果在每个文件中都设置了变量,那么就很难全部重载这些变量。如果只在一个顶层文件中设置这些变量,那么子目录中一些独立的编译就会失败,因为还没有设置变量! 根据所使用的 make 版本的不同,一个理想的解决方案是在每个文件中都有条件地设置变量:只有在还没有设置这些变量时才需要进行设置;然后顶层文件中的变化在完全编译时就会影响到所有的子目录。当然,此时如果单独进入一个子目录并运行 make 会产生不同的并且不兼容的结果。 如果所包含的文件不存在,这样做的负面影响就会被放大,那些曾经在 Imake 数千行 makefile 中挣扎过的人都可以证明这点。 有些人提倡另外一种简单的解决方案:根本就不要递归使用 make。对于大部分项目来说,这是绝对可行的,可以急剧简化(并加速)整个编译过程。 Peter Miller 撰写的文章 “Recursive Make Considered Harmful”(请参阅 参考资料)就是一个非常规范的例子。 首先,不要恐慌。开发人员在编写出一个完整的版本之前,可能需要解决很多怪异的 make 问题。隐式规则、没想到的变量替换以及嵌入式 shell 脚本中的语法错误,都可能会引发这种痛苦的享受。 此时需要仔细阅读错误消息。这是 make 自己产生的消息么?还是 make 所调用的东西产生的消息?如果有一个嵌套的编译,可能会需要通过对一组错误消息来仔细进行分析,才能找到确切的错误。 如果一个程序没有找到,首先要检查它是否已经安装了。如果已经安装了,那么就要检查路径设置是否正确;有些开发人员的习惯是在 makefile 中使用绝对路径,这在其他系统上可能会失败。如果将某些东西安装到 /opt 中,而 makefile 引用的却是 /usr/local/bin,那么编译就会失败。此时就需要修改路径的设置。 检查系统时钟;更重要的是,要检查编译树中文件的日期、系统中其他文件的日期以及系统的时钟。在面临输入数据的时间顺序不一致的情况时,make 的行为可能是无害的,也可能是不现实的。如果碰到了时钟问题(例如有些 “新” 文件被标记成 1970 年的),那么就需要修整这个问题了。 “touch” 工具是一个很好的帮手。在时钟问题中产生的错误消息通常都不太明显。 如果看到的错误消息显示有一些语法错误,或者有很多变量没有设置,或设置得不正确,那么可以尝试试验一下其他版本的 make;举例来说,有些程序在使用 gmake 编译时会产生一些非常含糊的错误,而使用 smake 时就能很好地进行编译。有些非常怪异的错误会说明正在使用 GNU make 来运行一个 Berkeley 的 makefile,反之亦然。Linux 特有的程序通常会假设使用 GNU make,使用其他 make 工具可能会碰到莫名其妙的错误,有些甚至在文档中都没有任何提示。 调试标记可能会非常有用。对于 GNU make , 上一篇:Windows 打印管理在Linux 平台实现 下一篇:C 语言中的指针和内存泄漏 更多相关文章
|
推荐文章
精彩文章
|