术语概要

  本文档概述及约定 YSLib 基本的概念含义,主要用于开发

  一些术语概念适用各种不同的上下文,主要用于开发过程中的设计和规则说明。

  术语以列表形式的条目列出。通过使用元语言语法 <相关范畴/上下文> 标记指示被修饰或被限定的概念的适用范围。不需要消歧义时,省略标记。

通用领域

  除非另行指定,适用于任意上下文;但存在更具体的上下文的特定概念定义时,优先适用后者。

经验语义

  经验语义解释的术语的含义总是假定可被实证,不需要进一步解释。

  元语言中的标记使用经验语义。标记可被本文档中已归类的章节提供。

  本文档中非形式地使用在特定理论中严格定义的、和本章的条目具有逻辑上相容的含义的概念时,不进一步解释。

自指

  自指是概念定义形式上的自我指涉。

举例本章”是关于位置的自指。

  有必要通过自指定义的概念,隐含引入定义内容的过程的循环论证。这些概念的精确内涵和外延依赖经验语义的实证,否则在自然语言语言中可能需要循环论证而失去定义的意义。此处的条目内容(包括链接的外部定义)仅仅供参考,而不是精确的内涵和外延。为简化复杂度,限制自指定义的概念都是名词。

举例 上述注释中,内涵外延约定为以下非自指的概念,因此可依据本文档给出明确的定义来源。

举例 在程序语言理论中,上下文(context) 指形式上可继续补充内容的构造;文档可能非形式地使用和这个含义相容的概念。

  • 实体(entity) :任意被自然语言表达的目标;不需要通过自然语言先验定义;参见经验语义。
  • 语义(semantics) :参见经验语义。
  • 经验(experience) :参见哲学或一般等价的经验语义。
  • 范畴(category) :参见范畴论
  • 态射(morphism) :参见范畴论。
  • 归纳(induction) :一种态射,可操作性参见经验语义。
  • 方法学(methodology) :一个归纳经验得到的范畴;参见哲学或一般等价的经验语义。
  • 方法(method) :方法学的一个子范畴;可操作性参见经验语义。
  • 概念(concept) :参见逻辑学。
  • 上下文(context) :一种概念范畴适用的态射;参见经验语义。

非自指

  包含多个一般领域的概念。

  • <名词> 形式(form) :参见经验语义和数学。
  • <概念> 内涵:参见逻辑学。
  • <概念> 外延:参见逻辑学。
  • <概念> 定义(definition) :确定概念内涵和外延的方法;参见任意一种形式逻辑学。
  • <动词> 抽象(abstracting) :通过经验语义定义概念范畴或集合的方法。
  • <名词> 抽象(abstraction) :<动词> 抽象的结果。
  • <动词> 封装(encapsulating) :从某一个范畴中抽象一个子范畴的方法。
  • <名词> 封装(encapsulation) :<动词> 封装的结果。
  • 规范(specialization) :一种提供在特定上下文中可定义的描述的封装,参见工程学(特别是软件工程学,下同)。
  • 接口(interface) :一种封装,参见工程学。
  • 实现(implementation) :一种封装,参见工程学。
  • 重用(reusing) :参见经验语义和工程学。
  • 不变性(invariance) :满足某种等价关系(自反、传递、对称的二元关系)。
  • 不变量(invariant) :具有不变性的实体。参见数学和契约式程序设计。
  • 状态(state) :可以和其它实体关联的、可在某个上下文中保持变化或不变的实体。同一状态总是保持变化或保持不变。状态变化的含义参见经验语义、数学或另行指定。
    • 可变状态(mutable state) :在某个上下文中满足以下条件的状态:
      • 可能映射到超过一个其它状态。
      • 存在对应的重新配置可变状态映射到不同的其它状态的改变(mutate) 操作。
    • 不可变状态(immutable state) :不是可变状态的状态。
  • <动词> 派生(deriving) :基于重用的操作。
  • <名词> 派生(derivation) :<动词> 派生的结果。

