Boost C++ Libraries

PrevUpHomeNext

特性

通常,我们需要控制传递给被调用工具的选项。这是通过特性来完成的。考虑一个例子

# Declare a new free feature
import feature : feature ;
feature verbatim-options : : free ;

# Cause the value of the 'verbatim-options' feature to be
# available as 'OPTIONS' variable inside verbatim.inline-file
import toolset : flags ;
flags verbatim.inline-file OPTIONS <verbatim-options> ;

# Use the "OPTIONS" variable
actions inline-file
{
    "./inline-file.py" $(OPTIONS) $(<) $(>)
}

我们首先定义一个新的特性。然后,flags 调用表示,每当运行 verbatin.inline-file 操作时,verbatim-options 特性的值将被添加到 OPTIONS 变量中,并且可以在操作体内部使用。您需要查阅联机帮助(--help)以查找 toolset.flags 规则的所有特性。

尽管您可以定义任何一组特性并以任何方式解释其值,但 Boost.Build 建议使用以下编码标准来设计特性。

大多数特性应该有一组固定的值,这些值在它们设计用于工作的工具类别中是可移植的(工具中立)。用户不必为确切的工具调整值。例如,<optimization>speed 对所有 C++ 编译器都有相同的含义,用户不必担心传递给编译器命令行的确切选项。

除了这些可移植特性之外,还有一些特殊的“原始”特性,允许用户在需要时将任何值传递给特定工具的命令行参数。例如,<cxxflags> 特性允许您将任何命令行选项传递给 C++ 编译器。 <include> 特性允许您传递以 -I 开头的任何字符串,并且解释是特定于工具的。(有关此特性的非常智能用法的示例,请参见 名为“我可以使用 Boost.Jam 变量捕获外部程序输出吗?”的部分)。当然,人们应该始终努力使用可移植特性,但这些特性仍然作为后门提供,以确保 Boost.Build 不会夺走用户任何控制权。

使用可移植特性是一个好主意,因为

添加特性的步骤

添加特性需要三个步骤

  1. 声明一个特性。为此,使用“feature.feature”规则。您必须确定特性属性的集合

    • 如果您希望一个目标的特性值集自动传播到其依赖目标,则将其设为“propagated”。

    • 如果一个特性没有固定的值列表,则它必须是“free”。例如,include 特性是一个自由特性。

    • 如果一个特性用于引用相对于 Jamfile 的路径,则它必须是“path”特性。此类特性的值也将自动转换为 Boost.Build 的内部路径表示形式。例如,include 是一个路径特性。

    • 如果特性用于引用某个目标,则它必须是“dependency”特性。

  2. 在目标特定的变量中表示特性值。构建操作是由 Boost.Jam 变量扩展修改的命令模板。toolset.flags 规则将目标特定的变量设置为特性的值。

  3. 使用变量。步骤 2 中设置的变量可用于构建操作中以形成命令参数或文件。

另一个例子

这是一个其他的例子。让我们看看如何创建一个引用目标的特性。例如,在 Windows 上链接动态库时,有时需要指定一个“DEF 文件”,告诉应该导出哪些函数。使用这个文件会很不错

        lib a : a.cpp : <def-file>a.def ;

实际上,此特性已得到支持,但无论如何...

  1. 由于该特性引用了一个目标,因此它必须是“dependency”。

    feature def-file : : free dependency ;
    

  2. 关心 DEF 文件的工具集之一是 msvc。应将其添加到其中。

    flags msvc.link DEF_FILE <def-file> ;
    

  3. 由于 msvc.link 操作未使用 DEF_FILE 变量,因此我们需要将其修改为

    actions link bind DEF_FILE
    {
        $(.LD) .... /DEF:$(DEF_FILE) ....
    }
    

    请注意 bind DEF_FILE 部分。它告诉 Boost.Build 将 DEF_FILE 中的内部目标名称转换为 link 操作中对应的文件名。如果没有它,$(DEF_FILE) 的扩展将是一个奇怪的符号,不太可能对链接器有意义。

    我们快完成了,除了将以下代码添加到 msvc.jam

    rule link
    {
        DEPENDS $(<) : [ on $(<) return $(DEF_FILE) ] ;
    }
    

    这是对 Boost.Build 引擎中错误的一种解决方法,希望有一天能修复它。

变体和复合特性。

有时您想为某些特性集创建一个快捷方式。例如,release<variant> 的一个值,并且是特性集的快捷方式。

可以定义您自己的构建变体。例如

variant crazy : <optimization>speed <inlining>off
                <debug-symbols>on <profiling>on ;

将定义一个具有指定属性集的新变体。您还可以扩展现有变体

variant super_release : release : <define>USE_ASM ;

在这种情况下,super_release 将扩展到 release 指定的所有属性,以及您指定的其他属性。

您不限于仅使用 variant 特性。这是一个定义全新特性的示例

feature parallelism : mpi fake none : composite link-incompatible ;
feature.compose <parallelism>mpi : <library>/mpi//mpi/<parallelism>none ;
feature.compose <parallelism>fake : <library>/mpi//fake/<parallelism>none ;

这将允许您指定特性 parallelism 的值,该值将扩展为链接到必要的库。


PrevUpHomeNext