文件元数据

moz.build 文件 提供了一种机制,用于将元数据附加到文件。本质上,您定义了一些要设置在文件或文件模式上的标志。稍后,某些工具或过程会查询附加到目标文件的元数据,并使用这些数据进行智能操作。

定义元数据

文件元数据是通过在 moz.build 文件中使用 文件子上下文 来定义的。例如:

with Files('**/Makefile.in'):
    BUG_COMPONENT = ('Firefox Build System', 'General')

此工作示例表示,*对于此目录下(包括此目录)每个目录中的所有 Makefile.in 文件,将 Bugzilla 组件设置为 Firefox 构建系统 :: 常规*。

有关更多信息,请阅读 文件文档

如何读取元数据

Files 元数据是在 文件系统读取模式 中提取的。

读取首先指定一组您感兴趣的元数据文件。对于每个文件,文件系统都会遍历到源目录的根目录。在此遍历过程中遇到的任何 moz.build 都被标记为与该文件相关。

假设您有以下文件系统内容

/moz.build
/root_file
/dir1/moz.build
/dir1/foo
/dir1/subdir1/foo
/dir2/foo

对于 /root_file,相关的 moz.build 文件仅为 /moz.build

对于 /dir1/foo/dir1/subdir1/foo,相关的文件为 /moz.build/dir1/moz.build

对于 /dir2,相关的文件仅为 /moz.build

获得相关 moz.build 文件列表后,将评估每个 moz.build 文件。首先是根 moz.build 文件,最后是叶级文件。这遵循 文件系统读取模式 的规则,其中已评估的 moz.build 文件集由文件系统内容控制,而不是 DIRS 变量控制。

其元数据正在解析的文件映射到一组 moz.build 文件,这些文件又会计算出一系列上下文。对于文件元数据,我们只关心其中一个上下文:Files

我们从一个空的 Files 实例开始,以表示该文件。当我们遇到一个*文件子上下文*时,我们会查看它是否适合此文件。如果是,我们会应用其值。此过程会重复,直到所有*文件子上下文*都已应用或跳过。最终状态的 Files 实例用于表示此特定文件的元数据。

这可能有助于可视化。假设我们有两个 moz.build 文件

# /moz.build
with Files('*.cpp'):
    BUG_COMPONENT = ('Core', 'XPCOM')

with Files('**/*.js'):
    BUG_COMPONENT = ('Firefox', 'General')

# /foo/moz.build
with Files('*.js'):
    BUG_COMPONENT = ('Another', 'Component')

查询文件 /foo/test.js 的元数据将显示 3 个相关的 Files 子上下文。它们按如下方式进行评估

  1. /moz.build - Files('*.cpp')/*.cpp 是否与 /foo/test.js 匹配?**否**。忽略此上下文。

  2. /moz.build - Files('**/*.js')/**/*.js 是否与 /foo/test.js 匹配?**是**。将 BUG_COMPONENT = ('Firefox', 'General') 应用于我们。

  3. /foo/moz.build - Files('*.js')/foo/*.js 是否与 /foo/test.js 匹配?**是**。应用 BUG_COMPONENT = ('Another', 'Component')

在执行结束时,我们有 BUG_COMPONENT = ('Another', 'Component') 作为 /foo/test.js 的元数据。

看待文件元数据的一种方法是将其视为数据结构的堆栈。与给定文件相关的每个 Files 子上下文都应用在先前状态的顶部,从空状态开始。最终状态获胜。

最终确定值

Files 子上下文评估的默认行为是在旧值的顶部应用新值。在大多数情况下,这会导致预期行为。但是,在某些情况下,这可能不是您想要的。因此,有一种机制可以*最终确定*或*冻结*值。

最终确定值对于您希望阻止通配符匹配覆盖先前设置的值的场景很有用。这对于一次性文件很有用。

Makefile.in 文件为例。构建系统模块策略规定 Makefile.in 文件是 Build Config 模块的一部分,应由该模块的同行进行审查。但是,源代码树中的许多目录中都存在 Makefile.in 文件。如果没有最终确定,则 *** 通配符匹配规则将匹配 Makefile.in 文件并覆盖其元数据。

值的最终确定是通过在 Files 子上下文中设置 FINAL 变量来执行的。有关更多信息,请参阅 文件文档

这是一个使用 Makefile.in 文件的示例,展示了如何最终确定 BUG_COMPONENT 值。

# /moz.build
with Files('**/Makefile.in'):
    BUG_COMPONENT = ('Firefox Build System', 'General')
    FINAL = True

# /foo/moz.build
with Files('**'):
    BUG_COMPONENT = ('Another', 'Component')

如果我们查询 /foo/Makefile.in 的元数据,则两个 Files 子上下文都与文件模式匹配。但是,由于 BUG_COMPONENT/moz.build 标记为已最终确定,因此 /foo/moz.build 中的赋值被忽略。 BUG_COMPONENT 的最终值为 ('Firefox Build System', 'General')

这是另一个示例

with Files('*.cpp'):
    BUG_COMPONENT = ('One-Off', 'For C++')
    FINAL = True

with Files('**'):
    BUG_COMPONENT = ('Regular', 'Component')

对于除 foo.cpp 之外的所有文件,bug 组件将解析为 Regular :: Component。但是,foo.cppOne-Off :: For C++ 值保留了下来,因为它已最终确定。

重要

FINAL 仅应用于上下文中定义的变量。

如果您想将一个变量标记为已最终确定,但希望另一个变量保持可变,则需要使用 2 个 Files 上下文。

定义元数据的指南

通常,在源代码树根目录中定义的值是通用的,并且在叶子方向上变得更具体。例如,/browserBUG_COMPONENT 可能是 Firefox :: General,而 /browser/components/preferences 将列出 Firefox :: Preferences