计算机科学

  包含多个关于数学、逻辑学和计算机领域的概念。

  • <动词> 形式化(formalize) :建立数学意义上的严格形式
  • <名词> 形式化(formalization) :建立形式的过程。
  • 形式方法(formal method) :包含形式化的方法
  • <动词> 建模(model) :建立形式化输出的形式。
  • <名词> 模型(model) :建模的结果。
  • 集合(set) :一种数学模型,参见 NBG 集合论
  • (class) :参见 NBG 集合论和范畴论。
  • 真类(proper class) :参见 NBG 集合论和范畴论。
  • 二元关系(binary relationship) :一种基于集合上定义的数学实体。
  • 等价关系(equivalence relationship) :自反的(reflexive)对称的(symentric)传递的(transitive) 二元关系。
  • 偏序关系(paritial order relationship) :自反的、反对称的(asymentric) 且传递的的二元关系。
  • 严格偏序关系(paritial order relationship) :反自反的(irreflexive)、反对称的且传递的的二元关系。
  • 等价类(equivalence class) :等价关系划分集合得到的类。
  • 可计算性(computability) :参见数学。
  • 计算(computation) :由可计算性定义的操作的等价类,可表现为特定的外在的行为(behavior) 。
  • 计算模型(computation model) :描述计算的模型,是对计算建模的结果。
  • 序列(sequence) :有序集合。
  • 形式语义(formal semantics) :使用形式化的方式表达的语义。
  • 形式语言(formal language) : 特定形式化的方式确定的元素的全集。
    • 注释 这也可能作为语言规则对应的某种形式语义。这同时是语言对应的语法的外延。
  • 计算复杂度(computational complexity) :某个形式化计算模型中以有限的正整数作为模型决定的规模(metric) 作为参数的渐进(asymptotic) 性质确定的度量。
    • 时间复杂度(time complexity) :描述步骤规模的计算复杂度。
    • 空间复杂度(space comlexity) :描述存储规模的计算复杂度。
  • 并发(concurrency) :计算的非确定性的(non-deterministic) 组合(composition) 的性质。
    • 并发的(concurrent) :已被并发方式组合的。
  • 并行(parallelism) :确定性的(deterministic) 计算行为蕴含的可提升渐进效率(asymptotic efficiency) 而不改变计算预期的其它行为的性质。
    • 并行的(parallel) :已蕴含并行的。
    • 可并行化的(parallelizable) :允许改变而蕴含并行的。
    • 注释 渐进效率可使用渐进形式的复杂度描述。
    • 注释 一个表达渐进效率的具体例子是大 O 记号(en-US)
  • 二进制(binary) :实数的二进位制表示格式。

规范

  包含提供规范实体定义。

  • 符合性(conformance) :满足规范的实现性质。
  • 要求(requirement) :规范对实现的作为判断符合性的条件。
  • 约束(constraint) :可被形式表达,用于限制和明确行为的规则。不一定使用形式表达。
  • 违反(violation) :对约束指定的条件的不满足。
  • 过时的(obsolesent) :已确认因为存在更合适的选项而建议不继续使用的(接口/特性)。
  • 废弃的(deprecated) :过时的但因为兼容性等原因,暂时保留的、一般可提供替代的接口或特性。
  • 语言:模型或者非形式地其它方式定义的一种接口
  • <语言> 接口(<language> interface) :和表达语义有关的语言的可见的特征。

  包含关于语言的规范的定义。

  • <语言> 实现(<language> implementation):对语言规则中的要求的<非自指> 实现
  • <语言> 人类接口(human interface) :语义仅对人类有意义(内容改变时可以导致语义的差异性),不提供为涉及作为计算模型实现的语言接口。
  • <语言> 机器接口(machine interface) :对机器(或特定语言实现的特定部分)有意义的语言接口。注意不同语言实现组成部分可以不同。
    • 举例C 语言的预处理器,C 源代码中的空白符是机器接口,而对翻译器来说则不是。就源代码而言,机器接口总是人类接口的子集。
  • <语言> 特性(*<language> feature) :作为功能提供的人类接口。
  • 语言规则(language rule) :约定可实现及应被实现的语言接口的描述,可包含语言特性的表达。
  • 语言规范(language specialization) :包含正式的(normative) 的语言规则的集合的规范;或称语言规格说明。
  • 语言实现(language implementation) :语言提供的接口的实现,是语言的表现形式,可以是具体语言实现或抽象语言实现之一。
    • 具体语言实现(concreate language implementation) :能最终完全表达为可预测的物理现象一一对应的表达可计算性的实现,一般应为程序。
    • 抽象语言实现(abstract language implementation) :非具体语言实现的语言实现。形式意义的标准定义的语言属于此类。
  • 派生语言实现(derived language implementation) :派生已有实现的部分或全部得到的语言实现。以下简作“派生实现”。
  • <语言> 实现环境(environment of implementation) :对应特定语言实现的特定不变状态(对机器来说可以是配置项,对人来说不确定,所以一般忽略)的集合。
  • <语言> 互操作(interoperation) :不同的语言实现环境中发生的交互。
  • <语言> 嵌入实现(embedded implemenation) :在现有的其它语言实现上建立的可共享部分实现环境支持互操作的语言实现。
  • 宿主语言(host language) :提供嵌入实现的现有实现中使用的语言。
  • 客户语言(guest language) :嵌入实现中被宿主语言支持实现的语言。
  • 未定义的(undefined) :可能导致违反规范的约束但语言规范同时没有要求提供任何可能影响符合性的保证(如具有诊断消息)的。
    • 注释 表示置于语言规则下的行为等不可预测。
  • 良定义的(well-defined) :明确地非未定义的。
  • 未指定的(unspecified) :规范隐式或显式地允许但不要求唯一确定的至少一个实现选项。
    • 注释 通常允许多种不同的选项;但在特定实现配置下,规则中未指定的选项也可被限制为只有一种可行的选项。
    • 注释 同一个实现或者不同实现可能确定地或非确定地选取不同的选项而不保证表现一致。
  • 由实现定义的(implementation-defined) :取决于各个具体语言实现的,要求有文档说明。
  • 由派生实现定义的(derived-implementation-defined) :取决于各个派生语言实现的,要求除存在默认定义或被派生实现的部分有明确的文档说明。

