一个 特性 是构建配置的标准化(工具集无关)方面,例如是否启用内联。特性名称不能包含 '>
' 字符。
构建配置中的每个特性都与一个或多个关联的 值 相关联。非自由特性的特性值不能包含 '<
'、':
' 或 '=
' 字符。自由特性的特性值不能包含 '<
' 字符。
一个 属性 是一个 (特性, 值) 对,表示为 <特性>值。
一个 子特性 是一种仅在其父特性存在时才存在的特性,其标识可以从其值(在其父特性上下文中)推断出来。子特性的父特性永远不能是另一个子特性。因此,特性及其子特性形成一个两级层次结构。
特性 F 的 值字符串 是一种形式为 value-subvalue1-subvalue2
...-subvalueN
的字符串,其中 value
是 F 的合法值,而 subvalue1
...subvalueN
是 F 的一些子特性的合法值。例如,属性 <toolset>gcc <toolset-version>3.0.1
可以使用值字符串更简洁地表示,例如 <toolset>gcc-3.0.1
。
一个 属性集 是一组属性(即不包含重复项的集合),例如: <toolset>gcc <runtime-link>static
。
一个 属性路径 是一组属性,其元素已通过斜杠分隔合并成一个字符串。前一个示例的属性路径表示将是 <toolset>gcc/<runtime-link>static
。
一个 构建规范 是一组属性,它完整地描述了用于构建目标的一组特性。
对于 自由 特性,所有值都是有效的。对于所有其他特性,有效值是明确指定的,并且构建系统将报告使用无效特性值的错误。子属性的有效性可能受到限制,以使某些值仅在存在某些其他子属性的情况下才有效。例如,可以指定属性 <gcc-target>mingw
仅在存在 <gcc-version>2.95.2
的情况下才有效。
每个特性都有一组零个或多个以下属性。特性属性是关于构建系统应如何在构建请求中出现时解释特性的值的低级描述。我们也提到属性的属性,例如,偶然的 属性是其特性具有 偶然的 属性的属性。
偶然的
假定偶然特性不会影响构建产品。因此,构建系统可以使用相同的文件来构建构建规范仅在偶然特性方面不同的目标。控制编译器警告级别的特性是可能存在的偶然特性的一个例子。
非偶然特性假定会影响构建产品,因此构建规范在非偶然特性方面不同的目标的文件将被放置在不同的目录中,如 “目标路径”部分 所述。
这类特性将传播到依赖项。也就是说,如果使用传播属性构建 主目标,构建系统将尝试在构建该主目标的任何依赖项时使用相同的属性。例如,当请求优化可执行文件时,通常希望它与优化库链接。因此,<optimization>
特性被传播。
大多数特性都有一个有限的允许值集,并且在给定的构建规范中只能从该集中取一个值。另一方面,自由特性可以在一次拥有多个值,并且每个值可以是任意字符串。例如,可以同时定义多个预处理器符号
<define>NDEBUG=1 <define>HAS_CONFIG_H=1
可选的
可选特性是在构建规范中不需要出现的特性。每个非可选的非自由特性都具有一个默认值,当目标的要求或用户的构建请求中没有另外指定特性值时,将使用该默认值。[特性的默认值由特性声明中列出的第一个值给出。-- 将此移到其他位置 - dwa]
对称的
通常,特性仅在其值与其默认值不同时才会生成子变体目录,从而导致某些特性的值导致非对称子变体目录结构。对称特性始终会生成相应的子变体目录。
路径
路径特性的值指定路径。该路径被视为相对于使用路径特性的 Jamfile 的目录,并在构建从不同目录调用时由构建系统适当地转换
隐式的
隐式特性的值本身就标识了特性。例如,用户不需要编写 "<toolset>gcc",而是可以简单地编写 "gcc"。隐式特性名称也不会出现在变体路径中,尽管值会出现在变体路径中。因此:bin/gcc/... 与 bin/toolset-gcc/... 相反。通常应该只有几个这样的特性,以避免可能的名称冲突。
复合的
复合特性实际上对应于属性组。例如,构建变体是一个复合特性。当从一组构建属性生成目标时,复合特性会递归展开并 添加 到构建属性集中,因此规则可以根据需要找到它们。在构建属性集中,非复合的非自由特性会覆盖复合特性的组件。
依赖项
依赖项特性的值是目标引用。当用于构建主目标时,依赖项特性的值被视为额外的依赖项。
例如,依赖项特性允许声明库 A 依赖于库 B。因此,每当应用程序链接到 A 时,它也将链接到 B。将 B 指定为 A 的依赖项与将 B 添加到 A 的源代码不同。
既不是自由特性也不是偶然特性的特性被称为 基本 特性。
当请求具有某些属性的目标时,并且该目标需要某些属性集,则需要找到用于构建的属性集。这个过程被称为 属性细化,由以下规则执行
有时,希望仅对其他属性的特定组合应用某些要求。例如,你使用的编译器之一会发出一个你想通过传递命令行选项来抑制的无用警告。你不希望将该选项传递给其他编译器。条件属性允许你执行此操作。它们的语法是
property ( "," property ) * ":" property
例如,上述问题可以通过以下方式解决
exe hello : hello.cpp : <toolset>yfc:<cxxflags>-disable-pointless-warning ;
该语法还允许在条件中包含多个属性,例如
exe hello : hello.cpp : <os>NT,<toolset>gcc:<link>static ;
目标标识符 用于表示目标。语法是
target-id -> (project-id | target-name | file-name ) | (project-id | directory-name) "//" target-name project-id -> path target-name -> path file-name -> path directory-name -> path
此语法允许将某些元素识别为
为了确定真实含义,将检查指定名称的项目 ID 是否存在,然后检查该名称的主目标是否存在。例如,有效的目标 ID 可能为
a -- target in current project lib/b.cpp -- regular file /boost/thread -- project "/boost/thread" /home/ghost/build/lr_library//parser -- target in specific project
基本原理:目标与项目通过特殊分隔符(不仅仅是斜杠)隔开,因为
目标引用 用于指定源目标,并且还可以另外指定该目标的所需属性。它具有以下语法
target-reference -> target-id [ "/" requested-properties ] requested-properties -> property-path
例如,
exe compiler : compiler.cpp libs/cmdline/<optimization>space ;
将导致链接到 cmdline
库的版本,该版本针对空间进行了优化,即使 compiler
可执行文件是针对速度进行构建的。