这是 makepp_scanning 命令,可以使用我们的多个免费在线工作站之一在 OnWorks 免费托管服务提供商中运行,例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器
程序:
您的姓名
makepp_scanning -- makepp 如何查找包含文件和其他隐藏的依赖项
商品描述
Makepp 可以为它知道的某些命令确定其他依赖项或目标
一些有关。 这对于 C/C++ 编译尤其重要,因为它太
手动列出给定源文件所依赖的所有包含文件时容易出错。
通过查看编译命令和源文件本身,makepp 能够
当某些包含文件更改时,准确确定需要重建哪些目标文件。
示例:给定规则
foo.o: # 通常%.o: %.c,只是为了说明
time -p /bin/libtool -bar /usr/bin/cc -c -I 某处 foo.c
makepp 知道必须跳过“time”和“libtool”并且“cc”是实际命令
在这里解析。 它明白 foo.c 是输入文件,因此依赖于
这个规则。 此外,它将扫描该文件以查找包含语句,也在
目录 某处,因为它理解命令选项。
实际上,历史上称为扫描的过程分为三个步骤:
1. 规则动作被拆分成行(连续行计为一个)。 每行
(内置函数和 Perl 块除外)是 词汇上 分析 作为一个或多个 Shell 命令。
重定向被识别为此规则的输入或输出。 每个字的第一个字
查找命令(使用其目录部分,但如果未找到,则再次没有它)以
为它找到一个解析器。 这些成为可选的依赖项,如果可能,它们会被构建,
但如果找不到则忽略,因为 makepp 无法知道复杂命令的哪一部分是
实际上运行。
反引号中的命令被分析但不执行。 (通常执行很重要,
但这将是 makepp 的主要干扰。)避免它们是更好的风格。
相反,通过以这种特殊方式分配命令,让 makepp 最多运行一次命令:
XYZFLAGS ;= $(shell pkg-config --cflags xyz)
目前只有一个词法分析器类可以理解 Bourne Shell。 为了更好
处理 C Shell 或“command.com”,可能会创建子类。 但是,很多语法是
相似到不保证这一点。 如果您想做出贡献,请与我们联系。
2. 已知命令对应 命令 解析器 (也称为解析器)
分析重要的选项和论点。 可用的描述如下。
即使没有找到专门的解析器,通用解析器也会使命令可执行
此规则的输入。 您可以使用 --no-path-executable-dependencies 更改它
命令选项。
3. 如果解析器识别出任何输入文件,它们就会被发送到 扫描器 由...选择
解析器。 它通过查找“#include”或类似的语句来查找进一步的输入。
这是最昂贵的步骤。 所有结果都被缓存以避免重复
不必要地。
如果 makepp 认为它正在编译 C/C++ 源代码但找不到解析器,它会给出一个
警告消息让您知道。 这通常意味着您隐藏了编译器命令
动作太深了,makepp 找不到它。 例如,我见过这样的规则:
%.o: %.c
@echo 现在编译 $<; 晦涩的包装器 gcc -c $< $(CFLAGS) -o $@
这里动作的第一个词是“echo”和“obscure_wrapper”,它们有
没有解析器,所以在这种情况下 makepp 不会扫描包含文件。 你可以忽略
前缀命令:
注册解析器晦涩_包装器跳过字
以下部分记录了内置的解析器和扫描器。 以你的名义
使用“-”与“_”互换。
扫描仪 (解析器)
各种扫描器必须由命令解析器选择,在括号中给出:
C / C ++ 汇编 (c-编译, gcc-编译)
C/C++ 扫描器,无差别地处理这两种语言。 事实上它只看
预处理语句,因此它可以用于很多语言。 解析器
激活它对 gcc 的许多选项有一个特殊的变体,如果
命令名称包括字符串“gcc”或 g++。 如果用 C 编译其他语言
预处理器使用与 C 编译器相同的选项(至少“-I”)然后这个解析器工作
精细。
它查看指定包含路径或“-Ldir”选项的“-Idir”选项的命令
指定链接路径。 然后它扫描任何源文件中的“#include”指令,并
还查看命令行,看看是否有提到的任何源文件或库
没有列为依赖项。 它通过扩展名识别这些。
如果包含在 "#include "file.h"" 中的文件不是
在包含路径中或在包含
文件是“#includ”ing,或在 / usr / include. 如果包含文件,则不会发出警告
用“#include " 未找到。Makepp 假设它在某些系统中,包括
编译器知道的目录,系统中的文件包括目录
不会改变。
此外,文件在 / usr / include, /usr/local/包括, /usr/X11R6/包括,以及任何其他
不扫描不可写的目录以查看它们包含的内容。 Makepp 假设
这些文件不会改变。 (如果您以 root 身份运行,则可写性测试是
使用运行 makepp 的目录的 UID 和 GID 执行。 这是如此编译
以普通用户身份运行程序,然后以 root 身份执行“makepp install”不会导致额外
要扫描的目录。)
这是一个相当简单的扫描仪。 如果你做这样的事情,它会感到困惑:
#ifdef INCLUDE_THIS
#include "this.h"
#ENDIF
因为它不知道预处理器条件。 这通常是无害的; 它
可能会导致额外的额外文件被标记为依赖项(有时会导致
不必要的重建),否则它可能会导致 makepp 警告包含文件不是
成立。 您可以忽略警告消息,也可以将空文件“this.h”输出
那里关闭化妆。
如果你的编译器有一个有趣的名字,你可以说
注册解析器晦涩_c_compiler c 编译
注册解析器晦涩_gcc_alias gcc-compilation
嵌入式 SQL C / C ++ 汇编 (esql-编译)
这些命令,随各种数据库一起提供,预处理特殊部分
否则类似 C/C++ 的源代码,并生成 C/C++ 头文件和源代码。 这将找到 EXEC SQL
INCLUDE "filename" 或 $INCLUDE "filename" 指令。
这些预处理器是公认的: Altibase APRE*C/C++ (打开)、CASEMaker DBMaker
(政协), 火鸟 / InterBase (预)、IBM DB2 (db2 预编译, db2 prep) & Informix
ESQL/C (sql), 安格尔 (sqlc), 密默 (sql), 甲骨文 (进程), PostgreSQL (心电图) & 院子
(码垛机)。 如果你的预处理器不被识别,你可以说
注册解析器晦涩_esqlc_preprocessor esql-compilation
然而,这只会处理 Informix 和其他常见的样式:命令参数
以“.ec”结尾的是要扫描的文件,“-I”定义了包含路径和EXEC SQL
没有后缀的 INCLUDE 指令会附加“.h”。
威格 (啜饮)
Swig(简化的包装器和接口生成器, http://www.swig.org/) 是一个程序
将 C/C++ 头文件转换为使代码可调用所需的包装函数
来自各种其他语言,例如 Perl、Python、Tcl、C#、Ruby、OCaml 和
可能还有一些我不知道的。
Makepp 理解并解析 swig 命令行,寻找“-I”和“-l”选项。
它还知道如何扫描 swig 的接口定义文件(.i 文件)寻找
%include、%import 以及“#include”(如果“-includeall”有效)。
如果你的 swig 有一个有趣的名字,你可以说
注册解析器晦涩_swig_alias swig
维拉 和 的Verilog (vcs_编译)
如果您设计硬件,这将派上用场。
可忽略的 包装 (跳过单词, 贝壳)
Makepp 识别以下命令词和更多并跳过它们
适当地寻找正确的扫描仪:“condor_compile”,“distcc”,
“ignore_error”、“libtool”、“noecho”、“净化”。
有一个变体可以在“sh -c 'command1;”中找到嵌套的命令。
命令2'”。
如果你有更多这样的命令,你可以说
注册解析器命令跳过字
工具
Libtool 是一个非常聪明的编译系统,极大地简化了共享
通过将所有与系统相关的细节隐藏在 shell 脚本中来实现库。 唯一的
难点在于库二进制文件实际上并没有存放在同一个目录中
作为输出文件——libtool 实际上创建了一个子目录“.libs”,其中包含
真实文件。 这通常不是问题,但 makepp 必须知道真正的
二进制文件是如果要将它们从存储库链接。 目前,libtool 库
(“.la”文件)未从存储库链接; 如果需要,它们总是会重建。
另外,makepp目前无法使用存储的依赖信息
在“.la”文件本身内。 这有望很快改变。
压制 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 浏览 (无)
有时您可能不希望解析规则或特定命令。 你可以关掉
解析并扫描
注册解析器 cc 无
有关 配置
快速扫描 和 智能扫描
":quickscan" 和 ":smartscan" 规则选项,如果适用,会影响文件的方式
被扫描。
在 ":quickscan" 模式下(默认),所有包含指令都被假定为活动的。 这允许
用于非常有效的扫描。
在 ":smartscan" 模式下,试图解释宏和表达式,以便
不活动的包含指令将被忽略。 例如,生成的可执行文件
编译以下 C 程序应该 而不去 依赖 foo.h:
#如果 0
#include "foo.h"
#ENDIF
int main() { 返回 0; }
定制 扫描仪
你可以在像 ":parser foo" 这样的规则选项中指定你自己的解析器,或者使用
“register_parser”或“register_command_parser”语句。
无论哪种方式,如“register_parser”中所述,您必须直接或间接地
(通过类)指定一个创建解析器对象的函数。 这个对象通常会
为文件创建一个扫描器对象,并从命令行提供它的发现
选项。 这两个对象将调用解析器的“add_*_dependency”方法,这些方法
将信息转发到稍微复杂的“Mpp::Lexer::add_*_dependency”
效用函数。
但是,您的解析器函数也可以在简单情况下自行完成这项工作。 有一个
如果此函数不返回解析器对象,则有几个特殊的返回值:
“未定义”
扫描信息不可缓存,必须在下次规则目标时重新计算
需要建造。
"p_none, p_skip_word" 或 "p_shell"
这些实际上是数字常量,它们告诉词法分析器完成这些工作
伪解析器。
任何参考,例如“\1”
这相当于返回一个“Mpp::CommandParser”基的解析器对象
类,它只会额外使命令可执行本身成为依赖项。
在大多数情况下,“Mpp::CommandParser”类型的对象应该至少实例化一个对象
类型为“Mpp::Scanner”。 “Mpp::Scanner”基类负责区分
介于快速扫描和智能扫描之间。 请注意,“Mpp::Scanner”的行为可以显着
受这种区别的影响,但如果它是派生类,它应该是透明的
形式良好。 新派生的“Mpp::Scanner”类应该在两种模式下进行测试。
如果您编写自己的“Mpp::Scanner”类,您还应该根据您的重新扫描决定
在构建信息“RESCAN”上。 这在没有签署文件后由“makeppreplay”设置
扫描。 因此,尽管签名是一致的,但仍然需要重新扫描。 如果
您的“Mpp::Scanner”使用继承的“scan_file1”方法,您可能没问题。
有关更多详细信息,请参阅相应的类文档。 有关示例,请参阅
“Mpp::CommandParser::Gcc”和“Mpp::CommandParser::Vcs”。 看看“p_”函数
Mpp/订阅.pm 它们在加载时被别名到它们各自的类中作为“工厂”。
高速缓存 扫描器 info
如果扫描器的所有重要副作用都通过调用方法来实现
“Mpp::CommandParser”基类的,那么这些副作用可以缓存在构建中
info 文件,以便它们可以通过随后的 makepp 调用播放,而无需
完成所有昂贵的扫描工作。 这可以节省相当多的时间,尤其是在
智能扫描模式。
如果扫描器有其他重要的副作用,那么它应该调用“规则”对象的
mark_scaninfo_uncacheable 方法。 否则,从构建中检索的扫描仪信息
信息可能不准确,导致构建结果可能不正确。 这种方法是
当 %parsers 散列中的值不返回类型对象时自动调用
"Mpp::CommandParser",或者当解析器指定了规则选项和 "p_*"
例程不返回“Mpp::CommandParser”类型的对象。
使用类似于用于确定何时的标准使缓存的扫描信息无效
目标已过时。 同样,它可以使用从存储库中检索
与用于确定何时可以从一个目标链接的标准类似
库。
您可以使用“--force-rescan”选项强制 makepp 忽略缓存的扫描仪信息。
当损坏的扫描仪可能导致缓存不正确的扫描仪信息时,这很有用。
Ad 特设 扫描器
通常你只有一个或几个包含依赖信息的文件。 你不
想要将其冗余写入 makefile 中(因为后面的冗余通常会导致
当一个更新被遗忘时的不一致)。 但你也不想写一个
Mpp::扫描仪? 作为一种解决方法,您可以即时生成包含文件。 例如
Qt有 .qrc文件 文件可能如下所示:
美国广播公司
xyz
...
如果你坚持上面的布局,你可以把相关的行变成一个makepp
包含文件,该文件通过被包含自动创建。
%.qrc.makepp: %.qrc
&grep 的! \n!$(词干).cc:! || ! * ! ! && ! \n!!' $(输入)-o $(输出)
include $(wildcard *.qrc) # .makepp 自动附加
Cookbook 中给出了它的几种变体。 缺点是你开始
在阅读 makefile 时构建。 所以 --loop 命令选项不会那么有用
在第一次迭代中。
使用 onworks.net 服务在线使用 makepp_scanning