程序设计语言

  提供上下文 <程序设计语言> ,特别是语言规范的定义。

  主要用例参见 NPL

  • 广义实体:<通用领域> 实体。语言抽象的目标,不另行定义(意义最终取决于自然语言)。
  • 名称(name) :一种特殊的可比较相等的广义实体,专用于和另一个的广义实体关联。
  • <动词> 指称(denote) :名称对广义实体的关联动作。
  • <名词> 指称(denotation) :被名称指称而关联的实体。
  • 实体(entity) :非名称的广义实体。
  • 表示(representation) :以一个符合某种形式的约束的实体指称另一个实体。
  • 符号(symbol) :语言规则允许的不使用其它对象表示的对象。符号可实现名称。
  • 字母表(alphabet) :符号在语言中的全集。
  • 串(string) :可能重复出现的符号的有限序列。
  • 文法(grammar) :描述任意的可形式化的语言规则。
  • 语法(syntax) :以语言中的串作为基本元素,描述语言的字面(literal) 结构模式(pattern) 的语言规则,通常是文法的一部分。
  • 语义(semantics) :非语法的考虑逻辑上的释义(interpretation) 或含义(meaning) 的规则、原理和过程,通常可被语法以外的文法描述并可约束含义的表达。
  • 实例(instance) :具有代表性含义的集合的元素。
  • 代码(code) :任意有限的语言的实例片段组成的语法范畴。
  • 伪代码(pseudo code):抽象语言实现的语言的代码。
    • 注释 习惯上和具体语言实现代码完全一致的代码可以不作为伪代码考虑。
  • 程序(program) :具体语言实现接受的以代码表示的输入,或被变换后对应的输出。
  • 数据(data) :程序处理的一般信息。
    • 注释 除以下的编码外,通常不直接作为代码处理。
  • 编码(encode) :变换数据为确切格式的代码。
    • 注释 格式通常使用语言定义。
  • <名词> 编码(encoding) :经编码得到的结果。
    • 原理 相对被编码的数据,因可预测格式,这可能更容易处理。因此,同时可能被视为数据。
  • 解码(decode) :变换确切格式的代码为数据。
    • 注释 编码和解码可以是对应可逆的。
  • 行为(behavior) :语言实现或在满足符合性的具体语言实现中的程序的外部表现。
    • 基于可操作性考虑,一般仅约束实现的机器接口
    • 注释 程序的行为是具体的计算行为的实例。
  • 计算作用(computational effect) :可被某个形式化计算模型描述的行为。
  • 翻译(translation) :不同语言的程序之间的变换,可作为语言实现的形式。
    • 注释 输入和输出具有相同表示的恒等变换不被视为翻译。
  • IR(intermediate representation ,中间表示):翻译过程中使用的和输入及输出都不同的表示。
  • 翻译器(translator) :实现翻译的程序。
  • 运行(run) :实现程序或组成程序的实体的行为的动作。
  • 加载(load) :运行程序或组成程序的实体时从实现环境取得相关实体的动作,可蕴含创建这些实体的副本或翻译其中的代码到特定形式。
  • 执行(execute) :处理程序或组成程序的实体,使这些实体或实体的副本作为资源被消费而蕴含这些实体被运行,同时可能蕴含消费实现环境的其它资源。
    • 注释 执行强调资源的消费,是运行的子集。资源被消费后不再可用。因此,除非同时蕴含资源的再生(reclaim) ,被执行的同一实体不预期被再次执行。再生资源包括实体加载时翻译或取得副本,及实现环境中补充的替代资源。
  • 解释(interpretation) :通过不依赖显式指定的附加的程序翻译而直接运行表现行为的具体语言实现的形式。
  • 解释器(interpreter) :实现解释的程序。
    • 注释 解释器是翻译器的真子集。
  • 编译(compilation) :通过依赖显式指定的附加的程序翻译而运行翻译的输出表现行为的具体语言实现的形式。
    • 注释 典型的编译以生成 IR 作为附加的程序翻译过程。
  • 编译器(compiler) :实现编译的程序。
    • 注释 编译器是翻译器的真子集。
  • 源语言(source language) :翻译的输入的语言。
  • 目标语言(target language) :编译的输出的语言。
  • 转译器(transpiler) :源语言和目标语言都能作为典型的源语言的翻译器。
    • 注释 或称为源到源翻译器(source-to-source translator)
  • 转译编译器(transcompiler) :源语言和目标语言都能作为典型的源语言的编译器。
    • 注释 或称为源到源编译器(source-to-source compiler)
    • 注释 通常转译器需要明确的 IR ,所以都是转译编译器。
  • 源代码(source code) :源语言编码的代码。
  • <翻译> 目标代码(target code) :目标语言编码的代码。
  • 目标代码(code code) :编译器输出的代码。
    • 注释 编译器输出的目标代码是翻译的目标代码的特例,一般具有二进制编码。
  • 源程序(source program) :形式为作为翻译的输入的源代码程序。
  • 复杂度(complexity) :以程序的规模作为参数的关于程序的直接执行的计算复杂度
  • 元语言(metalanguage) :描述其它语言的语言。
  • 对象语言(object language):被元语言操作或实现的语言。
  • 元编程(metaprograming) :使用元语言编程。
  • 反射(reflection) :元语言和对象语言相同的元编程。
  • 具现(reification) :在对象语言中以数据模型作为关联实体以表示程序的语义。
  • 诊断(diagnostics) :明确的对特定预期或非预期执行的行为的响应的总和。
  • 诊断消息(diagnostic message) :用于和用户交互的表现诊断的告知及提示。
  • 未定义行为(undefined behavior) :未定义的行为。
  • 良定义行为(well-defined behavior) :良定义的行为。
  • 未指定行为(unspecified behavior) :未指定的行为。
    • 注释 由实现选取语言规范中可能允许的指定行为的不确定选项,这些选项可能由显式或隐式的语言规则确定。
    • 注释 推论:由实现定义的行为是未指定行为。在本文档中,为最小化依赖,不在正式规则中明确这些关系。
  • 语言特性(language feature) :语言提供的功能接口,可以是具体语言特性或抽象语言特性之一。
  • 具体语言特性(concrete language feature) :完全没有派生语言实现定义的语言特性。
  • 抽象语言特性(abstract language feature) :非具体语言特性的语言特性。
  • 外部环境(external environment) :和程序及被翻译的程序没有交集的和实现环境无关的状态。
  • 外部表示(external representation) :具有特定形式的用于和外部环境交互的表示。
  • 内部表示(internal representation) :非外部表示的表示。
  • 可编程性(programmability) :允许使用程序提供实现的性质。
  • API(application programming interface ,应用程序编程接口):提供可编程性以实现程序之间交互的接口。
  • ABI(application binary interface ,应用程序二进制接口):提供可编程性以实现二进制编码的程序之间交互的接口。
    • 注释 ABI 可以是明确指定了二进制形式的程序之间的 API ,也可以是不依赖二进制编码实现的程序的 API 的实现细节。

