本节说明如何扩展 Boost.Build 以满足您的本地需求,主要是添加对您拥有的非标准工具的支持。在开始之前,请确保您已阅读并理解元目标的概念,名为“概念”的部分,这对于理解剩余内容至关重要。
当前版本的 Boost.Build 有三个目标级别,列出如下。
从 Jamfiles 中的声明创建的对象。可以与一组属性一起调用以生成具体目标。
对应于文件或操作的对象。
特定于 Boost.Jam 构建引擎的低级具体目标。本质上是一个字符串——通常是文件名。
在大多数情况下,您只需要处理具体目标和从元目标创建具体目标的过程。扩展元目标级别很少需要。Jam 目标通常仅在命令行模式中使用。
所有与 Boost.Jam 目标相关的内置函数,如 DEPENDS
或 ALWAYS
都作用于 Jam 目标。将它们应用于元目标或具体目标不会产生任何效果。
元目标是一个对象,它记录在 Jamfile 中指定的信息,例如元目标类型、名称、源和属性,并且可以与特定属性一起调用以生成具体目标。在代码级别,它由从 abstract-target 类派生的类的实例表示。 [4]
该 generate 方法获取构建属性(作为 property-set 类的实例)并返回包含以下内容的列表:
作为前端元素——此调用的使用需求(property-set 的实例)
作为后续元素——创建的具体目标(virtual-target
类的实例)
可以使用 targets.resolve-reference
函数通过目标 ID 查找元目标,而 targets.generate-from-reference
函数可以同时查找和生成元目标。
该 abstract-target 类有三个直接派生类
project-target 对应于一个项目,不打算进一步子类化。该 generate 此类的方法构建项目中所有未标记为显式的目标。
main-target 对应于项目中的目标,包含一个或多个目标替代方案。此类也不应该子类化。该 generate 此类的方法选择一个要构建的替代方案,并调用 generate 该替代方案的方法。
basic-target 对应于特定目标替代方案。这是一个基类,有很多派生类。该 generate 方法处理目标要求和请求的构建属性以确定目标的最终属性,构建所有源,最后调用抽象 construct 方法,其中包含源虚拟目标列表和最终属性。
该 project-target 和 main-target 类是隐式创建的——当加载新的 Jamfiles 时,或者当创建具有未知名称的新目标替代方案时。从 basic-target 类派生的类的实例通常在 Jamfile 调用 元目标规则 时创建,例如 exe
。
允许创建从 basic-target 类派生的自定义类,并创建创建此类目标实例的新元目标规则。但是,在大多数情况下,basic-target 的特定子类——typed-target 被使用。该类与一个 类型 相关联,并传递给 生成器 以构建该类型的具体目标。此过程将在下面解释。当声明新类型时,会自动定义新的元目标规则。该规则创建与该类型相关联的新类型目标实例。
具体目标由从 virtual-target
类派生的类的实例表示。最常用的子类是 file-target
。文件目标与创建它的操作相关联——action
类的实例。该操作反过来包含源目标列表。它还包含 property-set 用于该操作的构建属性的实例。
以下是从另一个目标 source
创建目标的示例
local a = [ new action $(source) : common.copy : $(property-set) ] ; local t = [ new file-target $(name) : CPP : $(project) : $(a) ] ;
第一行创建 action
类的实例。第一个参数是源列表。第二个参数是 Jam 级别的 操作。第三个参数是应用于此操作的属性集。第二行创建一个目标。我们指定了一个名称、一个类型和一个项目。我们还传递了之前创建的操作对象。如果该操作创建了多个目标,我们可以多次重复第二行。
在某些情况下,创建具体目标的代码可能会使用相同的属性多次调用。返回对应于相同文件的 file-target
的不同实例显然会导致问题。因此,在返回目标时,您应该通过 virtual-target.register
函数传递它们,除了允许 Boost.Build 跟踪为每个元目标创建了哪些虚拟目标之外,这还会根据需要用之前创建的相同目标替换目标。 [5]以下是一些示例
return [ virtual-target.register $(t) ] ; return [ sequence.transform virtual-target.register : $(targets) ] ;
理论上,Boost.Build 中的每种元目标(如 exe
、lib
或 obj
)都可以通过编写一个新的元目标类来实现,该类独立于其他代码来确定要生成哪些文件以及要使用哪些命令。但是,这将非常不灵活。例如,添加对新编译器的支持需要编辑多个元目标。
在实践中,大多数文件都有特定的类型,大多数工具使用和生成特定类型的文件。为了利用这一事实,Boost.Build 定义了目标类型和 生成器 的概念,并且有特殊的元目标类 typed-target。目标类型只是一个标识符。它与一组对应于该类型的文件扩展名相关联。生成器是工具的抽象。它宣传它生成的类型,并且如果用一组输入目标调用,它会尝试构建宣传类型的输出目标。最后,typed-target 与特定目标类型相关联,并传递该类型的生成器(或生成器)。
生成器是从 generator
类派生的类的实例。该 generator
类本身适用于常见情况。您可以为自定义场景定义派生类。