Boost C++ Libraries

PrevUpHomeNext

其他

诊断
错误,限制
基本原理

除了通用的错误信息,b2 可能会发出以下信息之一:

warning: unknown rule X

调用了一个未定义为 "actions" 或 "rule" 语句的规则。

using N temp target(s)

已找到标记为临时(但仍然存在)的目标。

updating N target(s)

目标已过期,将更新。

can't find N target(s)

找不到源文件,并且没有操作可以创建它们。

can't make N target(s)

由于找不到源文件,因此无法创建其他目标。

warning: X depends on itself

目标直接或通过其源文件依赖于自身。

don't know how to make X

目标不存在,并且没有定义操作来创建它。

X skipped for lack of Y

源文件构建失败,因此无法构建目标。

warning: using independent target X

使用 $(<)$(>) 引用非其他目标依赖项的目标。

X removed

B2 在中断后删除了部分构建的目标。

要使并行构建成功,必须正确说明文件之间的依赖关系,因为目标倾向于以最快的顺序构建。此外,请注意无法并行的命令,这些命令将固定名称的文件放入当前目录中,例如 yacc(1) 所做的那样。

设置不当的 $(JAMSHELL) 可能会导致静默失败。

本节内容源自官方 Jam 文档以及使用它和阅读 Jambase 规则的经验。我们在这里重复这些信息,主要是因为它对于理解和使用 Jam 至关重要,但没有在一个地方集中起来。其中一些内容完全缺少官方文档。我们希望它对任何希望熟悉 Jam 和 Boost 构建系统的人有用。

  • Jam "rules" 实际上是简单的过程实体。可以将它们视为函数。参数用冒号分隔。
  • Jam target 是一个抽象实体,由一个任意的字符串标识。内置的 DEPENDS 规则在命名目标之间建立依赖关系图中的链接。
  • 请注意,内置 INCLUDES 规则的原始 Jam 文档是不正确的:INCLUDES targets1 : targets2 会导致依赖于 targets1 成员的所有内容都依赖于 targets2 的所有成员。它以一种奇怪的方式做到这一点,即将 targets2 添加到 targets1 中所有内容的依赖项列表中的特殊尾部部分。似乎以这种方式创建循环依赖关系是可以的;实际上,当单个构建操作产生 targets1targets2 时,它似乎是“正确的事情”。
  • 调用规则时,如果存在与规则同名的 actions,则将操作添加到由规则第一个参数标识的目标的更新操作中。如果声明了相应的操作,实际上可以调用未声明的规则:该规则被视为为空。
  • 目标(除了 NOTFILE 目标)通过称为绑定的过程与文件系统中的路径相关联。绑定是一个基于目标特定的 SEARCHLOCATE 变量设置的过程,用于搜索与目标同名的文件(不包含 grist)。
  • 除了局部变量和全局变量外,jam 还允许您在目标上设置变量。目标特定的变量值通常无法读取,并且仅在以下情况下生效:

    • 在更新操作中,首先在由第一个参数命名的目标(正在更新的目标)上查找变量值。因为 Jam 在执行操作之前构建其完整的依赖项树,所以 Jam 规则通过目标特定的变量设置来提供相应的操作的参数。
    • 绑定完全由目标特定的 SEARCHLOCATE 变量设置控制,如这里所述。
    • 在用于头文件扫描的特殊规则中,首先在由规则第一个参数(正在扫描的源文件)命名的目标上查找变量值。
  • 变量的“绑定值”是与变量命名的目标关联的路径。在构建操作中,前两个参数会自动替换为其绑定值。使用 bind 操作修饰符可以选择性地将目标特定变量替换为其绑定值。
  • 请注意,Jam 文档中使用的“绑定”一词表示一个包含三个子阶段的处理阶段:绑定(是的!)、更新确定和头文件扫描。术语“绑定”的重复可能会导致一些混淆。特别是,Jam 文档中的“修改绑定”部分可能应该命名为“修改更新确定”。
  • “Grist”只是一个形式为 <characters> 的字符串前缀。它在 Jam 中用于根据更简单的名称创建唯一的目标名称。例如,文件名 "test.exe" 可能被不同子项目中的目标使用,或者用于“相同”抽象目标的调试和发布版本。绑定到名为“test.exe”的文件的每个不同目标都有自己的唯一 grist 前缀。Boost 构建系统还充分利用了 Jam 将字符串在 grist 边界上分割的能力,有时将多个带有 grist 的元素连接在字符串的开头。使用 grist 代替使用绝对路径来标识目标有两个原因:

    1. 目标的位置不能总是仅从用户在 Jamfile 中输入的内容推断出来,而有时还取决于绑定过程。仍然需要某种机制来明确标识具有相同名称的目标。
    2. Grist 允许我们对每个构建的目标使用统一的抽象标识符,无论目标文件位置如何(如设置 ALL_LOCATE_TARGET 所允许的那样)。
  • 当从名称中提取 grist 时,使用 $(var:G),结果包括前导和尾随尖括号。当使用 $(var:G=expr) 将 grist 添加到名称时,首先会剥离现有的 grist。然后,如果 expr 非空,则根据需要添加前导 <s 和尾随 >s 以形成形式为 <expr2> 的表达式;然后将 <expr2> 放在前面。
  • 当调用 Jam 时,它会将所有环境变量设置导入到相应的 Jam 变量中,然后是所有命令行 (-s...) 变量设置。名称以 PATH、Path 或 path 结尾的变量在特定于操作系统的路径列表分隔符边界上(例如,UNIX 为“:”,Windows 为“;”)被分割成字符串列表。所有其他变量都按空格(“ ”)边界分割。Boost Jam 通过允许对变量进行引用来修改该行为。
  • 值为空列表或完全由空字符串组成的变量具有负逻辑值。因此,例如,以下代码允许一个合理的非空默认值,该默认值可以轻松地被用户覆盖
    MESSAGE ?\= starting jam... ;
    if $(MESSAGE) { ECHO The message is: $(MESSAGE) ; }
    
    如果用户需要特定消息,则使用 "-sMESSAGE=message text" 调用 jam。如果用户不需要消息,则使用 -sMESSAGE= 调用 jam,不会打印任何内容。
  • Jam 中的命令行选项解析可能相当不直观,关于其他 Unix 程序如何接受选项。有两种变体被视为对选项有效:

    1. -xvalue
    2. -x value.

PrevUpHomeNext