计算机体系结构

  提供上下文 <计算机体系结构> ,特别是作为语言实现补充的定义。

  • 指令(instruction) :构成代码的具有有限的表示的基本单元,其表示一般具有二进制编码。
    • 注释 指令序列可作为一种目标代码的形式,可实现程序
    • 注释 典型地,指令是通过特定的机器的实现支持,即机器指令(machine instruction) 。这些机器可以是物理的(physical) 或虚拟的(virtual) 。一般物理的机器由特定的机器硬件直接提供指令功能实现的支持,而虚拟的机器指通过软件方式在其它硬件的基础上提供适配支持。
  • 指令集(instruction set) :通过指令的集合提供可编程功能的接口
    • 注释 指令集是提供接口为目的设计的具有相近格式的指令构成的统一规范,而非任意指令的集合。
  • ISA(instruction-set architecture ,指令集架构):依赖和蕴含特定指令集设计的程序之间交互的接口,包括指令集和实现环境的相关假设。
    • 注释 实现环境假设可蕴含明确的 ABI 和指令集以外的配置。
    • 注释 ISA 可作为具体语言实现的一部分。
    • 注释 ISA 可为特定的物理的或虚拟的机器设计,而不需要具有适应不同机器的可移植性(potability)
    • 注释 典型地,ISA 是软件实现可编程性的最底层次的机器接口;更低层次的接口通常依赖不能被纯软件方式访问的机器实现细节。但这并非绝对。
  • 地址(address) :在实现中指定实体位置的编码
  • 地址空间(address space) :映射到地址的操作中,地址的陪域(codomain) 。
  • 寻址(addressing) :在地址空间中确定实体关联的地址。
  • CPU(central processing unit,中央处理单元) :带有运算部件和控制部件,允许对物理计算资源寻址的物理 ISA 的通用实现。
    • 注释 CPU 是 ISA 的主要实现。
    • 物理的实现又称为中央处理器。强调具有缓存(cache) 时,又称为中央处理机。
    • 除非另行指定,讨论特定的(物理)机器的体系结构时,默认指 CPU 支持的 ISA 。
  • GPU(graphics processing unit,图形处理单元):带有图形处理功能的物理 ISA 的专用实现。
    • 注释 GPU 是非通用 ISA 的常见主要实现。
    • 物理的实现又称为图形处理器或显示核心,因其主要以处理 2D/3D 图形计算而得名。
    • 但 GPU 也能适用于比 CPU 更(计算时间和能效意义上)高效的特定计算任务,不一定和图形处理相关,即 GPGPU
    • 为通用的计算加速的类似设备仍可能被称为 CPU ,即便其中没有光栅化单元(rasterization unit) 或最后用于输出的 ROP(渲染输出单元,render output unit ),但保留了和图形处理流水线共用的物理部件,如支持着色器(shader) 的硬件实现。

项目管理

  提供上下文 <项目>

  主要用例参见版本库中的项目文档 doc/ProjectRules.txt

  • 涉众(skateholder) :项目关联的各方的主体。
  • 角色(role) :依据项目过程中起到的作用,对项目涉众实行一些附加归类。
    • 注释 项目的角色同时可用于项目阶段的描述中。
  • 用户(user) :使用项目输出的项目涉众。
  • 维护者(maintainer) :决定项目中各个部分的内容的用户。
    • 注释 维护者可参与和维护部分相关的项目决策。
  • 开发者(developer) :参与程序库和开发工具的功能修改的用户。
    • 注释 开发者可参与公开的构建过程以完成这些修改。
  • 最终用户(end user) :独立为项目过程的用户。
    • 注释 最终用户可以不参与提前(ahead-of-time) 构建的项目过程。基于认知需求的差异可能需要从一般用户中单独区分。

依赖管理

  项目管理的客体被分解为特定关联的依赖项。任意两个依赖项之间存在反对称传递二元关系称为依赖关系严格依赖关系是反自反的依赖关系。

  依赖项和依赖项之间的严格依赖关系统称为依赖(dependency)

依赖引用

  因为依赖关系的传递性,多个依赖关系可能存在无法满足严格依赖关系的情形,即循环依赖(cyclic dependency) 。这导致以确定的顺序解析依赖不可行,增加维护成本。

  为了避免一定层次上的循环依赖,以该层次内组件为顶点的依赖关系的关系图应明确组织为有向无环图。 在最简单情况下依赖关系可退化为线性顺序依赖。

内部依赖和外部依赖

  项目中的组成部分之间的依赖称为内部依赖,其它依赖为外部依赖

源代码

  源代码用于生成指定目标代码。

  通常源代码以文件形式保存,即源代码文件(source code file) ,简称源文件(source file) 。

版本库

  项目使用的版本控制系统(version controlling system) 具有存储库(repository) 作为持久存储实体,即版本库。

  当前使用的主要版本控制系统为 Mercurial 。因为是分布式版本控制,也用于直接分发源代码。

  每个文件系统上存储的版本库实例中,.hg 目录存储版本库元数据。

设计和模型

环境

  程序中的某一部分的外界称为环境(environment)。根据限定程序的范围,可以有更确切的定义,如实现环境(对一类语言实现而言)、运行时环境(对共享实现环境的一类程序而言)。

  一般地,实现环境可以分为独立环境(freestanding environment)宿主环境(hosted environment) ,区分依据为是否依赖宿主(对部署在单一计算机上的实现,一般指操作系统)的支持。因此,环境有时指操作系统及其提供的外部服务的集合。

  一些语言,如 ISO C 和 ISO C++ ,可以同时支持宿主环境和独立环境的实现,对应独立实现(freestanding impementation)宿主实现(hosted impementation)

平台

  环境中决定程序适用环境的被依赖的特定资源集合称为平台环境(platform environment),简称平台(platform)。平台的典型例子有:

  • 运行时支持的 ISA
  • 操作系统和 ABI

  平台的内涵是资源的集合,其构成并非任意。构成平台的特定准则应使之保持相对的稳定和可预期,即可配置;即平台是名义的(nominal) 可配置的资源集合。

  若平台包含的资源是已知的,则不需要平台的观念,分析其资源子集(即便不构成平台)即可解决几乎平台抽象涉及的所有技术问题(同时这也是定义一个具体平台的基础)。但在简化资源集合的全局性质分析(如比较资源配置方案)和名义抽象以隐藏实现(如为开发者提供预设环境集合)的应用角度上,平台仍有被单独讨论的意义。

兼容性和可移植性

  若一个依赖项对应的平台可以替换,则此依赖项和此平台兼容(compatible)兼容性(compatibility) 是平台兼容的二元关系。兼容性不是一种等价关系,因为不保证传递。

  替换平台的过程称为移植(porting) 。移植的可行性称为可移植性(portability)

  兼容任意平台的依赖项被称为是平台中立(platform-neutral) 的。

  当平台中立的依赖项的依赖能被自动满足而不需要考虑时,是平台无关(platform-independent) 的。平台中立实质蕴含平台无关。

依赖和外延

  若平台之间不出现平台的实现(如开发语言的实现)和环境自身的相互依赖,则这些平台相互独立(independent) 。总是保持相互独立的一组平台称为独立平台(independent platforms) 。每一组独立平台保证可以相对于其它独立平台分离开发和测试。

  注意以上术语和 ISO C 和 ISO C++ 定义的宿主实现(hosted implementation)独立实现(freestanding implementation) 的关联和区别。

  典型的应用场景约定以下类型的平台:

  • 构建平台(build platform) :运行开发环境的平台。
  • 宿主平台(host platform) :运行构建平台输出代码的平台。
  • 目标平台(target platform) :运行最终目标代码的平台。

  若宿主平台和构建平台一致,称为本机构建(native build) ;否则,称为交叉构建(corss build)

  通常构建工具在本机构建时提供对构建平台的检查以确定自身是否能够运行;交叉构建环境需要显式指定。

  目标平台通常和宿主平台一致。指定目标平台的理由是,存在最终不一定在宿主平台上运行的程序,其运行的环境可能需要宿主平台不保证支持的特性,这典型地包括:

  • 构建的程序自身是生成其它程序的程序,如编译器和链接器。这些程序生成的平台是目标平台,不需要和它们的宿主平台相同。
  • 构建的程序可以在宿主平台上运行,但在其它平台上具有更完全的特性集。后者被作为目标平台。

注意 此处的宿主平台具有相对意义,不一定脱离被运行的目标平台。一个宿主平台通常自身是宿主实现平台,但这点不被保证。

模拟和仿真

  模拟(emulation) 指适配和运行为不同平台设计的程序,广义上包括以下两类:

  • 环境模拟(environment emulation) :使用模拟器(emulator)或虚拟机(virtual machine) 等作为宿主平台的程序,模拟运行环境的通用解决方案。
  • 程序模拟(program emulation) :直接以运行时环境适配层嵌入宿主平台运行时,在具体程序中提供类似被模拟的目标平台的具体特性和接口。

  运行模拟程序的环境和被模拟环境分别是宿主平台和目标平台。

  注意虚拟机在这个意义下是广义的模拟器,但一般仍然分别对待。

  环境模拟和程序模拟的主要差异为是否独立的、专用的宿主平台程序作为中介以维护目标平台和宿主平台的隔离。

  在一般意义上,仿真(simulation) 指对需要分析的问题建立的模型的过程、方法和机制,在软件工程以外也被称为模拟,如计算机模拟(computer simulation) 。对于以计算机系统为目标的仿真,建立的模型可以是具体的实物(包括硬件和软件),称为仿真器(simulator) 。以软件接口为主要操作方式实现的仿真器同时实现了环境模拟,但侧重不同:精确重现需要分析行为,而非实用的功能等价性和体系中的可替换性。

平台配置

  实际的平台实现可能复用部分实现,配置之间可存在某种构成依赖关系的偏序关系(如继承关系)。这些在项目中所有被配置的平台称为公共平台(common platform) ,其中能对应生成输出的称为具体平台(concrete platform) ,否则为抽象平台(abstract platform)

  对一个平台配置,程序可提供更多的子配置共用现有的相同的配置。子配置可继续对平台特性具体特化,而对原始配置的用户程序隐藏细节。

  普遍适用于一般功能配置也可被作为平台配置的一部分而作为子配置。

注释 例如,多线程和非多线程版本、调试和非调试版本可作为平台配置的功能子配置。

原理 尽管功能配置提供的特性可能是普遍的,但它的实现依赖的特性不都在每个平台中存在,而可能需要一定程度的模拟和仿真,或可选地提供部分特性。提供功能子配置可把这些特性作为次要的实现细节,和原始的平台上的更显著特性隔离。

  若存在这样的子配置,应当满足:

  • 这些子配置应当在每个部署的用户程序的依赖中保持唯一,即一个环境中不能同时依赖不同的子配置的程序映像。
    • 原理 这样不但不需要保持子配置之间的 ABI 兼容性,同时 API 也可以存在不兼容(而不仅仅是调试符号等附加元数据的差异)。
  • 相应地,依赖不同子配置的用户程序也具有对应的子配置。用户程序可以仅提供其中的部分子配置的程序映像。
    • 原理 对每个子配置需要提供单独的依赖路径以避免冲突,因此一般不能在同一个部署中直接复用不同子配置的程序映像。为了避免不必要的资源占用,支持用户程序仅提供部分子配置(而非所有子配置的映像)是必要的。
  • 除非另行指定,被复用的公开库的程序名称在不同子配置中应当存在差异。
    • 原理 尽管不会同时被一个用户程序依赖,每个部署中,不同的子配置的程序映像通常仍需共存。在名称上要求差异允许文件系统直接支持这种策略。

平台标识

  不同平台可以标识符加以区分。由于平台受到不同环境因素决定的正交性,通常此类标识符可以分解为表示这些正交环境的标识符的元组形式,用 - 等字符分隔。

  一种常用的方式是 GNU 构建系统的系统类型,经典表示方式为三元组(triplet) ,或其省略形式:

  • 一般包括体系结构(architecture) 、系统厂商(system vendor) 和系统软件环境。
  • 第一项不可省略,之后的项可省略。
  • 体系结构一般指定 CPU 要求的最小 ISA
  • 系统厂商指集成平台的环境厂商。
  • 系统软件环境保证满足 ABI 要求,可以包含操作系统及本机语言运行时实现的名称。

  确定为宿主环境时,系统软件同时指定操作系统和运行时环境而拆分为两项,三元组扩充为四元组,如 Gentoo 使用的 CHOST

  在不够充分体现平台的必要差异(尤其是体系结构相关的配置)时也可通过自行定义标识符并指定与三元组的对应关系,如 Debian multiarch

  系统类型用来提供一定程度的兼容(替换和互操作):

  • 系统类型代表了系统厂商的预设的配置集合,因此可提供符合相对上的(事实)标准的构建和运行环境。
  • 这种兼容性有时会被过度依赖,乃至被误认为完全的 ABI 兼容:
    • 系统类型不保证涵盖所有 ABI 细节,满足相同的系统类型的程序实例之间不一定符合完全相同的 ABI 而可相互替换或互操作,即原则上即不保证完全的 ABI 兼容。
      • 原理 实现的差异原则上不适合或无法通过系统类型区分。否则,系统类型事实上需要任意地长以涵盖不同细节,而会导致程序部署环境的碎片化,使维护兼容性的原始目的失去主要意义。
    • 一个主要实例:不同构建工具链生成的二进制程序之间不总是保证完全的 ABI 兼容。
      • 同一个版本的同一工具链通过某些构建选项即可能构建出不能保证 ABI 兼容的二进制程序映像。
        • 例如,GCC 使用 -m 前缀选项可能影响 ABI 。
      • 即便使用工具链发行版固定的默认预设选项,不同版本工具链在设计上不能完全保证二进制兼容性。
        • 例如,为兼容 ISO C++11 中关于 std::basic_stringstd::listAPI 改动,GCC 5 显式提供不同的 ABI 配置 而在支持这些改动的配置上[放弃对原有 libstdc++ 的 ABI 兼容保证。
    • 相同的系统类型可以对应不同的依赖集合,已被作为实用的维护兼容性的方法。
      • 这种差异通常隐藏在系统库之下,此时提供不同的二进制兼容映像可以在部署时对依赖系统库的程序隐藏这些差异。
    • 注释 现代 Microsoft Windows(基于 Windows NT 执行体)是应用包括这类兼容性在内的多种策略的一个典型实例:
      • 隐藏二进制差异的主要实例是 Microsoft Windows NT 的 Win32 和 POSIX 子系统,用户程序通过链接到不同的子系统 DLL ,可共享上层 ABI 。
      • Cygwin 是一个类似的 POSIX 子系统替代实现,其用户程序当前默认依赖系统库 cygwin1.dll
      • Windows Subsystem for Linux (WSL) 则不是这种兼容性的实例。
        • 因为映像格式的差异,它的用户空间程序使用的系统类型更接近 x86_64-pc-linux(具体系统类型取决于安装的发行版;典型地是 x86_64-pc-linux-gnu )。
        • 部署 WSL 环境需要涉及一整套不同系统类型的二进制映像,仅在子系统的内部实现存在(对 Windows NT 执行体而言的)隐藏实现差异的情形。
      • 不涉及子系统但同样通过 DLL 隐藏二进制的实例是隐藏系统库的版本差异:不同版本的 C 运行时(CRT) 和 Microsoft VC++ 运行时库可以在一个 Windows 系统实例中共存。
        • 特别地,MSVCRT 和 UCRT 作为不同的 CRT ,可在同一个系统映像中安装,并作为同一个系统类型的不同实现提供。
        • 同时,不同的 CRT 可具有不同的工具链支持。
        • 不同版本的运行时中每个子配置(多线程和非多线程版本、调试和非调试版本)共用相同的配置,在此不视为存在差异。
        • CRT 的多版本部署和其它一些系统中 libc 显式影响系统类型不同。
          • 原理 尽管同样是作为语言实现的一部分部署的系统库(至少在通常以此为由取得许可证豁免的意义上),仅有后者通常是影响整个系统部署的库,而不适合通过相同的系统类型提供二进制不兼容的版本。否则,这会使整个系统中的几乎所有二进制程序映像之间都不具有二进制兼容性,而无法通过通常的机制共享二进制代码。
      • MSYS2 提供的不同环境 是体现上述所有各种不同兼容性方式的一个复杂实例。
        • 其中,MSYS2 环境基于 Cygwin ,是通过类似子系统 DLL 部署的兼容层,其用户程序当前默认依赖系统库 msys-2.0.dll
        • 其余环境被视为原生的 Win32 应用,使用 Win32 子系统。按体系结构归类分组,每一组内可存在原生的共用相同系统类型的不同实现。
          • 例如,/mingw64/clang64/ucrt64 中部署的二进制程序共享系统类型 x86_64-w64-mingw32
          • 其中 /mingw64 中的程序依赖的 CRT 和另两种共享 x86_64-w64-mingw32 的环境不同,而 /clang64 中的程序依赖的 C++ 运行时库也和另两种环境不同。
      • 上述的这些配置仍然没有穷尽系统库的 ABI 的差异。
      • 包括上述 MSYS2 中的每个环境的使用 GCC 的不同发行版都预设了具体的内部依赖,如:
        • MSYS2 中,x86_64-w64-mingw32 环境使用 SEH 异常处理模型,其用户程序当前默认依赖系统库 libgcc_s_seh-1.dll
        • MSYS2 中,i686-w64-mingw32 环境使用 Dwarf2 线程处理模型,其用户程序当前默认依赖系统库 libgcc_s_dw2-1.dll
        • 一些发行版如 MinGW-builds 默认使用 SjLj 异常处理模型,其用户程序当前默认依赖系统库 libgcc_s_sjlj-1.dll
        • MSYS2 和大多数其它 MinGW-w64 发行版中长期使用 POSIX 线程模型提供较完善的 C++ 标准库线程特性实现,当前使用 winpthreads ,其用户程序当前默认依赖系统库 libwinpthread-1.dll
        • 预期可在现代环境中替代 winpthreadsmcfgthread上游的修改已被讨论,使用新的线程模型 mcf ,其用户程序会依赖不同的系统库。
      • 实现系统库时,可依赖非系统库 API 。通常,系统库可直接在运行时依赖 Windows NT 执行体。系统库之间也可存在其它单向的内部依赖。这些情形下,系统库自身不是符合环境要求的程序。
        • 例如,mcfgthread 依赖非 Win32 API ,自身不是严格意义的 Win32 程序(尽管构建时仍在运行于 Win32 子系统的假定下链接)。
        • POSIX 子系统依赖 Win32 系统。
  • 为了避免兼容性保证过程的复杂性,除非另行指定,关于系统类型:
    • 可标识通过源代码部署的单一配置。构建支持和其它外部环境应当被文档明确。
    • 避免认为其它形式部署的唯一依据。特别地,支持可共享相同二进制部署的平台子配置

  除非另行指定:

  • 本项目的文档描述使用和三元组兼容的方式指定平台标识的基本形式。
  • 若同一个平台配置存在多个不同的标识符,默认使用以下规则确定:
  • 注释 通常不使用 Clang 的三元组
    • 原理 尽管形式上更清晰,<sys>-<abi> 的划分实际使之成为四元组而非三元组,这种明确划分不总是符合现实的复杂需求。
      • 这在关于 ABI 兼容的不明确性和歧义更加显著。这类不一致对适配更多不在现有清单上的平台更加困难,特别是未指定 <vendor> 时。
        • 注释 一个歧义的例子:gnu 在 Linux 上特指 glibc ,而在 Windows 上却指 libstdc++ 代表的 Itanium C++ ABI 实现。后者的 C 运行时库(通称 CRT )却和 msvc 兼容。
      • 和 GNU guess 不同,Clang 三元组使用的情形相当有限,甚至长期以来并不具有用户文档中明确的列表或检查规则
      • 默认 <unknown> 但不一定在清单中被排除。这种随意性引起一些解析和理解上的困难。
        • 注释 在清单中滥用 <unknown> 的大量(却不是每个)例子可在 rustc --print target-list 的输出中找到。例如,通常读者(和系统维护者)难以理解:为何存在 wasm32-unknown-emscriptenwasm32-wasi 的同时还有 wasm32-unknown-unknown 而非 wasm32-unknown
  • 具体构建过程可按需不同形式的标识符。
    • 原理 平台配置不一定通过系统类型描述。
      • 注释 例如,cmake -G 支持的标识依赖生成系统的配置,而非运行程序的系统类型。
    • 原理 在不需要关心系统类型中各个组成部分的情形,其它的平台标识符可提供更简单明确的替代。
      • 注释 cmake -G clang --print-targets 的结果是一个实例。

多平台构建

  构建系统中可能涉及多个平台。

  运行构建系统的环境和被构建的程序的环境不需要相同,对应的平台分别是宿主平台目标平台 。宿主平台和目标平台相同时称为本机(native) 构建;不同时称为交叉(cross) 构建。

  多个构建过程可能串联组成更大的构建过程。不同构建过程存在输出和输入之间的依赖。此时,前一过程输出的目标平台需要兼容于后一过程作为输入的宿主平台,否则无法直接运行。典型情况下这些平台是相同的,但也可以存在平台之间自身保证二进制互操作兼容性(如支持 x86_64 的体系结构上混用 i686 和 x86_64 )的情况。

  一些构建系统如 GNU 工具链使用更复杂的术语,单独引入构建(build) 平台。为确保一般性并简化模型,本文档不要求单独使用这个概念,而默认构建平台是第一级构建过程(即 GNU autoconf 的“配置”)的宿主平台。